Merge "Allow set_requesting_sid to be enabled when AIDL Binder is created."
diff --git a/.clang-format b/.clang-format
index 03af56d..6725a1f 100644
--- a/.clang-format
+++ b/.clang-format
@@ -11,3 +11,4 @@
IndentWidth: 4
PenaltyBreakBeforeFirstCallParameter: 100000
SpacesBeforeTrailingComments: 1
+IncludeBlocks: Preserve
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index f48f1fb..aff32c3 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -99,6 +99,7 @@
"libhidlbase",
"liblog",
"libutils",
+ "libbinderdebug",
],
srcs: [
"DumpstateService.cpp",
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 039dbc5..b8df99f 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -793,6 +793,9 @@
if (module_metadata_version != 0) {
printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
}
+ printf("SDK extension versions [r=%s s=%s]\n",
+ android::base::GetProperty("build.version.extensions.r", "-").c_str(),
+ android::base::GetProperty("build.version.extensions.s", "-").c_str());
printf("Kernel: ");
DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
@@ -2174,13 +2177,13 @@
}
/*
- * 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 91aa018..6ab6b7f 100644
--- a/cmds/dumpsys/Android.bp
+++ b/cmds/dumpsys/Android.bp
@@ -32,6 +32,7 @@
"libutils",
"liblog",
"libbinder",
+ "libbinderdebug",
],
static_libs: [
diff --git a/cmds/dumpsys/OWNERS b/cmds/dumpsys/OWNERS
index 2a9b681..4f6a89e 100644
--- a/cmds/dumpsys/OWNERS
+++ b/cmds/dumpsys/OWNERS
@@ -2,3 +2,6 @@
nandana@google.com
jsharkey@android.com
+
+# for ServiceManager mock
+per-file dumpsys_test.cpp=smoreland@google.com
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index a017246..ba1c449 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 @@
"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 @@
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 @@
}
} 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 @@
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 @@
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 929c55c..349947c 100644
--- a/cmds/dumpsys/dumpsys.h
+++ b/cmds/dumpsys/dumpsys.h
@@ -52,13 +52,14 @@
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 6854c75..58fec30 100644
--- a/cmds/dumpsys/tests/Android.bp
+++ b/cmds/dumpsys/tests/Android.bp
@@ -19,6 +19,7 @@
"libbase",
"libbinder",
"libutils",
+ "libbinderdebug",
],
static_libs: [
@@ -26,6 +27,4 @@
"libgmock",
"libserviceutils",
],
-
- clang: true,
}
diff --git a/cmds/dumpsys/tests/AndroidTest.xml b/cmds/dumpsys/tests/AndroidTest.xml
index 1a8c67f..c2351d9 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 67a77f6..c9d2dbb 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>
@@ -56,6 +59,7 @@
MOCK_METHOD1(waitForService, sp<IBinder>(const String16&));
MOCK_METHOD1(isDeclared, bool(const String16&));
MOCK_METHOD1(getDeclaredInstances, Vector<String16>(const String16&));
+ MOCK_METHOD1(updatableViaApex, std::optional<String16>(const String16&));
protected:
MOCK_METHOD0(onAsBinder, IBinder*());
};
@@ -222,6 +226,10 @@
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 +582,30 @@
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 +631,13 @@
/* 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/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index 3a87776..83f01de 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -179,6 +179,11 @@
// want it for product APKs. Same notes as vendor above.
TryExtraMount("product", arg[2], "/postinstall/product");
+ // Try to mount the system_ext partition. update_engine doesn't do this for
+ // us, but we want it for system_ext APKs. Same notes as vendor and product
+ // above.
+ TryExtraMount("system_ext", arg[2], "/postinstall/system_ext");
+
constexpr const char* kPostInstallLinkerconfig = "/postinstall/linkerconfig";
// Try to mount /postinstall/linkerconfig. we will set it up after performing the chroot
if (mount("tmpfs", kPostInstallLinkerconfig, "tmpfs", 0, nullptr) != 0) {
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index d5110f6..2722e21 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -417,7 +417,7 @@
}
}
out << "-->" << std::endl;
- out << vintf::gHalManifestConverter(manifest, vintf::SerializeFlags::HALS_ONLY);
+ out << vintf::toXml(manifest, vintf::SerializeFlags::HALS_ONLY);
}
std::string ListCommand::INIT_VINTF_NOTES{
diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp
index 7c1ca91..6f08f74 100644
--- a/cmds/lshal/test.cpp
+++ b/cmds/lshal/test.cpp
@@ -47,8 +47,6 @@
using ::android::hardware::Void;
using android::vintf::Arch;
using android::vintf::CompatibilityMatrix;
-using android::vintf::gCompatibilityMatrixConverter;
-using android::vintf::gHalManifestConverter;
using android::vintf::HalManifest;
using android::vintf::Transport;
using android::vintf::VintfObject;
@@ -510,7 +508,7 @@
std::string error;
vintf::HalManifest m;
- EXPECT_EQ(true, vintf::gHalManifestConverter(&m, out.str(), &error))
+ EXPECT_EQ(true, vintf::fromXml(&m, out.str(), &error))
<< "--init-vintf does not emit valid HAL manifest: " << error;
}
@@ -775,10 +773,10 @@
auto deviceMatrix = std::make_shared<CompatibilityMatrix>();
auto frameworkMatrix = std::make_shared<CompatibilityMatrix>();
- ASSERT_TRUE(gHalManifestConverter(deviceManifest.get(), deviceManifestXml));
- ASSERT_TRUE(gHalManifestConverter(frameworkManifest.get(), frameworkManifestXml));
- ASSERT_TRUE(gCompatibilityMatrixConverter(deviceMatrix.get(), deviceMatrixXml));
- ASSERT_TRUE(gCompatibilityMatrixConverter(frameworkMatrix.get(), frameworkMatrixXml));
+ ASSERT_TRUE(fromXml(deviceManifest.get(), deviceManifestXml));
+ ASSERT_TRUE(fromXml(frameworkManifest.get(), frameworkManifestXml));
+ ASSERT_TRUE(fromXml(deviceMatrix.get(), deviceMatrixXml));
+ ASSERT_TRUE(fromXml(frameworkMatrix.get(), frameworkMatrixXml));
ON_CALL(*mockList, getDeviceManifest()).WillByDefault(Return(deviceManifest));
ON_CALL(*mockList, getDeviceMatrix()).WillByDefault(Return(deviceMatrix));
@@ -964,7 +962,7 @@
" </hal>\n"
"</manifest>";
auto manifest = std::make_shared<HalManifest>();
- EXPECT_TRUE(gHalManifestConverter(manifest.get(), mockManifestXml));
+ EXPECT_TRUE(fromXml(manifest.get(), mockManifestXml));
EXPECT_CALL(*mockList, getDeviceManifest())
.Times(AnyNumber())
.WillRepeatedly(Return(manifest));
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index 2f55249..b429fb3 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -58,22 +58,34 @@
return false;
}
-static bool isVintfDeclared(const std::string& name) {
- size_t firstSlash = name.find('/');
- size_t lastDot = name.rfind('.', firstSlash);
- if (firstSlash == std::string::npos || lastDot == std::string::npos) {
- LOG(ERROR) << "VINTF HALs require names in the format type/instance (e.g. "
- << "some.package.foo.IFoo/default) but got: " << name;
- return false;
- }
- const std::string package = name.substr(0, lastDot);
- const std::string iface = name.substr(lastDot+1, firstSlash-lastDot-1);
- const std::string instance = name.substr(firstSlash+1);
+struct AidlName {
+ std::string package;
+ std::string iface;
+ std::string instance;
- bool found = forEachManifest([&] (const ManifestWithDescription& mwd) {
- if (mwd.manifest->hasAidlInstance(package, iface, instance)) {
+ static bool fill(const std::string& name, AidlName* aname) {
+ size_t firstSlash = name.find('/');
+ size_t lastDot = name.rfind('.', firstSlash);
+ if (firstSlash == std::string::npos || lastDot == std::string::npos) {
+ LOG(ERROR) << "VINTF HALs require names in the format type/instance (e.g. "
+ << "some.package.foo.IFoo/default) but got: " << name;
+ return false;
+ }
+ aname->package = name.substr(0, lastDot);
+ aname->iface = name.substr(lastDot + 1, firstSlash - lastDot - 1);
+ aname->instance = name.substr(firstSlash + 1);
+ return true;
+ }
+};
+
+static bool isVintfDeclared(const std::string& name) {
+ AidlName aname;
+ if (!AidlName::fill(name, &aname)) return false;
+
+ bool found = forEachManifest([&](const ManifestWithDescription& mwd) {
+ if (mwd.manifest->hasAidlInstance(aname.package, aname.iface, aname.instance)) {
LOG(INFO) << "Found " << name << " in " << mwd.description << " VINTF manifest.";
- return true;
+ return true; // break
}
return false; // continue
});
@@ -81,13 +93,34 @@
if (!found) {
// Although it is tested, explicitly rebuilding qualified name, in case it
// becomes something unexpected.
- LOG(ERROR) << "Could not find " << package << "." << iface << "/" << instance
- << " in the VINTF manifest.";
+ LOG(ERROR) << "Could not find " << aname.package << "." << aname.iface << "/"
+ << aname.instance << " in the VINTF manifest.";
}
return found;
}
+static std::optional<std::string> getVintfUpdatableApex(const std::string& name) {
+ AidlName aname;
+ if (!AidlName::fill(name, &aname)) return std::nullopt;
+
+ std::optional<std::string> updatableViaApex;
+
+ forEachManifest([&](const ManifestWithDescription& mwd) {
+ mwd.manifest->forEachInstance([&](const auto& manifestInstance) {
+ if (manifestInstance.format() != vintf::HalFormat::AIDL) return true;
+ if (manifestInstance.package() != aname.package) return true;
+ if (manifestInstance.interface() != aname.iface) return true;
+ if (manifestInstance.instance() != aname.instance) return true;
+ updatableViaApex = manifestInstance.updatableViaApex();
+ return false; // break (libvintf uses opposite convention)
+ });
+ return false; // continue
+ });
+
+ return updatableViaApex;
+}
+
static std::vector<std::string> getVintfInstances(const std::string& interface) {
size_t lastDot = interface.rfind('.');
if (lastDot == std::string::npos) {
@@ -388,6 +421,22 @@
return Status::ok();
}
+Status ServiceManager::updatableViaApex(const std::string& name,
+ std::optional<std::string>* outReturn) {
+ auto ctx = mAccess->getCallingContext();
+
+ if (!mAccess->canFind(ctx, name)) {
+ return Status::fromExceptionCode(Status::EX_SECURITY);
+ }
+
+ *outReturn = std::nullopt;
+
+#ifndef VENDORSERVICEMANAGER
+ *outReturn = getVintfUpdatableApex(name);
+#endif
+ return Status::ok();
+}
+
void ServiceManager::removeRegistrationCallback(const wp<IBinder>& who,
ServiceCallbackMap::iterator* it,
bool* found) {
diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h
index c089115..4f23c21 100644
--- a/cmds/servicemanager/ServiceManager.h
+++ b/cmds/servicemanager/ServiceManager.h
@@ -46,6 +46,8 @@
binder::Status isDeclared(const std::string& name, bool* outReturn) override;
binder::Status getDeclaredInstances(const std::string& interface, std::vector<std::string>* outReturn) override;
+ binder::Status updatableViaApex(const std::string& name,
+ std::optional<std::string>* outReturn) override;
binder::Status registerClientCallback(const std::string& name, const sp<IBinder>& service,
const sp<IClientCallback>& cb) override;
binder::Status tryUnregisterService(const std::string& name, const sp<IBinder>& binder) override;
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 79fa6ba..cba8207 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -60,10 +60,6 @@
// 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/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 406bd54..6fb1227 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -90,6 +90,8 @@
"BR_DEAD_BINDER",
"BR_CLEAR_DEATH_NOTIFICATION_DONE",
"BR_FAILED_REPLY",
+ "BR_FROZEN_REPLY",
+ "BR_ONEWAY_SPAM_SUSPECT",
"BR_TRANSACTION_SEC_CTX",
};
@@ -894,6 +896,11 @@
}
switch (cmd) {
+ case BR_ONEWAY_SPAM_SUSPECT:
+ ALOGE("Process seems to be sending too many oneway calls.");
+ CallStack::logStack("oneway spamming", CallStack::getCurrent().get(),
+ ANDROID_LOG_ERROR);
+ [[fallthrough]];
case BR_TRANSACTION_COMPLETE:
if (!reply && !acquireResult) goto finish;
break;
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 61f4581..f684cf6 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -75,6 +75,7 @@
sp<IBinder> waitForService(const String16& name16) override;
bool isDeclared(const String16& name) override;
Vector<String16> getDeclaredInstances(const String16& interface) override;
+ std::optional<String16> updatableViaApex(const String16& name) override;
// for legacy ABI
const String16& getInterfaceDescriptor() const override {
@@ -388,4 +389,12 @@
return res;
}
+std::optional<String16> ServiceManagerShim::updatableViaApex(const String16& name) {
+ std::optional<std::string> declared;
+ if (!mTheRealServiceManager->updatableViaApex(String8(name).c_str(), &declared).isOk()) {
+ return std::nullopt;
+ }
+ return declared ? std::optional<String16>(String16(declared.value().c_str())) : std::nullopt;
+}
+
} // namespace android
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index a8b2fb2..ca99042 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -43,6 +43,7 @@
#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
#define DEFAULT_MAX_BINDER_THREADS 15
+#define DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION 1
#ifdef __ANDROID_VNDK__
const char* kDefaultDriver = "/dev/vndbinder";
@@ -358,6 +359,15 @@
return result;
}
+status_t ProcessState::enableOnewaySpamDetection(bool enable) {
+ uint32_t enableDetection = enable ? 1 : 0;
+ if (ioctl(mDriverFD, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enableDetection) == -1) {
+ ALOGE("Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
+ return -errno;
+ }
+ return NO_ERROR;
+}
+
void ProcessState::giveThreadPoolName() {
androidSetThreadName( makeBinderThreadName().string() );
}
@@ -388,6 +398,11 @@
if (result == -1) {
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
+ uint32_t enable = DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION;
+ result = ioctl(fd, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable);
+ if (result == -1) {
+ ALOGE("Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
+ }
} else {
ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
}
diff --git a/libs/binder/RpcConnection.cpp b/libs/binder/RpcConnection.cpp
index 1bf3d88..1388a80 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 @@
namespace android {
using base::unique_fd;
+using AddrInfo = std::unique_ptr<addrinfo, decltype(&freeaddrinfo)>;
RpcConnection::SocketAddress::~SocketAddress() {}
@@ -51,6 +57,10 @@
}
RpcConnection::~RpcConnection() {
LOG_RPC_DETAIL("RpcConnection destroyed %p", this);
+
+ std::lock_guard<std::mutex> _l(mSocketMutex);
+ LOG_ALWAYS_FATAL_IF(mServers.size() != 0,
+ "Should not be able to destroy a connection with servers in use.");
}
sp<RpcConnection> RpcConnection::make() {
@@ -61,7 +71,8 @@
public:
explicit UnixSocketAddress(const char* path) : mAddr({.sun_family = AF_UNIX}) {
unsigned int pathLen = strlen(path) + 1;
- LOG_ALWAYS_FATAL_IF(pathLen > sizeof(mAddr.sun_path), "%u %s", pathLen, path);
+ LOG_ALWAYS_FATAL_IF(pathLen > sizeof(mAddr.sun_path), "Socket path is too long: %u %s",
+ pathLen, path);
memcpy(mAddr.sun_path, path, pathLen);
}
virtual ~UnixSocketAddress() {}
@@ -78,11 +89,11 @@
};
bool RpcConnection::setupUnixDomainServer(const char* path) {
- return addServer(UnixSocketAddress(path));
+ return setupSocketServer(UnixSocketAddress(path));
}
bool RpcConnection::addUnixDomainClient(const char* path) {
- return addClient(UnixSocketAddress(path));
+ return addSocketClient(UnixSocketAddress(path));
}
#ifdef __BIONIC__
@@ -97,7 +108,7 @@
}) {}
virtual ~VsockSocketAddress() {}
std::string toString() const override {
- return String8::format("cid %du port %du", mAddr.svm_cid, mAddr.svm_port).c_str();
+ return String8::format("cid %u port %u", mAddr.svm_cid, mAddr.svm_port).c_str();
}
const sockaddr* addr() const override { return reinterpret_cast<const sockaddr*>(&mAddr); }
size_t addrSize() const override { return sizeof(mAddr); }
@@ -110,15 +121,91 @@
// realizing value w/ this type at compile time to avoid ubsan abort
constexpr unsigned int kAnyCid = VMADDR_CID_ANY;
- return addServer(VsockSocketAddress(kAnyCid, port));
+ return setupSocketServer(VsockSocketAddress(kAnyCid, port));
}
bool RpcConnection::addVsockClient(unsigned int cid, unsigned int port) {
- return addClient(VsockSocketAddress(cid, port));
+ return addSocketClient(VsockSocketAddress(cid, 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)));
+
+ if (serverFd == -1) {
+ ALOGE("Could not connect to /dev/null: %s", strerror(errno));
+ return false;
+ }
+
+ addClient(std::move(serverFd));
+ return true;
+}
+
sp<IBinder> RpcConnection::getRootObject() {
ExclusiveSocket socket(sp<RpcConnection>::fromExisting(this), SocketUse::CLIENT);
return state()->getRootObject(socket.fd(), sp<RpcConnection>::fromExisting(this));
@@ -139,36 +226,35 @@
}
void RpcConnection::join() {
- // establish a connection
- {
- unique_fd clientFd(
- TEMP_FAILURE_RETRY(accept4(mServer.get(), nullptr, 0 /*length*/, SOCK_CLOEXEC)));
- if (clientFd < 0) {
- // If this log becomes confusing, should save more state from setupUnixDomainServer
- // in order to output here.
- ALOGE("Could not accept4 socket: %s", strerror(errno));
- return;
- }
-
- LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get());
-
- assignServerToThisThread(std::move(clientFd));
+ // TODO(b/185167543): do this dynamically, instead of from a static number
+ // of threads
+ unique_fd clientFd(
+ TEMP_FAILURE_RETRY(accept4(mServer.get(), nullptr, 0 /*length*/, SOCK_CLOEXEC)));
+ if (clientFd < 0) {
+ // If this log becomes confusing, should save more state from setupUnixDomainServer
+ // in order to output here.
+ ALOGE("Could not accept4 socket: %s", strerror(errno));
+ return;
}
- // We may not use the connection we just established (two threads might
- // establish connections for each other), but for now, just use one
- // server/socket connection.
- ExclusiveSocket socket(sp<RpcConnection>::fromExisting(this), SocketUse::SERVER);
+ LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get());
+
+ // must be registered to allow arbitrary client code executing commands to
+ // be able to do nested calls (we can't only read from it)
+ sp<ConnectionSocket> socket = assignServerToThisThread(std::move(clientFd));
while (true) {
status_t error =
- state()->getAndExecuteCommand(socket.fd(), sp<RpcConnection>::fromExisting(this));
+ state()->getAndExecuteCommand(socket->fd, sp<RpcConnection>::fromExisting(this));
if (error != OK) {
ALOGI("Binder socket thread closing w/ status %s", statusToString(error).c_str());
- return;
+ break;
}
}
+
+ LOG_ALWAYS_FATAL_IF(!removeServerSocket(socket),
+ "bad state: socket object guaranteed to be in list");
}
void RpcConnection::setForServer(const wp<RpcServer>& server) {
@@ -179,7 +265,7 @@
return mForServer;
}
-bool RpcConnection::addServer(const SocketAddress& addr) {
+bool RpcConnection::setupSocketServer(const SocketAddress& addr) {
LOG_ALWAYS_FATAL_IF(mServer.get() != -1, "Each RpcConnection can only have one server.");
unique_fd serverFd(
@@ -205,7 +291,7 @@
return true;
}
-bool RpcConnection::addClient(const SocketAddress& addr) {
+bool RpcConnection::addSocketClient(const SocketAddress& addr) {
unique_fd serverFd(
TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)));
if (serverFd == -1) {
@@ -222,18 +308,34 @@
LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get());
- std::lock_guard<std::mutex> _l(mSocketMutex);
- sp<ConnectionSocket> connection = sp<ConnectionSocket>::make();
- connection->fd = std::move(serverFd);
- mClients.push_back(connection);
+ addClient(std::move(serverFd));
return true;
}
-void RpcConnection::assignServerToThisThread(base::unique_fd&& fd) {
+void RpcConnection::addClient(unique_fd&& fd) {
std::lock_guard<std::mutex> _l(mSocketMutex);
sp<ConnectionSocket> connection = sp<ConnectionSocket>::make();
connection->fd = std::move(fd);
+ mClients.push_back(connection);
+}
+
+sp<RpcConnection::ConnectionSocket> RpcConnection::assignServerToThisThread(unique_fd&& fd) {
+ std::lock_guard<std::mutex> _l(mSocketMutex);
+ sp<ConnectionSocket> connection = sp<ConnectionSocket>::make();
+ connection->fd = std::move(fd);
+ connection->exclusiveTid = gettid();
mServers.push_back(connection);
+
+ return connection;
+}
+
+bool RpcConnection::removeServerSocket(const sp<ConnectionSocket>& socket) {
+ std::lock_guard<std::mutex> _l(mSocketMutex);
+ if (auto it = std::find(mServers.begin(), mServers.end(), socket); it != mServers.end()) {
+ mServers.erase(it);
+ return true;
+ }
+ return false;
}
RpcConnection::ExclusiveSocket::ExclusiveSocket(const sp<RpcConnection>& connection, SocketUse use)
@@ -248,37 +350,31 @@
// CHECK FOR DEDICATED CLIENT SOCKET
//
- // A server/looper should always use a dedicated connection.
- if (use != SocketUse::SERVER) {
- findSocket(tid, &exclusive, &available, mConnection->mClients,
- mConnection->mClientsOffset);
+ // A server/looper should always use a dedicated connection if available
+ findSocket(tid, &exclusive, &available, mConnection->mClients, mConnection->mClientsOffset);
- // WARNING: this assumes a server cannot request its client to send
- // a transaction, as mServers is excluded below.
- //
- // Imagine we have more than one thread in play, and a single thread
- // sends a synchronous, then an asynchronous command. Imagine the
- // asynchronous command is sent on the first client socket. Then, if
- // we naively send a synchronous command to that same socket, the
- // thread on the far side might be busy processing the asynchronous
- // command. So, we move to considering the second available thread
- // for subsequent calls.
- if (use == SocketUse::CLIENT_ASYNC && (exclusive != nullptr || available != nullptr)) {
- mConnection->mClientsOffset =
- (mConnection->mClientsOffset + 1) % mConnection->mClients.size();
- }
+ // WARNING: this assumes a server cannot request its client to send
+ // a transaction, as mServers is excluded below.
+ //
+ // Imagine we have more than one thread in play, and a single thread
+ // sends a synchronous, then an asynchronous command. Imagine the
+ // asynchronous command is sent on the first client socket. Then, if
+ // we naively send a synchronous command to that same socket, the
+ // thread on the far side might be busy processing the asynchronous
+ // command. So, we move to considering the second available thread
+ // for subsequent calls.
+ if (use == SocketUse::CLIENT_ASYNC && (exclusive != nullptr || available != nullptr)) {
+ mConnection->mClientsOffset =
+ (mConnection->mClientsOffset + 1) % mConnection->mClients.size();
}
- // USE SERVING SOCKET (to start serving or for nested transaction)
+ // USE SERVING SOCKET (for nested transaction)
//
// asynchronous calls cannot be nested
if (use != SocketUse::CLIENT_ASYNC) {
- // servers should start serving on an available thread only
- // otherwise, this should only be a nested call
- bool useAvailable = use == SocketUse::SERVER;
-
- findSocket(tid, &exclusive, (useAvailable ? &available : nullptr),
- mConnection->mServers, 0 /* index hint */);
+ // server sockets are always assigned to a thread
+ findSocket(tid, &exclusive, nullptr /*available*/, mConnection->mServers,
+ 0 /* index hint */);
}
// if our thread is already using a connection, prioritize using that
@@ -292,8 +388,6 @@
break;
}
- LOG_ALWAYS_FATAL_IF(use == SocketUse::SERVER, "Must create connection to join one.");
-
// in regular binder, this would usually be a deadlock :)
LOG_ALWAYS_FATAL_IF(mConnection->mClients.size() == 0,
"Not a client of any connection. You must create a connection to an "
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 755ff35..d934136 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -40,7 +40,7 @@
// We need to be able to send instructions over the socket for how to
// connect to a different server, and we also need to let the host
// process know that this is happening.
- ALOGE("Canot send binder from unrelated binder RPC connection.");
+ ALOGE("Cannot send binder from unrelated binder RPC connection.");
return INVALID_OPERATION;
}
@@ -498,19 +498,20 @@
}
}
- Parcel data;
- // transaction->data is owned by this function. Parcel borrows this data and
- // only holds onto it for the duration of this function call. Parcel will be
- // deleted before the 'transactionData' object.
- data.ipcSetDataReference(transaction->data,
- transactionData.size() - offsetof(RpcWireTransaction, data),
- nullptr /*object*/, 0 /*objectCount*/, do_nothing_to_transact_data);
- data.markForRpc(connection);
-
Parcel reply;
reply.markForRpc(connection);
if (replyStatus == OK) {
+ Parcel data;
+ // transaction->data is owned by this function. Parcel borrows this data and
+ // only holds onto it for the duration of this function call. Parcel will be
+ // deleted before the 'transactionData' object.
+ data.ipcSetDataReference(transaction->data,
+ transactionData.size() - offsetof(RpcWireTransaction, data),
+ nullptr /*object*/, 0 /*objectCount*/,
+ do_nothing_to_transact_data);
+ data.markForRpc(connection);
+
if (target) {
replyStatus = target->transact(transaction->code, data, &reply, transaction->flags);
} else {
diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl
index 2fabf94..75c4092 100644
--- a/libs/binder/aidl/android/os/IServiceManager.aidl
+++ b/libs/binder/aidl/android/os/IServiceManager.aidl
@@ -108,6 +108,11 @@
@utf8InCpp String[] getDeclaredInstances(@utf8InCpp String iface);
/**
+ * If updatable-via-apex, returns the APEX via which this is updated.
+ */
+ @nullable @utf8InCpp String updatableViaApex(@utf8InCpp String name);
+
+ /**
* Request a callback when the number of clients of the service changes.
* Used by LazyServiceRegistrar to dynamically stop services that have no clients.
*/
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 5f0d056..3dbe2c4 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -20,6 +20,8 @@
#include <utils/Vector.h>
#include <utils/String16.h>
+#include <optional>
+
namespace android {
// ----------------------------------------------------------------------
@@ -99,6 +101,12 @@
* Get all instances of a service as declared in the VINTF manifest
*/
virtual Vector<String16> getDeclaredInstances(const String16& interface) = 0;
+
+ /**
+ * If this instance is updatable via an APEX, returns the APEX with which
+ * this can be updated.
+ */
+ virtual std::optional<String16> updatableViaApex(const String16& name) = 0;
};
sp<IServiceManager> defaultServiceManager();
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 211790d..9578372 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -101,6 +101,10 @@
// is for an RPC transaction).
void markForBinder(const sp<IBinder>& binder);
+ // Whenever possible, markForBinder should be preferred. This method is
+ // called automatically on reply Parcels for RPC transactions.
+ void markForRpc(const sp<RpcConnection>& connection);
+
// Whether this Parcel is written for RPC transactions (after calls to
// markForBinder or markForRpc).
bool isForRpc() const;
@@ -536,10 +540,6 @@
const binder_size_t* objects, size_t objectsCount,
release_func relFunc);
- // Whenever possible, markForBinder should be preferred. This method is
- // called automatically on reply Parcels for RPC transactions.
- void markForRpc(const sp<RpcConnection>& connection);
-
status_t finishWrite(size_t len);
void releaseObjects();
void acquireObjects();
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index 0919648..b9db5d7 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -58,6 +58,7 @@
void spawnPooledThread(bool isMain);
status_t setThreadPoolMaxThreadCount(size_t maxThreads);
+ status_t enableOnewaySpamDetection(bool enable);
void giveThreadPoolName();
String8 getDriverName();
diff --git a/libs/binder/include/binder/RpcConnection.h b/libs/binder/include/binder/RpcConnection.h
index efa922d..2395e78 100644
--- a/libs/binder/include/binder/RpcConnection.h
+++ b/libs/binder/include/binder/RpcConnection.h
@@ -74,6 +74,25 @@
#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
+ * response will never be satisfied. All data sent here will be
+ * unceremoniously cast down the bottomless pit, /dev/null.
+ */
+ [[nodiscard]] bool addNullDebuggingClient();
+
+ /**
* Query the other side of the connection for the root object hosted by that
* process's RpcServer (if one exists)
*/
@@ -109,10 +128,6 @@
friend sp<RpcConnection>;
RpcConnection();
- bool addServer(const SocketAddress& address);
- bool addClient(const SocketAddress& address);
- void assignServerToThisThread(base::unique_fd&& fd);
-
struct ConnectionSocket : public RefBase {
base::unique_fd fd;
@@ -121,11 +136,16 @@
std::optional<pid_t> exclusiveTid;
};
+ bool setupSocketServer(const SocketAddress& address);
+ bool addSocketClient(const SocketAddress& address);
+ void addClient(base::unique_fd&& fd);
+ sp<ConnectionSocket> assignServerToThisThread(base::unique_fd&& fd);
+ bool removeServerSocket(const sp<ConnectionSocket>& socket);
+
enum class SocketUse {
CLIENT,
CLIENT_ASYNC,
CLIENT_REFCOUNT,
- SERVER,
};
// RAII object for connection socket
diff --git a/libs/binder/include/binder/Status.h b/libs/binder/include/binder/Status.h
index c30ae01..aaafa36 100644
--- a/libs/binder/include/binder/Status.h
+++ b/libs/binder/include/binder/Status.h
@@ -91,6 +91,9 @@
static Status fromExceptionCode(int32_t exceptionCode,
const char* message);
+ // warning: this is still considered an error if it is constructed with a
+ // zero value error code. Please use Status::ok() instead and avoid zero
+ // error codes
static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode);
static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode,
const String8& message);
diff --git a/libs/binder/include/private/binder/binder_module.h b/libs/binder/include/private/binder/binder_module.h
index 1579199..151235c 100644
--- a/libs/binder/include/private/binder/binder_module.h
+++ b/libs/binder/include/private/binder/binder_module.h
@@ -32,10 +32,6 @@
#include <sys/ioctl.h>
#include <linux/android/binder.h>
-#ifdef __cplusplus
-namespace android {
-#endif
-
#ifndef BR_FROZEN_REPLY
// Temporary definition of BR_FROZEN_REPLY. For production
// this will come from UAPI binder.h
@@ -88,8 +84,18 @@
};
#endif //BINDER_GET_FROZEN_INFO
-#ifdef __cplusplus
-} // namespace android
-#endif
+#ifndef BR_ONEWAY_SPAM_SUSPECT
+// Temporary definition of BR_ONEWAY_SPAM_SUSPECT. For production
+// this will come from UAPI binder.h
+#define BR_ONEWAY_SPAM_SUSPECT _IO('r', 19)
+#endif //BR_ONEWAY_SPAM_SUSPECT
+
+#ifndef BINDER_ENABLE_ONEWAY_SPAM_DETECTION
+/*
+ * Temporary definitions for oneway spam detection support. For the final version
+ * these will be defined in the UAPI binder.h file from upstream kernel.
+ */
+#define BINDER_ENABLE_ONEWAY_SPAM_DETECTION _IOW('b', 16, __u32)
+#endif //BINDER_ENABLE_ONEWAY_SPAM_DETECTION
#endif // _BINDER_MODULE_H_
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index b9adc9a..9e2050b 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -173,7 +173,7 @@
* Available since API level 29.
*
* \param interfaceDescriptor this is a unique identifier for the class. This is used internally for
- * sanity checks on transactions.
+ * validity checks on transactions. This should be utf-8.
* \param onCreate see AIBinder_Class_onCreate.
* \param onDestroy see AIBinder_Class_onDestroy.
* \param onTransact see AIBinder_Class_onTransact.
@@ -645,7 +645,9 @@
*
* \return the class descriptor string. This pointer will never be null; a
* descriptor is required to define a class. The pointer is owned by the class
- * and will remain valid as long as the class does.
+ * and will remain valid as long as the class does. For a local class, this will
+ * be the same value (not necessarily pointer equal) as is passed into
+ * AIBinder_Class_define. Format is utf-8.
*/
const char* AIBinder_Class_getDescriptor(const AIBinder_Class* clazz) __INTRODUCED_IN(31);
@@ -669,7 +671,7 @@
*
* \return whether "lhs < rhs" is true
*/
-bool AIBinder_lt(const AIBinder* lhs, const AIBinder* rhs);
+bool AIBinder_lt(const AIBinder* lhs, const AIBinder* rhs) __INTRODUCED_IN(31);
/**
* Clone an AIBinder_Weak. Useful because even if a weak binder promotes to a
@@ -683,7 +685,7 @@
* \return clone of the input parameter. This must be deleted with
* AIBinder_Weak_delete. Null if weak input parameter is also null.
*/
-AIBinder_Weak* AIBinder_Weak_clone(const AIBinder_Weak* weak);
+AIBinder_Weak* AIBinder_Weak_clone(const AIBinder_Weak* weak) __INTRODUCED_IN(31);
/**
* Whether AIBinder_Weak is less than another.
@@ -718,7 +720,7 @@
*
* \return whether "lhs < rhs" is true
*/
-bool AIBinder_Weak_lt(const AIBinder_Weak* lhs, const AIBinder_Weak* rhs);
+bool AIBinder_Weak_lt(const AIBinder_Weak* lhs, const AIBinder_Weak* rhs) __INTRODUCED_IN(31);
__END_DECLS
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
index 5516914..a90b4aa 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -124,6 +124,15 @@
__INTRODUCED_IN(31);
/**
+ * Check if a service is updatable via an APEX module.
+ *
+ * \param instance identifier of the service
+ *
+ * \return whether the interface is updatable via APEX
+ */
+bool AServiceManager_isUpdatableViaApex(const char* instance) __INTRODUCED_IN(31);
+
+/**
* Prevent lazy services without client from shutting down their process
*
* \param persist 'true' if the process should not exit.
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 67c85b6..7d4b82e 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -118,14 +118,15 @@
AIBinder_getCallingSid; # apex
AIBinder_setRequestingSid; # apex
AParcel_markSensitive; # llndk
- AServiceManager_isDeclared; # apex llndk
AServiceManager_forEachDeclaredInstance; # apex llndk
- AServiceManager_registerLazyService; # llndk
- AServiceManager_waitForService; # apex llndk
AServiceManager_forceLazyServicesPersist; # llndk
+ AServiceManager_isDeclared; # apex llndk
+ AServiceManager_isUpdatableViaApex; # apex
+ AServiceManager_reRegister; # llndk
+ AServiceManager_registerLazyService; # llndk
AServiceManager_setActiveServicesCallback; # llndk
AServiceManager_tryUnregister; # llndk
- AServiceManager_reRegister; # llndk
+ AServiceManager_waitForService; # apex llndk
AIBinder_forceDowngradeToSystemStability; # apex
AIBinder_forceDowngradeToVendorStability; # llndk
diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp
index 1ccd0d2..7649a26 100644
--- a/libs/binder/ndk/service_manager.cpp
+++ b/libs/binder/ndk/service_manager.cpp
@@ -105,6 +105,14 @@
callback(String8(instance).c_str(), context);
}
}
+bool AServiceManager_isUpdatableViaApex(const char* instance) {
+ if (instance == nullptr) {
+ return false;
+ }
+
+ sp<IServiceManager> sm = defaultServiceManager();
+ return sm->updatableViaApex(String16(instance)) != std::nullopt;
+}
void AServiceManager_forceLazyServicesPersist(bool persist) {
auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
serviceRegistrar.forcePersist(persist);
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 496a915..1c43948 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -280,6 +280,11 @@
EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get()));
}
+TEST(NdkBinder, IsUpdatable) {
+ bool isUpdatable = AServiceManager_isUpdatableViaApex("android.hardware.light.ILights/default");
+ EXPECT_EQ(isUpdatable, false);
+}
+
// This is too slow
TEST(NdkBinder, CheckLazyServiceShutDown) {
ndk::SpAIBinder binder(AServiceManager_waitForService(kLazyBinderNdkUnitTestService));
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index e12a429..57c9013 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -65,15 +65,15 @@
// 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 0bf76c6..607860f 100644
--- a/libs/binder/rust/tests/Android.bp
+++ b/libs/binder/rust/tests/Android.bp
@@ -114,8 +114,8 @@
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/Android.bp b/libs/binder/tests/Android.bp
index afc4b1b..f303b7c 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -151,6 +151,27 @@
require_root: true,
}
+cc_benchmark {
+ name: "binderRpcBenchmark",
+ defaults: ["binder_test_defaults"],
+ host_supported: true,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+ srcs: [
+ "binderRpcBenchmark.cpp",
+ "IBinderRpcBenchmark.aidl",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "liblog",
+ "libutils",
+ ],
+}
+
cc_test {
name: "binderThroughputTest",
defaults: ["binder_test_defaults"],
diff --git a/libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h b/libs/binder/tests/IBinderRpcBenchmark.aidl
similarity index 69%
copy from libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
copy to libs/binder/tests/IBinderRpcBenchmark.aidl
index b92a6a9..1457422 100644
--- a/libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
+++ b/libs/binder/tests/IBinderRpcBenchmark.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -14,11 +14,7 @@
* limitations under the License.
*/
-#pragma once
-
-#include <binder/Parcel.h>
-#include <fuzzer/FuzzedDataProvider.h>
-
-namespace android {
-void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider);
-} // namespace android
+interface IBinderRpcBenchmark {
+ @utf8InCpp String repeatString(@utf8InCpp String str);
+ IBinder repeatBinder(IBinder binder);
+}
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index e2193fa..dc8c0f1 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -88,6 +88,7 @@
BINDER_LIB_TEST_GETPID,
BINDER_LIB_TEST_ECHO_VECTOR,
BINDER_LIB_TEST_REJECT_BUF,
+ BINDER_LIB_TEST_CAN_GET_SID,
};
pid_t start_server_process(int arg2, bool usePoll = false)
@@ -1192,6 +1193,14 @@
EXPECT_NE(NO_ERROR, ret);
}
+TEST_F(BinderLibTest, GotSid) {
+ sp<IBinder> server = addServer();
+
+ Parcel data;
+ status_t ret = server->transact(BINDER_LIB_TEST_CAN_GET_SID, data, nullptr);
+ EXPECT_EQ(OK, ret);
+}
+
class BinderLibTestService : public BBinder
{
public:
@@ -1494,6 +1503,9 @@
case BINDER_LIB_TEST_REJECT_BUF: {
return data.objectsCount() == 0 ? BAD_VALUE : NO_ERROR;
}
+ case BINDER_LIB_TEST_CAN_GET_SID: {
+ return IPCThreadState::self()->getCallingSid() == nullptr ? BAD_VALUE : NO_ERROR;
+ }
default:
return UNKNOWN_TRANSACTION;
};
diff --git a/libs/binder/tests/binderRpcBenchmark.cpp b/libs/binder/tests/binderRpcBenchmark.cpp
new file mode 100644
index 0000000..7c82226
--- /dev/null
+++ b/libs/binder/tests/binderRpcBenchmark.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2021 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 <BnBinderRpcBenchmark.h>
+#include <android-base/logging.h>
+#include <benchmark/benchmark.h>
+#include <binder/Binder.h>
+#include <binder/RpcConnection.h>
+#include <binder/RpcServer.h>
+
+#include <thread>
+
+#include <sys/types.h>
+#include <unistd.h>
+
+using android::BBinder;
+using android::IBinder;
+using android::interface_cast;
+using android::OK;
+using android::RpcConnection;
+using android::RpcServer;
+using android::sp;
+using android::binder::Status;
+
+class MyBinderRpcBenchmark : public BnBinderRpcBenchmark {
+ Status repeatString(const std::string& str, std::string* out) override {
+ *out = str;
+ return Status::ok();
+ }
+ Status repeatBinder(const sp<IBinder>& str, sp<IBinder>* out) override {
+ *out = str;
+ return Status::ok();
+ }
+};
+
+static sp<RpcConnection> gConnection = RpcConnection::make();
+
+void BM_getRootObject(benchmark::State& state) {
+ while (state.KeepRunning()) {
+ CHECK(gConnection->getRootObject() != nullptr);
+ }
+}
+BENCHMARK(BM_getRootObject);
+
+void BM_pingTransaction(benchmark::State& state) {
+ sp<IBinder> binder = gConnection->getRootObject();
+ CHECK(binder != nullptr);
+
+ while (state.KeepRunning()) {
+ CHECK_EQ(OK, binder->pingBinder());
+ }
+}
+BENCHMARK(BM_pingTransaction);
+
+void BM_repeatString(benchmark::State& state) {
+ sp<IBinder> binder = gConnection->getRootObject();
+ CHECK(binder != nullptr);
+ sp<IBinderRpcBenchmark> iface = interface_cast<IBinderRpcBenchmark>(binder);
+ CHECK(iface != nullptr);
+
+ // Googlers might see go/another-look-at-aidl-hidl-perf
+ //
+ // When I checked in July 2019, 99.5% of AIDL transactions and 99.99% of HIDL
+ // transactions were less than one page in size (system wide during a test
+ // involving media and camera). This is why this diverges from
+ // binderThroughputTest and hwbinderThroughputTest. Future consideration - get
+ // this data on continuous integration. Here we are testing sending a
+ // transaction of twice this size. In other cases, we should focus on
+ // benchmarks of particular usecases. If individual binder transactions like
+ // the ones tested here are fast, then Android performance will be dominated
+ // by how many binder calls work together (and by factors like the scheduler,
+ // thermal throttling, core choice, etc..).
+ std::string str = std::string(getpagesize() * 2, 'a');
+ CHECK_EQ(str.size(), getpagesize() * 2);
+
+ while (state.KeepRunning()) {
+ std::string out;
+ Status ret = iface->repeatString(str, &out);
+ CHECK(ret.isOk()) << ret;
+ }
+}
+BENCHMARK(BM_repeatString);
+
+void BM_repeatBinder(benchmark::State& state) {
+ sp<IBinder> binder = gConnection->getRootObject();
+ CHECK(binder != nullptr);
+ sp<IBinderRpcBenchmark> iface = interface_cast<IBinderRpcBenchmark>(binder);
+ CHECK(iface != nullptr);
+
+ while (state.KeepRunning()) {
+ // force creation of a new address
+ sp<IBinder> binder = sp<BBinder>::make();
+
+ sp<IBinder> out;
+ Status ret = iface->repeatBinder(binder, &out);
+ CHECK(ret.isOk()) << ret;
+ }
+}
+BENCHMARK(BM_repeatBinder);
+
+int main(int argc, char** argv) {
+ ::benchmark::Initialize(&argc, argv);
+ if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1;
+
+ std::string addr = std::string(getenv("TMPDIR") ?: "/tmp") + "/binderRpcBenchmark";
+ (void)unlink(addr.c_str());
+
+ std::thread([addr]() {
+ sp<RpcServer> server = RpcServer::make();
+ server->setRootObject(sp<MyBinderRpcBenchmark>::make());
+
+ server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
+
+ sp<RpcConnection> connection = server->addClientConnection();
+ CHECK(connection->setupUnixDomainServer(addr.c_str()));
+
+ connection->join();
+ }).detach();
+
+ for (size_t tries = 0; tries < 5; tries++) {
+ usleep(10000);
+ if (gConnection->addUnixDomainClient(addr.c_str())) goto success;
+ }
+ LOG(FATAL) << "Could not connect.";
+success:
+
+ ::benchmark::RunSpecifiedBenchmarks();
+}
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index a51c987..dd68fdb 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -80,11 +80,10 @@
sp<RpcConnection> connection;
Status sendString(const std::string& str) override {
- std::cout << "Child received string: " << str << std::endl;
+ (void)str;
return Status::ok();
}
Status doubleString(const std::string& str, std::string* strstr) override {
- std::cout << "Child received string to double: " << str << std::endl;
*strstr = str + str;
return Status::ok();
}
@@ -199,13 +198,8 @@
static std::string allocateSocketAddress() {
static size_t id = 0;
- static bool gUseTmp = access("/tmp/", F_OK) != -1;
-
- if (gUseTmp) {
- return "/tmp/binderRpcTest_" + std::to_string(id++);
- } else {
- return "/dev/binderRpcTest_" + std::to_string(id++);
- }
+ std::string temp = getenv("TMPDIR") ?: "/tmp";
+ return temp + "/binderRpcTest_" + std::to_string(id++);
};
struct ProcessConnection {
@@ -262,6 +256,7 @@
#ifdef __BIONIC__
VSOCK,
#endif // __BIONIC__
+ INET,
};
static inline std::string PrintSocketType(const testing::TestParamInfo<SocketType>& info) {
switch (info.param) {
@@ -271,6 +266,8 @@
case SocketType::VSOCK:
return "vm_socket";
#endif // __BIONIC__
+ case SocketType::INET:
+ return "inet_socket";
default:
LOG_ALWAYS_FATAL("Unknown socket type");
return "";
@@ -310,6 +307,9 @@
CHECK(connection->setupVsockServer(port));
break;
#endif // __BIONIC__
+ case SocketType::INET:
+ CHECK(connection->setupInetServer(port));
+ break;
default:
LOG_ALWAYS_FATAL("Unknown socket type");
}
@@ -340,6 +340,9 @@
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");
}
@@ -745,7 +748,7 @@
threads.push_back(std::thread([&] {
for (size_t j = 0; j < kNumCalls; j++) {
sp<IBinder> out;
- proc.rootIface->repeatBinder(proc.rootBinder, &out);
+ EXPECT_OK(proc.rootIface->repeatBinder(proc.rootBinder, &out));
EXPECT_EQ(proc.rootBinder, out);
}
}));
@@ -754,6 +757,28 @@
for (auto& t : threads) t.join();
}
+TEST_P(BinderRpc, OnewayStressTest) {
+ constexpr size_t kNumClientThreads = 10;
+ constexpr size_t kNumServerThreads = 10;
+ constexpr size_t kNumCalls = 100;
+
+ auto proc = createRpcTestSocketServerProcess(kNumServerThreads);
+
+ std::vector<std::thread> threads;
+ for (size_t i = 0; i < kNumClientThreads; i++) {
+ threads.push_back(std::thread([&] {
+ for (size_t j = 0; j < kNumCalls; j++) {
+ EXPECT_OK(proc.rootIface->sendString("a"));
+ }
+
+ // check threads are not stuck
+ EXPECT_OK(proc.rootIface->sleepMs(250));
+ }));
+ }
+
+ for (auto& t : threads) t.join();
+}
+
TEST_P(BinderRpc, OnewayCallDoesNotWait) {
constexpr size_t kReallyLongTimeMs = 100;
constexpr size_t kSleepMs = kReallyLongTimeMs * 5;
@@ -857,12 +882,13 @@
}
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/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp
index ffb3ef2..c857d62 100644
--- a/libs/binder/tests/binderSafeInterfaceTest.cpp
+++ b/libs/binder/tests/binderSafeInterfaceTest.cpp
@@ -226,7 +226,7 @@
IncrementNativeHandle,
IncrementNoCopyNoMove,
IncrementParcelableVector,
- ToUpper,
+ DoubleString,
CallMeBack,
IncrementInt32,
IncrementUint32,
@@ -256,7 +256,7 @@
virtual status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const = 0;
virtual status_t increment(const std::vector<TestParcelable>& a,
std::vector<TestParcelable>* aPlusOne) const = 0;
- virtual status_t toUpper(const String8& str, String8* upperStr) const = 0;
+ virtual status_t doubleString(const String8& str, String8* doubleStr) const = 0;
// As mentioned above, sp<IBinder> is already tested by setDeathToken
virtual void callMeBack(const sp<ICallback>& callback, int32_t a) const = 0;
virtual status_t increment(int32_t a, int32_t* aPlusOne) const = 0;
@@ -329,9 +329,10 @@
std::vector<TestParcelable>*);
return callRemote<Signature>(Tag::IncrementParcelableVector, a, aPlusOne);
}
- status_t toUpper(const String8& str, String8* upperStr) const override {
+ status_t doubleString(const String8& str, String8* doubleStr) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
- return callRemote<decltype(&ISafeInterfaceTest::toUpper)>(Tag::ToUpper, str, upperStr);
+ return callRemote<decltype(&ISafeInterfaceTest::doubleString)>(Tag::DoubleString, str,
+ doubleStr);
}
void callMeBack(const sp<ICallback>& callback, int32_t a) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
@@ -454,10 +455,9 @@
}
return NO_ERROR;
}
- status_t toUpper(const String8& str, String8* upperStr) const override {
+ status_t doubleString(const String8& str, String8* doubleStr) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
- *upperStr = str;
- upperStr->toUpper();
+ *doubleStr = str + str;
return NO_ERROR;
}
void callMeBack(const sp<ICallback>& callback, int32_t a) const override {
@@ -548,8 +548,8 @@
std::vector<TestParcelable>*) const;
return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
}
- case ISafeInterfaceTest::Tag::ToUpper: {
- return callLocal(data, reply, &ISafeInterfaceTest::toUpper);
+ case ISafeInterfaceTest::Tag::DoubleString: {
+ return callLocal(data, reply, &ISafeInterfaceTest::doubleString);
}
case ISafeInterfaceTest::Tag::CallMeBack: {
return callLocalAsync(data, reply, &ISafeInterfaceTest::callMeBack);
@@ -726,12 +726,12 @@
}
}
-TEST_F(SafeInterfaceTest, TestToUpper) {
- const String8 str{"Hello, world!"};
- String8 upperStr;
- status_t result = mSafeInterfaceTest->toUpper(str, &upperStr);
+TEST_F(SafeInterfaceTest, TestDoubleString) {
+ const String8 str{"asdf"};
+ String8 doubleStr;
+ status_t result = mSafeInterfaceTest->doubleString(str, &doubleStr);
ASSERT_EQ(NO_ERROR, result);
- ASSERT_TRUE(upperStr == String8{"HELLO, WORLD!"});
+ ASSERT_TRUE(doubleStr == String8{"asdfasdf"});
}
TEST_F(SafeInterfaceTest, TestCallMeBack) {
diff --git a/libs/binder/tests/binderStabilityTest.cpp b/libs/binder/tests/binderStabilityTest.cpp
index cb309bd..2ce13df 100644
--- a/libs/binder/tests/binderStabilityTest.cpp
+++ b/libs/binder/tests/binderStabilityTest.cpp
@@ -192,6 +192,8 @@
EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
android::defaultServiceManager()->addService(String16("."), vintfServer)) << instance8;
EXPECT_FALSE(android::defaultServiceManager()->isDeclared(instance)) << instance8;
+ EXPECT_EQ(std::nullopt, android::defaultServiceManager()->updatableViaApex(instance))
+ << instance8;
}
}
diff --git a/libs/binder/parcel_fuzzer/Android.bp b/libs/binder/tests/parcel_fuzzer/Android.bp
similarity index 100%
rename from libs/binder/parcel_fuzzer/Android.bp
rename to libs/binder/tests/parcel_fuzzer/Android.bp
diff --git a/libs/binder/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/binder.cpp
rename to libs/binder/tests/parcel_fuzzer/binder.cpp
diff --git a/libs/binder/parcel_fuzzer/binder.h b/libs/binder/tests/parcel_fuzzer/binder.h
similarity index 100%
rename from libs/binder/parcel_fuzzer/binder.h
rename to libs/binder/tests/parcel_fuzzer/binder.h
diff --git a/libs/binder/parcel_fuzzer/binder_ndk.cpp b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/binder_ndk.cpp
rename to libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
diff --git a/libs/binder/parcel_fuzzer/binder_ndk.h b/libs/binder/tests/parcel_fuzzer/binder_ndk.h
similarity index 97%
rename from libs/binder/parcel_fuzzer/binder_ndk.h
rename to libs/binder/tests/parcel_fuzzer/binder_ndk.h
index e69d9c1..cf24ab9 100644
--- a/libs/binder/parcel_fuzzer/binder_ndk.h
+++ b/libs/binder/tests/parcel_fuzzer/binder_ndk.h
@@ -23,7 +23,7 @@
// libbinder_ndk doesn't export this header which breaks down its API for NDK
// and APEX users, but we need access to it to fuzz.
-#include "../ndk/parcel_internal.h"
+#include "../../ndk/parcel_internal.h"
class NdkParcelAdapter {
public:
diff --git a/libs/binder/parcel_fuzzer/hwbinder.cpp b/libs/binder/tests/parcel_fuzzer/hwbinder.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/hwbinder.cpp
rename to libs/binder/tests/parcel_fuzzer/hwbinder.cpp
diff --git a/libs/binder/parcel_fuzzer/hwbinder.h b/libs/binder/tests/parcel_fuzzer/hwbinder.h
similarity index 100%
rename from libs/binder/parcel_fuzzer/hwbinder.h
rename to libs/binder/tests/parcel_fuzzer/hwbinder.h
diff --git a/libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h
similarity index 100%
rename from libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h
rename to libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h
diff --git a/libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
similarity index 80%
rename from libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
rename to libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
index b92a6a9..749bf21 100644
--- a/libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
+++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
@@ -20,5 +20,12 @@
#include <fuzzer/FuzzedDataProvider.h>
namespace android {
+/**
+ * Fill parcel data, including some random binder objects and FDs
+ */
void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider);
+/**
+ * Fill parcel data, but don't fill any objects.
+ */
+void fillRandomParcelData(Parcel* p, FuzzedDataProvider&& provider);
} // namespace android
diff --git a/libs/binder/parcel_fuzzer/main.cpp b/libs/binder/tests/parcel_fuzzer/main.cpp
similarity index 89%
rename from libs/binder/parcel_fuzzer/main.cpp
rename to libs/binder/tests/parcel_fuzzer/main.cpp
index 78606cc..332e2ad 100644
--- a/libs/binder/parcel_fuzzer/main.cpp
+++ b/libs/binder/tests/parcel_fuzzer/main.cpp
@@ -23,6 +23,7 @@
#include <iostream>
#include <android-base/logging.h>
+#include <binder/RpcConnection.h>
#include <fuzzbinder/random_parcel.h>
#include <fuzzer/FuzzedDataProvider.h>
@@ -32,6 +33,8 @@
#include <sys/time.h>
using android::fillRandomParcel;
+using android::RpcConnection;
+using android::sp;
void fillRandomParcel(::android::hardware::Parcel* p, FuzzedDataProvider&& provider) {
// TODO: functionality to create random parcels for libhwbinder parcels
@@ -56,7 +59,18 @@
provider.ConsumeIntegralInRange<size_t>(0, maxInstructions));
P p;
- fillRandomParcel(&p, std::move(provider));
+ if constexpr (std::is_same_v<P, android::Parcel>) {
+ if (provider.ConsumeBool()) {
+ auto connection = sp<RpcConnection>::make();
+ CHECK(connection->addNullDebuggingClient());
+ p.markForRpc(connection);
+ fillRandomParcelData(&p, std::move(provider));
+ } else {
+ fillRandomParcel(&p, std::move(provider));
+ }
+ } else {
+ fillRandomParcel(&p, std::move(provider));
+ }
// since we are only using a byte to index
CHECK(reads.size() <= 255) << reads.size();
diff --git a/libs/binder/parcel_fuzzer/parcel_fuzzer.h b/libs/binder/tests/parcel_fuzzer/parcel_fuzzer.h
similarity index 100%
rename from libs/binder/parcel_fuzzer/parcel_fuzzer.h
rename to libs/binder/tests/parcel_fuzzer/parcel_fuzzer.h
diff --git a/libs/binder/parcel_fuzzer/random_fd.cpp b/libs/binder/tests/parcel_fuzzer/random_fd.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/random_fd.cpp
rename to libs/binder/tests/parcel_fuzzer/random_fd.cpp
diff --git a/libs/binder/parcel_fuzzer/random_parcel.cpp b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
similarity index 93%
rename from libs/binder/parcel_fuzzer/random_parcel.cpp
rename to libs/binder/tests/parcel_fuzzer/random_parcel.cpp
index 9ca4c8a..b045a22 100644
--- a/libs/binder/parcel_fuzzer/random_parcel.cpp
+++ b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
@@ -75,4 +75,9 @@
}
}
+void fillRandomParcelData(Parcel* p, FuzzedDataProvider&& provider) {
+ std::vector<uint8_t> data = provider.ConsumeBytes<uint8_t>(provider.remaining_bytes());
+ CHECK(OK == p->write(data.data(), data.size()));
+}
+
} // namespace android
diff --git a/libs/binder/parcel_fuzzer/util.cpp b/libs/binder/tests/parcel_fuzzer/util.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/util.cpp
rename to libs/binder/tests/parcel_fuzzer/util.cpp
diff --git a/libs/binder/parcel_fuzzer/util.h b/libs/binder/tests/parcel_fuzzer/util.h
similarity index 100%
rename from libs/binder/parcel_fuzzer/util.h
rename to libs/binder/tests/parcel_fuzzer/util.h
diff --git a/libs/binder/tests/fuzzers/Android.bp b/libs/binder/tests/unit_fuzzers/Android.bp
similarity index 100%
rename from libs/binder/tests/fuzzers/Android.bp
rename to libs/binder/tests/unit_fuzzers/Android.bp
diff --git a/libs/binder/tests/fuzzers/BinderFuzz.cpp b/libs/binder/tests/unit_fuzzers/BinderFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/BinderFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/BinderFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/BinderFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/BinderFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/BinderFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/BinderFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/BpBinderFuzz.cpp b/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/BpBinderFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/BpBinderFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/BpBinderFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/BpBinderFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/BpBinderFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/BufferedTextOutputFuzz.cpp b/libs/binder/tests/unit_fuzzers/BufferedTextOutputFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/BufferedTextOutputFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/BufferedTextOutputFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/IBinderFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/IBinderFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/IBinderFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/IBinderFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/MemoryDealerFuzz.cpp b/libs/binder/tests/unit_fuzzers/MemoryDealerFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/MemoryDealerFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/MemoryDealerFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/PersistableBundleFuzz.cpp b/libs/binder/tests/unit_fuzzers/PersistableBundleFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/PersistableBundleFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/PersistableBundleFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/PersistableBundleFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/PersistableBundleFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/PersistableBundleFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/PersistableBundleFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/StabilityFuzz.cpp b/libs/binder/tests/unit_fuzzers/StabilityFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/StabilityFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/StabilityFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/StabilityFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/StabilityFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/StabilityFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/StabilityFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/StatusFuzz.cpp b/libs/binder/tests/unit_fuzzers/StatusFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/StatusFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/StatusFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/StatusFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/StatusFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/StatusFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/StatusFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/TextOutputFuzz.cpp b/libs/binder/tests/unit_fuzzers/TextOutputFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/TextOutputFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/TextOutputFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/commonFuzzHelpers.h b/libs/binder/tests/unit_fuzzers/commonFuzzHelpers.h
similarity index 100%
rename from libs/binder/tests/fuzzers/commonFuzzHelpers.h
rename to libs/binder/tests/unit_fuzzers/commonFuzzHelpers.h
diff --git a/libs/fakeservicemanager/ServiceManager.cpp b/libs/fakeservicemanager/ServiceManager.cpp
index 4ecbe53..761e45c 100644
--- a/libs/fakeservicemanager/ServiceManager.cpp
+++ b/libs/fakeservicemanager/ServiceManager.cpp
@@ -73,4 +73,9 @@
return out;
}
+std::optional<String16> ServiceManager::updatableViaApex(const String16& name) {
+ (void)name;
+ return std::nullopt;
+}
+
} // namespace android
diff --git a/libs/fakeservicemanager/ServiceManager.h b/libs/fakeservicemanager/ServiceManager.h
index 4ef47fb..e26c21b 100644
--- a/libs/fakeservicemanager/ServiceManager.h
+++ b/libs/fakeservicemanager/ServiceManager.h
@@ -19,6 +19,7 @@
#include <binder/IServiceManager.h>
#include <map>
+#include <optional>
namespace android {
@@ -48,6 +49,8 @@
Vector<String16> getDeclaredInstances(const String16& iface) override;
+ std::optional<String16> updatableViaApex(const String16& name) override;
+
private:
std::map<String16, sp<IBinder>> mNameToService;
};
diff --git a/libs/permission/Android.bp b/libs/permission/Android.bp
new file mode 100644
index 0000000..a5712b3
--- /dev/null
+++ b/libs/permission/Android.bp
@@ -0,0 +1,23 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
+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
similarity index 100%
rename from libs/binder/AppOpsManager.cpp
rename to libs/permission/AppOpsManager.cpp
diff --git a/libs/binder/IAppOpsCallback.cpp b/libs/permission/IAppOpsCallback.cpp
similarity index 100%
rename from libs/binder/IAppOpsCallback.cpp
rename to libs/permission/IAppOpsCallback.cpp
diff --git a/libs/binder/IAppOpsService.cpp b/libs/permission/IAppOpsService.cpp
similarity index 100%
rename from libs/binder/IAppOpsService.cpp
rename to libs/permission/IAppOpsService.cpp
diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/permission/include/binder/AppOpsManager.h
similarity index 100%
rename from libs/binder/include/binder/AppOpsManager.h
rename to libs/permission/include/binder/AppOpsManager.h
diff --git a/libs/binder/include/binder/IAppOpsCallback.h b/libs/permission/include/binder/IAppOpsCallback.h
similarity index 100%
rename from libs/binder/include/binder/IAppOpsCallback.h
rename to libs/permission/include/binder/IAppOpsCallback.h
diff --git a/libs/binder/include/binder/IAppOpsService.h b/libs/permission/include/binder/IAppOpsService.h
similarity index 100%
rename from libs/binder/include/binder/IAppOpsService.h
rename to libs/permission/include/binder/IAppOpsService.h
diff --git a/libs/sensor/Android.bp b/libs/sensor/Android.bp
index 497c33c..edd453a 100644
--- a/libs/sensor/Android.bp
+++ b/libs/sensor/Android.bp
@@ -48,11 +48,10 @@
"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 9aecaff..4151b45 100644
--- a/services/sensorservice/Android.bp
+++ b/services/sensorservice/Android.bp
@@ -54,6 +54,7 @@
"libbinder",
"libsensor",
"libsensorprivacy",
+ "libpermission",
"libprotoutil",
"libcrypto",
"libbase",
@@ -74,6 +75,7 @@
"libactivitymanager_aidl",
"libsensor",
"libsensorprivacy",
+ "libpermission",
],
}