blob: 5e221b3b19cd8a4f6ee77013ea977552bdd44ca7 [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <cstring>
#include "daemon/connector.h"
#include "daemon/daemon.h"
#include "echo.h"
#include "gflags/gflags.h"
#include "perfd/perfd.h"
#include "proto/common.pb.h"
#include "utils/current_process.h"
#include "utils/daemon_config.h"
#include "utils/device_info.h"
#include "utils/file_cache.h"
#include "utils/fs/path.h"
#include "utils/log.h"
#include "utils/socket_utils.h"
#include "utils/termination_service.h"
#include "utils/trace.h"
DEFINE_bool(experimental_pipeline, false, "Use unified pipeline");
DEFINE_bool(profiler_test, false, "Run profiler test");
DEFINE_string(config_file, profiler::kDaemonConfigDefaultPath,
"Path to daemon config file");
DEFINE_string(connect, "", "Communicate with an agent");
void RegisterTransports(profiler::Daemon* daemon) {
if (profiler::Perfd::Initialize(daemon) != 0) {
profiler::Log::E("Failed to initialize perfd");
}
// Initializing the agent to handle daemon commands. This is only needed if
// we want the daemon to handle commands. If we only want the agent to handle
// commands then we do not need to do this step.
demo::Echo::Initialize(daemon);
}
int main(int argc, char** argv) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
profiler::TerminationService::Instance();
// If directed by command line argument, establish a communication channel
// with the agent which is running a Unix socket server and send the arguments
// over. When this argument is used, the program is usually invoked by from
// GenericComponent's ProfilerServiceImpl::AttachAgent().
if (!FLAGS_connect.empty()) {
if (profiler::ConnectAndSendDataToPerfa(FLAGS_connect)) {
return 0;
} else {
return -1;
}
// Note that in this case we should not initialize various
// components as the following code does. They create threads but the
// associated thread objects might be destructed before the threads exit,
// causing 'terminate called without an active exception' error.
}
profiler::SteadyClock clock;
profiler::DaemonConfig config(FLAGS_config_file);
profiler::EventBuffer buffer(&clock);
profiler::FileCache file_cache(FLAGS_profiler_test
? getenv("TEST_TMPDIR")
: profiler::CurrentProcess::dir());
profiler::Daemon daemon(&clock, &config, &file_cache, &buffer);
RegisterTransports(&daemon);
if (profiler::DeviceInfo::feature_level() >= 26 &&
config.GetConfig().common().socket_type() ==
profiler::proto::CommonConfig::ABSTRACT_SOCKET) {
// For O and newer devices, use a Unix abstract socket.
// Since we are building a gRPC server, we need a special prefix to inform
// gRPC that this is a Unix socket name.
std::string grpc_target{profiler::kGrpcUnixSocketAddrPrefix};
grpc_target.append(config.GetConfig().common().service_socket_name());
daemon.RunServer(grpc_target);
} else {
// For legacy devices (Nougat or older), use an internet address.
daemon.RunServer(config.GetConfig().common().service_address());
}
return 0;
}