Loading cmds/dumpsys/dumpsys.cpp +67 −30 Original line number Diff line number Diff line Loading @@ -21,7 +21,9 @@ #include <android-base/file.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/unique_fd.h> #include <binder/BpBinder.h> #include <binder/Parcel.h> #include <binder/ProcessState.h> #include <binder/Stability.h> Loading Loading @@ -58,17 +60,20 @@ static int sort_func(const String16* lhs, const String16* rhs) } static void usage() { fprintf(stderr, fprintf( stderr, "usage: dumpsys\n" " To dump all services.\n" "or:\n" " dumpsys [-t TIMEOUT] [--priority LEVEL] [--dump] [--pid] [--thread] [--help | " " dumpsys [-t TIMEOUT] [--priority LEVEL] [--clients] [--dump] [--pid] [--thread] " "[--help | " "-l | --skip SERVICES " "| SERVICE [ARGS]]\n" " --help: shows this help\n" " -l: only list services, do not dump them\n" " -t TIMEOUT_SEC: TIMEOUT to use in seconds instead of default 10 seconds\n" " -T TIMEOUT_MS: TIMEOUT to use in milliseconds instead of default 10 seconds\n" " --clients: dump client PIDs instead of usual dump\n" " --dump: ask the service to dump itself (this is the default)\n" " --pid: dump PID instead of usual dump\n" " --proto: filter services that support dumping data in proto format. Dumps\n" Loading Loading @@ -131,15 +136,12 @@ int Dumpsys::main(int argc, char* const argv[]) { int dumpTypeFlags = 0; int timeoutArgMs = 10000; int priorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL; static struct option longOptions[] = {{"help", no_argument, 0, 0}, {"dump", no_argument, 0, 0}, {"pid", no_argument, 0, 0}, {"priority", required_argument, 0, 0}, {"proto", no_argument, 0, 0}, {"skip", no_argument, 0, 0}, {"stability", no_argument, 0, 0}, {"thread", no_argument, 0, 0}, {0, 0, 0, 0}}; static struct option longOptions[] = { {"help", no_argument, 0, 0}, {"clients", no_argument, 0, 0}, {"dump", no_argument, 0, 0}, {"pid", no_argument, 0, 0}, {"priority", required_argument, 0, 0}, {"proto", no_argument, 0, 0}, {"skip", no_argument, 0, 0}, {"stability", no_argument, 0, 0}, {"thread", no_argument, 0, 0}, {0, 0, 0, 0}}; // Must reset optind, otherwise subsequent calls will fail (wouldn't happen on main.cpp, but // happens on test cases). Loading Loading @@ -178,6 +180,8 @@ int Dumpsys::main(int argc, char* const argv[]) { dumpTypeFlags |= TYPE_STABILITY; } else if (!strcmp(longOptions[optionIndex].name, "thread")) { dumpTypeFlags |= TYPE_THREAD; } else if (!strcmp(longOptions[optionIndex].name, "clients")) { dumpTypeFlags |= TYPE_CLIENTS; } break; Loading Loading @@ -373,6 +377,35 @@ static status_t dumpThreadsToFd(const sp<IBinder>& service, const unique_fd& fd) return OK; } static status_t dumpClientsToFd(const sp<IBinder>& service, const unique_fd& fd) { std::string clientPids; const auto remoteBinder = service->remoteBinder(); if (remoteBinder == nullptr) { WriteStringToFd("Client PIDs are not available for local binders.\n", fd.get()); return OK; } const auto handle = remoteBinder->getDebugBinderHandle(); if (handle == std::nullopt) { return OK; } std::vector<pid_t> pids; pid_t myPid = getpid(); pid_t servicePid; status_t status = service->getDebugPid(&servicePid); if (status != OK) { return status; } status = getBinderClientPids(BinderDebugContext::BINDER, myPid, servicePid, handle.value(), &pids); if (status != OK) { return status; } pids.erase(std::remove_if(pids.begin(), pids.end(), [&](pid_t pid) { return pid == myPid; }), pids.end()); WriteStringToFd("Client PIDs: " + ::android::base::Join(pids, ", ") + "\n", fd.get()); return OK; } static void reportDumpError(const String16& serviceName, status_t error, const char* context) { if (error == OK) return; Loading Loading @@ -413,6 +446,10 @@ status_t Dumpsys::startDumpThread(int dumpTypeFlags, const String16& serviceName status_t err = dumpThreadsToFd(service, remote_end); reportDumpError(serviceName, err, "dumping thread info"); } if (dumpTypeFlags & TYPE_CLIENTS) { status_t err = dumpClientsToFd(service, remote_end); reportDumpError(serviceName, err, "dumping clients info"); } // other types always act as a header, this is usually longer if (dumpTypeFlags & TYPE_DUMP) { Loading cmds/dumpsys/dumpsys.h +5 −4 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ class Dumpsys { TYPE_PID = 0x2, // dump pid of server only TYPE_STABILITY = 0x4, // dump stability information of server TYPE_THREAD = 0x8, // dump thread usage of server only TYPE_CLIENTS = 0x10, // dump pid of clients }; /** Loading cmds/dumpsys/tests/dumpsys_test.cpp +23 −0 Original line number Diff line number Diff line Loading @@ -627,6 +627,29 @@ TEST_F(DumpsysTest, ListServiceWithThread) { AssertOutputFormat(format); } // Tests 'dumpsys --clients' TEST_F(DumpsysTest, ListAllServicesWithClients) { ExpectListServices({"Locksmith", "Valet"}); ExpectCheckService("Locksmith"); ExpectCheckService("Valet"); CallMain({"--clients"}); AssertRunningServices({"Locksmith", "Valet"}); const std::string format("(.|\n)*((Client PIDs are not available for local binders.)(.|\n)*){2}"); AssertOutputFormat(format); } // Tests 'dumpsys --clients service_name' TEST_F(DumpsysTest, ListServiceWithClients) { ExpectCheckService("Locksmith"); CallMain({"--clients", "Locksmith"}); const std::string format("Client PIDs are not available for local binders.\n"); AssertOutputFormat(format); } // Tests 'dumpsys --thread --stability' TEST_F(DumpsysTest, ListAllServicesWithMultipleOptions) { ExpectListServices({"Locksmith", "Valet"}); Loading libs/binder/BpBinder.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -188,6 +188,14 @@ int32_t BpBinder::binderHandle() const { return std::get<BinderHandle>(mHandle).handle; } std::optional<int32_t> BpBinder::getDebugBinderHandle() const { if (!isRpcBinder()) { return binderHandle(); } else { return std::nullopt; } } bool BpBinder::isDescriptorCached() const { Mutex::Autolock _l(mLock); return mDescriptorCache.size() ? true : false; Loading libs/binder/include/binder/BpBinder.h +2 −0 Original line number Diff line number Diff line Loading @@ -90,6 +90,8 @@ public: static void setLimitCallback(binder_proxy_limit_callback cb); static void setBinderProxyCountWatermarks(int high, int low); std::optional<int32_t> getDebugBinderHandle() const; class ObjectManager { public: ObjectManager(); Loading Loading
cmds/dumpsys/dumpsys.cpp +67 −30 Original line number Diff line number Diff line Loading @@ -21,7 +21,9 @@ #include <android-base/file.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/unique_fd.h> #include <binder/BpBinder.h> #include <binder/Parcel.h> #include <binder/ProcessState.h> #include <binder/Stability.h> Loading Loading @@ -58,17 +60,20 @@ static int sort_func(const String16* lhs, const String16* rhs) } static void usage() { fprintf(stderr, fprintf( stderr, "usage: dumpsys\n" " To dump all services.\n" "or:\n" " dumpsys [-t TIMEOUT] [--priority LEVEL] [--dump] [--pid] [--thread] [--help | " " dumpsys [-t TIMEOUT] [--priority LEVEL] [--clients] [--dump] [--pid] [--thread] " "[--help | " "-l | --skip SERVICES " "| SERVICE [ARGS]]\n" " --help: shows this help\n" " -l: only list services, do not dump them\n" " -t TIMEOUT_SEC: TIMEOUT to use in seconds instead of default 10 seconds\n" " -T TIMEOUT_MS: TIMEOUT to use in milliseconds instead of default 10 seconds\n" " --clients: dump client PIDs instead of usual dump\n" " --dump: ask the service to dump itself (this is the default)\n" " --pid: dump PID instead of usual dump\n" " --proto: filter services that support dumping data in proto format. Dumps\n" Loading Loading @@ -131,15 +136,12 @@ int Dumpsys::main(int argc, char* const argv[]) { int dumpTypeFlags = 0; int timeoutArgMs = 10000; int priorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL; static struct option longOptions[] = {{"help", no_argument, 0, 0}, {"dump", no_argument, 0, 0}, {"pid", no_argument, 0, 0}, {"priority", required_argument, 0, 0}, {"proto", no_argument, 0, 0}, {"skip", no_argument, 0, 0}, {"stability", no_argument, 0, 0}, {"thread", no_argument, 0, 0}, {0, 0, 0, 0}}; static struct option longOptions[] = { {"help", no_argument, 0, 0}, {"clients", no_argument, 0, 0}, {"dump", no_argument, 0, 0}, {"pid", no_argument, 0, 0}, {"priority", required_argument, 0, 0}, {"proto", no_argument, 0, 0}, {"skip", no_argument, 0, 0}, {"stability", no_argument, 0, 0}, {"thread", no_argument, 0, 0}, {0, 0, 0, 0}}; // Must reset optind, otherwise subsequent calls will fail (wouldn't happen on main.cpp, but // happens on test cases). Loading Loading @@ -178,6 +180,8 @@ int Dumpsys::main(int argc, char* const argv[]) { dumpTypeFlags |= TYPE_STABILITY; } else if (!strcmp(longOptions[optionIndex].name, "thread")) { dumpTypeFlags |= TYPE_THREAD; } else if (!strcmp(longOptions[optionIndex].name, "clients")) { dumpTypeFlags |= TYPE_CLIENTS; } break; Loading Loading @@ -373,6 +377,35 @@ static status_t dumpThreadsToFd(const sp<IBinder>& service, const unique_fd& fd) return OK; } static status_t dumpClientsToFd(const sp<IBinder>& service, const unique_fd& fd) { std::string clientPids; const auto remoteBinder = service->remoteBinder(); if (remoteBinder == nullptr) { WriteStringToFd("Client PIDs are not available for local binders.\n", fd.get()); return OK; } const auto handle = remoteBinder->getDebugBinderHandle(); if (handle == std::nullopt) { return OK; } std::vector<pid_t> pids; pid_t myPid = getpid(); pid_t servicePid; status_t status = service->getDebugPid(&servicePid); if (status != OK) { return status; } status = getBinderClientPids(BinderDebugContext::BINDER, myPid, servicePid, handle.value(), &pids); if (status != OK) { return status; } pids.erase(std::remove_if(pids.begin(), pids.end(), [&](pid_t pid) { return pid == myPid; }), pids.end()); WriteStringToFd("Client PIDs: " + ::android::base::Join(pids, ", ") + "\n", fd.get()); return OK; } static void reportDumpError(const String16& serviceName, status_t error, const char* context) { if (error == OK) return; Loading Loading @@ -413,6 +446,10 @@ status_t Dumpsys::startDumpThread(int dumpTypeFlags, const String16& serviceName status_t err = dumpThreadsToFd(service, remote_end); reportDumpError(serviceName, err, "dumping thread info"); } if (dumpTypeFlags & TYPE_CLIENTS) { status_t err = dumpClientsToFd(service, remote_end); reportDumpError(serviceName, err, "dumping clients info"); } // other types always act as a header, this is usually longer if (dumpTypeFlags & TYPE_DUMP) { Loading
cmds/dumpsys/dumpsys.h +5 −4 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ class Dumpsys { TYPE_PID = 0x2, // dump pid of server only TYPE_STABILITY = 0x4, // dump stability information of server TYPE_THREAD = 0x8, // dump thread usage of server only TYPE_CLIENTS = 0x10, // dump pid of clients }; /** Loading
cmds/dumpsys/tests/dumpsys_test.cpp +23 −0 Original line number Diff line number Diff line Loading @@ -627,6 +627,29 @@ TEST_F(DumpsysTest, ListServiceWithThread) { AssertOutputFormat(format); } // Tests 'dumpsys --clients' TEST_F(DumpsysTest, ListAllServicesWithClients) { ExpectListServices({"Locksmith", "Valet"}); ExpectCheckService("Locksmith"); ExpectCheckService("Valet"); CallMain({"--clients"}); AssertRunningServices({"Locksmith", "Valet"}); const std::string format("(.|\n)*((Client PIDs are not available for local binders.)(.|\n)*){2}"); AssertOutputFormat(format); } // Tests 'dumpsys --clients service_name' TEST_F(DumpsysTest, ListServiceWithClients) { ExpectCheckService("Locksmith"); CallMain({"--clients", "Locksmith"}); const std::string format("Client PIDs are not available for local binders.\n"); AssertOutputFormat(format); } // Tests 'dumpsys --thread --stability' TEST_F(DumpsysTest, ListAllServicesWithMultipleOptions) { ExpectListServices({"Locksmith", "Valet"}); Loading
libs/binder/BpBinder.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -188,6 +188,14 @@ int32_t BpBinder::binderHandle() const { return std::get<BinderHandle>(mHandle).handle; } std::optional<int32_t> BpBinder::getDebugBinderHandle() const { if (!isRpcBinder()) { return binderHandle(); } else { return std::nullopt; } } bool BpBinder::isDescriptorCached() const { Mutex::Autolock _l(mLock); return mDescriptorCache.size() ? true : false; Loading
libs/binder/include/binder/BpBinder.h +2 −0 Original line number Diff line number Diff line Loading @@ -90,6 +90,8 @@ public: static void setLimitCallback(binder_proxy_limit_callback cb); static void setBinderProxyCountWatermarks(int high, int low); std::optional<int32_t> getDebugBinderHandle() const; class ObjectManager { public: ObjectManager(); Loading