diff options
24 files changed, 208 insertions, 37 deletions
diff --git a/.clang-format b/.clang-format index 03af56d640..6725a1fde8 100644 --- a/.clang-format +++ b/.clang-format @@ -11,3 +11,4 @@ ContinuationIndentWidth: 8 IndentWidth: 4 PenaltyBreakBeforeFirstCallParameter: 100000 SpacesBeforeTrailingComments: 1 +IncludeBlocks: Preserve diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp index f48f1fb6f8..aff32c38c2 100644 --- a/cmds/dumpstate/Android.bp +++ b/cmds/dumpstate/Android.bp @@ -99,6 +99,7 @@ cc_defaults { "libhidlbase", "liblog", "libutils", + "libbinderdebug", ], srcs: [ "DumpstateService.cpp", diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index c2ae341600..b8df99fd55 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -2177,13 +2177,13 @@ void Dumpstate::DumpstateBoard(int out_fd) { } /* - * mount debugfs for non-user builds with ro.product.enforce_debugfs_restrictions + * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled * set to true and unmount it after invoking dumpstateBoard_* methods. * This is to enable debug builds to not have debugfs mounted during runtime. * It will also ensure that debugfs is only accessed by the dumpstate HAL. */ auto mount_debugfs = - android::base::GetBoolProperty("ro.product.enforce_debugfs_restrictions", false); + android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false); if (mount_debugfs) { RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"}, AS_ROOT_20); diff --git a/cmds/dumpsys/Android.bp b/cmds/dumpsys/Android.bp index 91aa018451..6ab6b7f951 100644 --- a/cmds/dumpsys/Android.bp +++ b/cmds/dumpsys/Android.bp @@ -32,6 +32,7 @@ cc_defaults { "libutils", "liblog", "libbinder", + "libbinderdebug", ], static_libs: [ diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp index a017246184..ba1c449dbf 100644 --- a/cmds/dumpsys/dumpsys.cpp +++ b/cmds/dumpsys/dumpsys.cpp @@ -25,6 +25,7 @@ #include <binder/Parcel.h> #include <binder/ProcessState.h> #include <binder/TextOutput.h> +#include <binderdebug/BinderDebug.h> #include <serviceutils/PriorityDumper.h> #include <utils/Log.h> #include <utils/Vector.h> @@ -60,13 +61,15 @@ static void usage() { "usage: dumpsys\n" " To dump all services.\n" "or:\n" - " dumpsys [-t TIMEOUT] [--priority LEVEL] [--pid] [--help | -l | --skip SERVICES " + " dumpsys [-t TIMEOUT] [--priority LEVEL] [--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" " --pid: dump PID instead of usual dump\n" + " --thread: dump thread usage instead of usual dump\n" " --proto: filter services that support dumping data in proto format. Dumps\n" " will be in proto format.\n" " --priority LEVEL: filter services based on specified priority\n" @@ -125,7 +128,8 @@ int Dumpsys::main(int argc, char* const argv[]) { Type type = Type::DUMP; int timeoutArgMs = 10000; int priorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL; - static struct option longOptions[] = {{"pid", no_argument, 0, 0}, + static struct option longOptions[] = {{"thread", no_argument, 0, 0}, + {"pid", no_argument, 0, 0}, {"priority", required_argument, 0, 0}, {"proto", no_argument, 0, 0}, {"skip", no_argument, 0, 0}, @@ -163,6 +167,8 @@ int Dumpsys::main(int argc, char* const argv[]) { } } else if (!strcmp(longOptions[optionIndex].name, "pid")) { type = Type::PID; + } else if (!strcmp(longOptions[optionIndex].name, "thread")) { + type = Type::THREAD; } break; @@ -329,6 +335,23 @@ static status_t dumpPidToFd(const sp<IBinder>& service, const unique_fd& fd) { return OK; } +static status_t dumpThreadsToFd(const sp<IBinder>& service, const unique_fd& fd) { + pid_t pid; + status_t status = service->getDebugPid(&pid); + if (status != OK) { + return status; + } + BinderPidInfo pidInfo; + status = getBinderPidInfo(BinderDebugContext::BINDER, pid, &pidInfo); + if (status != OK) { + return status; + } + WriteStringToFd("Threads in use: " + std::to_string(pidInfo.threadUsage) + "/" + + std::to_string(pidInfo.threadCount) + "\n", + fd.get()); + return OK; +} + status_t Dumpsys::startDumpThread(Type type, const String16& serviceName, const Vector<String16>& args) { sp<IBinder> service = sm_->checkService(serviceName); @@ -359,6 +382,9 @@ status_t Dumpsys::startDumpThread(Type type, const String16& serviceName, case Type::PID: err = dumpPidToFd(service, remote_end); break; + case Type::THREAD: + err = dumpThreadsToFd(service, remote_end); + break; default: std::cerr << "Unknown dump type" << static_cast<int>(type) << std::endl; return; diff --git a/cmds/dumpsys/dumpsys.h b/cmds/dumpsys/dumpsys.h index 929c55c364..349947ce12 100644 --- a/cmds/dumpsys/dumpsys.h +++ b/cmds/dumpsys/dumpsys.h @@ -52,13 +52,14 @@ class Dumpsys { static void setServiceArgs(Vector<String16>& args, bool asProto, int priorityFlags); enum class Type { - DUMP, // dump using `dump` function - PID, // dump pid of server only + DUMP, // dump using `dump` function + PID, // dump pid of server only + THREAD, // dump thread usage of server only }; /** * Starts a thread to connect to a service and get its dump output. The thread redirects - * the output to a pipe. Thread must be stopped by a subsequent callto {@code + * the output to a pipe. Thread must be stopped by a subsequent call to {@code * stopDumpThread}. * @param serviceName * @param args list of arguments to pass to service dump method. diff --git a/cmds/dumpsys/tests/Android.bp b/cmds/dumpsys/tests/Android.bp index 6854c7550e..58fec30c9b 100644 --- a/cmds/dumpsys/tests/Android.bp +++ b/cmds/dumpsys/tests/Android.bp @@ -19,6 +19,7 @@ cc_test { "libbase", "libbinder", "libutils", + "libbinderdebug", ], static_libs: [ @@ -26,6 +27,4 @@ cc_test { "libgmock", "libserviceutils", ], - - clang: true, } diff --git a/cmds/dumpsys/tests/AndroidTest.xml b/cmds/dumpsys/tests/AndroidTest.xml index 1a8c67f7aa..c2351d9aff 100644 --- a/cmds/dumpsys/tests/AndroidTest.xml +++ b/cmds/dumpsys/tests/AndroidTest.xml @@ -23,4 +23,4 @@ <option name="native-test-device-path" value="/data/local/tmp" /> <option name="module-name" value="dumpsys_test" /> </test> -</configuration>
\ No newline at end of file +</configuration> diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp index 67a77f6015..39af7dfae0 100644 --- a/cmds/dumpsys/tests/dumpsys_test.cpp +++ b/cmds/dumpsys/tests/dumpsys_test.cpp @@ -16,12 +16,15 @@ #include "../dumpsys.h" +#include <regex> #include <vector> #include <gmock/gmock.h> #include <gtest/gtest.h> #include <android-base/file.h> +#include <binder/Binder.h> +#include <binder/ProcessState.h> #include <serviceutils/PriorityDumper.h> #include <utils/String16.h> #include <utils/String8.h> @@ -222,6 +225,10 @@ class DumpsysTest : public Test { EXPECT_THAT(stdout_, HasSubstr(expected)); } + void AssertOutputFormat(const std::string format) { + EXPECT_THAT(stdout_, testing::MatchesRegex(format)); + } + void AssertDumped(const std::string& service, const std::string& dump) { EXPECT_THAT(stdout_, HasSubstr("DUMP OF SERVICE " + service + ":\n" + dump)); EXPECT_THAT(stdout_, HasSubstr("was the duration of dumpsys " + service + ", ending at: ")); @@ -574,6 +581,30 @@ TEST_F(DumpsysTest, ListServiceWithPid) { AssertOutput(std::to_string(getpid()) + "\n"); } +// Tests 'dumpsys --thread' +TEST_F(DumpsysTest, ListAllServicesWithThread) { + ExpectListServices({"Locksmith", "Valet"}); + ExpectCheckService("Locksmith"); + ExpectCheckService("Valet"); + + CallMain({"--thread"}); + + AssertRunningServices({"Locksmith", "Valet"}); + + const std::string format("(.|\n)*((Threads in use: [0-9]+/[0-9]+)?\n-(.|\n)*){2}"); + AssertOutputFormat(format); +} + +// Tests 'dumpsys --thread service_name' +TEST_F(DumpsysTest, ListServiceWithThread) { + ExpectCheckService("Locksmith"); + + CallMain({"--thread", "Locksmith"}); + // returns an empty string without root enabled + const std::string format("(^$|Threads in use: [0-9]/[0-9]+\n)"); + AssertOutputFormat(format); +} + TEST_F(DumpsysTest, GetBytesWritten) { const char* serviceName = "service2"; const char* dumpContents = "dump1"; @@ -599,3 +630,13 @@ TEST_F(DumpsysTest, WriteDumpWithoutThreadStart) { /* as_proto = */ false, elapsedDuration, bytesWritten); EXPECT_THAT(status, Eq(INVALID_OPERATION)); } + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + + // start a binder thread pool for testing --thread option + android::ProcessState::self()->setThreadPoolMaxThreadCount(8); + ProcessState::self()->startThreadPool(); + + return RUN_ALL_TESTS(); +} diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index 79fa6bae30..cba82071d4 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -60,10 +60,6 @@ cc_library_headers { // Currently, these are only on system android (not vendor, not host) // TODO(b/183654927) - move these into separate libraries libbinder_device_interface_sources = [ - "AppOpsManager.cpp", - "IAppOpsCallback.cpp", - "IAppOpsService.cpp", - "IPermissionController.cpp", "PermissionCache.cpp", "PermissionController.cpp", diff --git a/libs/binder/RpcConnection.cpp b/libs/binder/RpcConnection.cpp index 4aff92b58a..22e04666eb 100644 --- a/libs/binder/RpcConnection.cpp +++ b/libs/binder/RpcConnection.cpp @@ -18,6 +18,16 @@ #include <binder/RpcConnection.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <netinet/in.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <sys/un.h> +#include <unistd.h> + +#include <string_view> + #include <binder/Parcel.h> #include <binder/Stability.h> #include <utils/String8.h> @@ -25,11 +35,6 @@ #include "RpcState.h" #include "RpcWireFormat.h" -#include <sys/socket.h> -#include <sys/types.h> -#include <sys/un.h> -#include <unistd.h> - #ifdef __GLIBC__ extern "C" pid_t gettid(); #endif @@ -41,6 +46,7 @@ extern "C" pid_t gettid(); namespace android { using base::unique_fd; +using AddrInfo = std::unique_ptr<addrinfo, decltype(&freeaddrinfo)>; RpcConnection::SocketAddress::~SocketAddress() {} @@ -120,6 +126,70 @@ bool RpcConnection::addVsockClient(unsigned int cid, unsigned int port) { #endif // __BIONIC__ +class SocketAddressImpl : public RpcConnection::SocketAddress { +public: + SocketAddressImpl(const sockaddr* addr, size_t size, const String8& desc) + : mAddr(addr), mSize(size), mDesc(desc) {} + [[nodiscard]] std::string toString() const override { + return std::string(mDesc.c_str(), mDesc.size()); + } + [[nodiscard]] const sockaddr* addr() const override { return mAddr; } + [[nodiscard]] size_t addrSize() const override { return mSize; } + void set(const sockaddr* addr, size_t size) { + mAddr = addr; + mSize = size; + } + +private: + const sockaddr* mAddr = nullptr; + size_t mSize = 0; + String8 mDesc; +}; + +AddrInfo GetAddrInfo(const char* addr, unsigned int port) { + addrinfo hint{ + .ai_flags = 0, + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + .ai_protocol = 0, + }; + addrinfo* aiStart = nullptr; + if (int rc = getaddrinfo(addr, std::to_string(port).data(), &hint, &aiStart); 0 != rc) { + ALOGE("Unable to resolve %s:%u: %s", addr, port, gai_strerror(rc)); + return AddrInfo(nullptr, nullptr); + } + if (aiStart == nullptr) { + ALOGE("Unable to resolve %s:%u: getaddrinfo returns null", addr, port); + return AddrInfo(nullptr, nullptr); + } + return AddrInfo(aiStart, &freeaddrinfo); +} + +bool RpcConnection::setupInetServer(unsigned int port) { + auto aiStart = GetAddrInfo("127.0.0.1", port); + if (aiStart == nullptr) return false; + SocketAddressImpl socketAddress(nullptr, 0, String8::format("127.0.0.1:%u", port)); + for (auto ai = aiStart.get(); ai != nullptr; ai = ai->ai_next) { + socketAddress.set(ai->ai_addr, ai->ai_addrlen); + if (setupSocketServer(socketAddress)) return true; + } + ALOGE("None of the socket address resolved for 127.0.0.1:%u can be set up as inet server.", + port); + return false; +} + +bool RpcConnection::addInetClient(const char* addr, unsigned int port) { + auto aiStart = GetAddrInfo(addr, port); + if (aiStart == nullptr) return false; + SocketAddressImpl socketAddress(nullptr, 0, String8::format("%s:%u", addr, port)); + for (auto ai = aiStart.get(); ai != nullptr; ai = ai->ai_next) { + socketAddress.set(ai->ai_addr, ai->ai_addrlen); + if (addSocketClient(socketAddress)) return true; + } + ALOGE("None of the socket address resolved for %s:%u can be added as inet client.", addr, port); + return false; +} + bool RpcConnection::addNullDebuggingClient() { unique_fd serverFd(TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY | O_CLOEXEC))); diff --git a/libs/binder/include/binder/RpcConnection.h b/libs/binder/include/binder/RpcConnection.h index dba47b4d15..1763d10a8e 100644 --- a/libs/binder/include/binder/RpcConnection.h +++ b/libs/binder/include/binder/RpcConnection.h @@ -74,6 +74,16 @@ public: #endif // __BIONIC__ /** + * Creates an RPC server at the current port. + */ + [[nodiscard]] bool setupInetServer(unsigned int port); + + /** + * Connects to an RPC server at the given address and port. + */ + [[nodiscard]] bool addInetClient(const char* addr, unsigned int port); + + /** * For debugging! * * Sets up an empty socket. All queries to this socket which require a diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp index e12a429cf9..57c9013f60 100644 --- a/libs/binder/rust/Android.bp +++ b/libs/binder/rust/Android.bp @@ -65,15 +65,15 @@ rust_bindgen { // rustified "--constified-enum", "android::c_interface::consts::.*", - "--whitelist-type", "android::c_interface::.*", - "--whitelist-type", "AStatus", - "--whitelist-type", "AIBinder_Class", - "--whitelist-type", "AIBinder", - "--whitelist-type", "AIBinder_Weak", - "--whitelist-type", "AIBinder_DeathRecipient", - "--whitelist-type", "AParcel", - "--whitelist-type", "binder_status_t", - "--whitelist-function", ".*", + "--allowlist-type", "android::c_interface::.*", + "--allowlist-type", "AStatus", + "--allowlist-type", "AIBinder_Class", + "--allowlist-type", "AIBinder", + "--allowlist-type", "AIBinder_Weak", + "--allowlist-type", "AIBinder_DeathRecipient", + "--allowlist-type", "AParcel", + "--allowlist-type", "binder_status_t", + "--allowlist-function", ".*", ], shared_libs: [ "libbinder_ndk", diff --git a/libs/binder/rust/tests/Android.bp b/libs/binder/rust/tests/Android.bp index 0bf76c696a..607860f462 100644 --- a/libs/binder/rust/tests/Android.bp +++ b/libs/binder/rust/tests/Android.bp @@ -114,8 +114,8 @@ rust_bindgen { source_stem: "bindings", cpp_std: "gnu++17", bindgen_flags: [ - "--whitelist-type", "Transaction", - "--whitelist-var", "TESTDATA_.*", + "--allowlist-type", "Transaction", + "--allowlist-var", "TESTDATA_.*", ], shared_libs: [ diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp index 33402937ab..ec4ced299b 100644 --- a/libs/binder/tests/binderRpcTest.cpp +++ b/libs/binder/tests/binderRpcTest.cpp @@ -257,6 +257,7 @@ enum class SocketType { #ifdef __BIONIC__ VSOCK, #endif // __BIONIC__ + INET, }; static inline std::string PrintSocketType(const testing::TestParamInfo<SocketType>& info) { switch (info.param) { @@ -266,6 +267,8 @@ static inline std::string PrintSocketType(const testing::TestParamInfo<SocketTyp case SocketType::VSOCK: return "vm_socket"; #endif // __BIONIC__ + case SocketType::INET: + return "inet_socket"; default: LOG_ALWAYS_FATAL("Unknown socket type"); return ""; @@ -305,6 +308,9 @@ public: CHECK(connection->setupVsockServer(port)); break; #endif // __BIONIC__ + case SocketType::INET: + CHECK(connection->setupInetServer(port)); + break; default: LOG_ALWAYS_FATAL("Unknown socket type"); } @@ -335,6 +341,9 @@ public: if (ret.connection->addVsockClient(VMADDR_CID_LOCAL, port)) goto success; break; #endif // __BIONIC__ + case SocketType::INET: + if (ret.connection->addInetClient("127.0.0.1", port)) goto success; + break; default: LOG_ALWAYS_FATAL("Unknown socket type"); } @@ -852,12 +861,13 @@ TEST_P(BinderRpc, Fds) { } INSTANTIATE_TEST_CASE_P(PerSocket, BinderRpc, - ::testing::Values(SocketType::UNIX + ::testing::ValuesIn({ + SocketType::UNIX, #ifdef __BIONIC__ - , - SocketType::VSOCK + SocketType::VSOCK, #endif // __BIONIC__ - ), + SocketType::INET, + }), PrintSocketType); } // namespace android diff --git a/libs/permission/Android.bp b/libs/permission/Android.bp new file mode 100644 index 0000000000..dd38224a60 --- /dev/null +++ b/libs/permission/Android.bp @@ -0,0 +1,14 @@ +cc_library_shared { + name: "libpermission", + srcs: [ + "AppOpsManager.cpp", + "IAppOpsCallback.cpp", + "IAppOpsService.cpp", + ], + export_include_dirs: ["include"], + shared_libs: [ + "libbinder", + "liblog", + "libutils", + ], +} diff --git a/libs/binder/AppOpsManager.cpp b/libs/permission/AppOpsManager.cpp index f3ea1a71d0..f3ea1a71d0 100644 --- a/libs/binder/AppOpsManager.cpp +++ b/libs/permission/AppOpsManager.cpp diff --git a/libs/binder/IAppOpsCallback.cpp b/libs/permission/IAppOpsCallback.cpp index 2b3f462ab8..2b3f462ab8 100644 --- a/libs/binder/IAppOpsCallback.cpp +++ b/libs/permission/IAppOpsCallback.cpp diff --git a/libs/binder/IAppOpsService.cpp b/libs/permission/IAppOpsService.cpp index 1af5ab8719..1af5ab8719 100644 --- a/libs/binder/IAppOpsService.cpp +++ b/libs/permission/IAppOpsService.cpp diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/permission/include/binder/AppOpsManager.h index 35c697e3d2..35c697e3d2 100644 --- a/libs/binder/include/binder/AppOpsManager.h +++ b/libs/permission/include/binder/AppOpsManager.h diff --git a/libs/binder/include/binder/IAppOpsCallback.h b/libs/permission/include/binder/IAppOpsCallback.h index eb76f57bf8..eb76f57bf8 100644 --- a/libs/binder/include/binder/IAppOpsCallback.h +++ b/libs/permission/include/binder/IAppOpsCallback.h diff --git a/libs/binder/include/binder/IAppOpsService.h b/libs/permission/include/binder/IAppOpsService.h index b0719d4ebc..b0719d4ebc 100644 --- a/libs/binder/include/binder/IAppOpsService.h +++ b/libs/permission/include/binder/IAppOpsService.h diff --git a/libs/sensor/Android.bp b/libs/sensor/Android.bp index 497c33c386..edd453a936 100644 --- a/libs/sensor/Android.bp +++ b/libs/sensor/Android.bp @@ -48,11 +48,10 @@ cc_library_shared { "libutils", "liblog", "libhardware", + "libpermission", ], export_include_dirs: ["include"], - export_shared_lib_headers: ["libbinder", "libhardware"], + export_shared_lib_headers: ["libbinder", "libpermission", "libhardware"], } - -subdirs = ["tests"] diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp index 9aecaff409..4151b4512f 100644 --- a/services/sensorservice/Android.bp +++ b/services/sensorservice/Android.bp @@ -54,6 +54,7 @@ cc_library_shared { "libbinder", "libsensor", "libsensorprivacy", + "libpermission", "libprotoutil", "libcrypto", "libbase", @@ -74,6 +75,7 @@ cc_library_shared { "libactivitymanager_aidl", "libsensor", "libsensorprivacy", + "libpermission", ], } |