From 2eed130607109075ddf07df83eb82361e295360a Mon Sep 17 00:00:00 2001 From: Pawan Wagh Date: Thu, 8 Feb 2024 20:53:42 +0000 Subject: Add --all to record_binder Adding --all argument to start and stop commands. This will start recording all the binders which are listed with defaultServiceManager Test: record_binder start --all Test: record_binder stop --all Bug: 295220956 Change-Id: I5b0e754fa26bf2a89693f599eef121b8929b3755 --- analyzer/analyzerMain.cpp | 111 +++++++++++++++++++++++++++++++--------------- 1 file changed, 76 insertions(+), 35 deletions(-) diff --git a/analyzer/analyzerMain.cpp b/analyzer/analyzerMain.cpp index e5e61285..f6f3564d 100644 --- a/analyzer/analyzerMain.cpp +++ b/analyzer/analyzerMain.cpp @@ -30,18 +30,32 @@ using android::NO_ERROR; using android::sp; using android::status_t; using android::String16; +using android::String8; using android::aidl::Analyzer; using android::base::unique_fd; using android::binder::debug::RecordedTransaction; using std::string; - namespace { static std::atomic_uint gCtrlCCount = 0; static constexpr unsigned kCtrlCLimit = 3; static const char kStandardRecordingPath[] = "/data/local/recordings/"; -status_t startRecording(const sp& binder, const string& filePath) { +string getRecordingPath(const string& serviceName) { + // Service names may contain '/', replace them with '.' to avoid interpreting as path + string filename = serviceName; + std::replace(filename.begin(), filename.end(), '/', '.'); + return kStandardRecordingPath + filename; +} + +status_t startRecording(const string& serviceName) { + sp binder = + android::defaultServiceManager()->checkService(String16(serviceName.c_str())); + if (binder == nullptr) { + return android::BAD_VALUE; + } + + auto filePath = getRecordingPath(serviceName); if (auto mkdir_return = mkdir(kStandardRecordingPath, 0666); mkdir_return != 0 && errno != EEXIST) { std::cout << "Failed to create recordings directory.\n"; @@ -87,14 +101,20 @@ status_t startRecording(const sp& binder, const string& filePath) { } } -status_t stopRecording(const sp& binder) { +status_t stopRecording(const string& serviceName) { + sp binder = + android::defaultServiceManager()->checkService(String16(serviceName.c_str())); + if (binder == nullptr) { + return android::BAD_VALUE; + } + if (status_t err = binder->remoteBinder()->stopRecordingBinder(); err != NO_ERROR) { std::cout << "Failed to stop recording with error: " << err << '\n'; return err; - } else { - std::cout << "Recording stopped successfully.\n"; - return NO_ERROR; } + + std::cout << "Recording stopped successfully.\n"; + return NO_ERROR; } void printTransaction(const RecordedTransaction& transaction) { @@ -142,7 +162,8 @@ void incrementCtrlCCount(int signum) { } } -status_t listenToFile(const string& filePath) { +status_t listenToFile(const string& serviceName) { + auto filePath = getRecordingPath(serviceName); unique_fd listenFd(open(filePath.c_str(), O_RDONLY)); if (!listenFd.ok()) { std::cout << "Failed to open listening file with error: " << strerror(errno) << '\n'; @@ -229,45 +250,70 @@ const AnalyzerCommand helpCommand = {helpCommandEntryPoint, "Show help informati const AnalyzerCommand listCommand = {listAvailableInterfaces, "Prints a list of available interfaces.", "", ""}; +status_t startRecordingAllBinders() { + auto services = android::defaultServiceManager()->listServices(); + for (auto service : services) { + std::string serviceName = String8(service.c_str()).c_str(); + // Print failed service name. Don't exit early because it would leave the previous successful + // services recording. + if (status_t result = startRecording(serviceName); result != NO_ERROR) { + std::cout << "Failed to start binder recording on service : " << service << std::endl; + } + } + + return NO_ERROR; +} + status_t startCommandEntryPoint(int argc, char* argv[]) { if (argc != 3) { helpCommandEntryPoint(argc, argv); return android::BAD_VALUE; } - sp binder = android::defaultServiceManager()->checkService(String16(argv[2])); - if (binder == nullptr) { - helpCommandEntryPoint(argc, argv); - return android::BAD_VALUE; + string startOption = argv[2]; + if (startOption == "--all") { + return startRecordingAllBinders(); } - string filename = argv[2]; - std::replace(filename.begin(), filename.end(), '/', '.'); - auto filePath = kStandardRecordingPath + filename; - - return startRecording(binder, filePath); + return startRecording(startOption); } -const AnalyzerCommand startCommand = { - startCommandEntryPoint, "Start recording Binder transactions from a given service.", - "", " \tService to record. See 'dumpsys -l'"}; +const AnalyzerCommand startCommand = {startCommandEntryPoint, + "Start recording Binder transactions from a given service. " + "Use --all to start recoding all binders.", + ", --all", + " \tService to record. See 'dumpsys -l'"}; + +status_t stopRecordingAllBinders() { + auto services = android::defaultServiceManager()->listServices(); + for (auto service : services) { + std::string serviceName = String8(service.c_str()).c_str(); + // Print failed service name. Don't exit early because it would leave the other recordings on. + if (status_t result = stopRecording(serviceName); result != NO_ERROR) { + std::cout << "Failed to stop binder recording on service : " << service << std::endl; + } + } + + return NO_ERROR; +} status_t stopCommandEntryPoint(int argc, char* argv[]) { if (argc != 3) { helpCommandEntryPoint(argc, argv); return android::BAD_VALUE; } - - sp binder = android::defaultServiceManager()->checkService(String16(argv[2])); - if (binder == nullptr) { - helpCommandEntryPoint(argc, argv); - return android::BAD_VALUE; + string stopOption = argv[2]; + if (stopOption == "--all") { + stopRecordingAllBinders(); } - return stopRecording(binder); + + return stopRecording(stopOption); } const AnalyzerCommand stopCommand = { stopCommandEntryPoint, - "Stops recording Binder transactions from a given process. (See 'start')", "", + "Stops recording Binder transactions from a given process. (See 'start') Use --all to stop " + "recoding all binders", + ", --all", " \tService to stop recording; argument to previous 'start' command."}; status_t inspectCommandEntryPoint(int argc, char* argv[]) { @@ -292,19 +338,14 @@ status_t listenCommandEntryPoint(int argc, char* argv[]) { return android::BAD_VALUE; } - sp binder = android::defaultServiceManager()->checkService(String16(argv[2])); - - string filename = argv[2]; - std::replace(filename.begin(), filename.end(), '/', '.'); - auto filePath = kStandardRecordingPath + filename; - - if (status_t startErr = startRecording(binder, filePath); startErr != NO_ERROR) { + string serviceName = argv[2]; + if (status_t startErr = startRecording(serviceName); startErr != NO_ERROR) { return startErr; } - status_t listenStatus = listenToFile(filePath); + status_t listenStatus = listenToFile(serviceName); - if (status_t stopErr = stopRecording(binder); stopErr != NO_ERROR) { + if (status_t stopErr = stopRecording(serviceName); stopErr != NO_ERROR) { return stopErr; } -- cgit v1.2.3