Merge "Add surfaceflinger owners to libgui OWNERS"
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 097bc53..2ce3fb0 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -7,6 +7,7 @@
rustfmt = --config-path=rustfmt.toml
# Only turn on clang-format check for the following subfolders.
clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
+ cmds/dumpstate/
cmds/idlcli/
cmds/installd/
cmds/servicemanager/
diff --git a/cmds/atrace/Android.bp b/cmds/atrace/Android.bp
index aa0ef25..1c4e63e 100644
--- a/cmds/atrace/Android.bp
+++ b/cmds/atrace/Android.bp
@@ -38,6 +38,7 @@
],
init_rc: ["atrace.rc"],
+ required: ["ftrace_synthetic_events.conf"],
product_variables: {
debuggable: {
@@ -45,3 +46,8 @@
},
},
}
+
+prebuilt_etc {
+ name: "ftrace_synthetic_events.conf",
+ src: "ftrace_synthetic_events.conf",
+}
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 07e586e..c3cf2c2 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -291,12 +291,10 @@
# Setup synthetic events
chmod 0666 /sys/kernel/tracing/synthetic_events
chmod 0666 /sys/kernel/debug/tracing/synthetic_events
+ copy /system/etc/ftrace_synthetic_events.conf /sys/kernel/tracing/synthetic_events
+ copy /system/etc/ftrace_synthetic_events.conf /sys/kernel/debug/tracing/synthetic_events
- # rss_stat_throttled
- write /sys/kernel/tracing/synthetic_events "rss_stat_throttled unsigned int mm_id; unsigned int curr; int member; long size"
- write /sys/kernel/debug/tracing/synthetic_events "rss_stat_throttled unsigned int mm_id; unsigned int curr; int member; long size"
-
- # allow creating event triggers
+ # allow creating rss_stat event triggers
chmod 0666 /sys/kernel/tracing/events/kmem/rss_stat/trigger
chmod 0666 /sys/kernel/debug/tracing/events/kmem/rss_stat/trigger
@@ -304,6 +302,14 @@
chmod 0666 /sys/kernel/tracing/events/synthetic/rss_stat_throttled/enable
chmod 0666 /sys/kernel/debug/tracing/events/synthetic/rss_stat_throttled/enable
+ # allow creating suspend_resume triggers
+ chmod 0666 /sys/kernel/tracing/events/power/suspend_resume/trigger
+ chmod 0666 /sys/kernel/debug/tracing/events/power/suspend_resume/trigger
+
+ # allow enabling suspend_resume_minimal
+ chmod 0666 /sys/kernel/tracing/events/synthetic/suspend_resume_minimal/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/synthetic/suspend_resume_minimal/enable
+
on late-init && property:ro.boot.fastboot.boottrace=enabled
setprop debug.atrace.tags.enableflags 802922
setprop persist.traced.enable 0
@@ -527,6 +533,7 @@
# Run atrace with the categories written in a file
service boottrace /system/bin/atrace --async_start -f /data/misc/boottrace/categories
+ user root
disabled
oneshot
diff --git a/cmds/atrace/ftrace_synthetic_events.conf b/cmds/atrace/ftrace_synthetic_events.conf
new file mode 100644
index 0000000..e2257fe
--- /dev/null
+++ b/cmds/atrace/ftrace_synthetic_events.conf
@@ -0,0 +1,2 @@
+rss_stat_throttled unsigned int mm_id; unsigned int curr; int member; long size
+suspend_resume_minimal bool start
diff --git a/cmds/cmd/fuzzer/Android.bp b/cmds/cmd/fuzzer/Android.bp
index a65f6de..faf461a 100644
--- a/cmds/cmd/fuzzer/Android.bp
+++ b/cmds/cmd/fuzzer/Android.bp
@@ -42,5 +42,13 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libcmd",
+ vector: "local_no_privileges_required",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 8c77255..dc0e26b 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -814,6 +814,8 @@
printf("Kernel: ");
DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
+ printf("Bootconfig: ");
+ DumpFileToFd(STDOUT_FILENO, "", "/proc/bootconfig");
printf("Uptime: ");
RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
CommandOptions::WithTimeout(1).Always().Build());
@@ -1252,7 +1254,8 @@
dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
} else {
- status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID,
+ status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
+ Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
service, args);
if (status == OK) {
dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
@@ -1271,6 +1274,9 @@
dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
bool dump_complete = (status == OK);
dumpsys.stopDumpThread(dump_complete);
+ } else {
+ MYLOGE("Failed to start dump thread for service: %s, status: %d",
+ String8(service).c_str(), status);
}
}
@@ -2059,6 +2065,10 @@
SEC_TO_MSEC(10));
RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
SEC_TO_MSEC(10));
+ RunDumpsys("DUMPSYS", {"isub"}, CommandOptions::WithTimeout(90).Build(),
+ SEC_TO_MSEC(10));
+ RunDumpsys("DUMPSYS", {"telecom"}, CommandOptions::WithTimeout(90).Build(),
+ SEC_TO_MSEC(10));
if (include_sensitive_info) {
// Contains raw IP addresses, omit from reports on user builds.
RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
@@ -2189,6 +2199,16 @@
continue;
}
+ // Skip cached processes.
+ if (IsCached(pid)) {
+ // For consistency, the header and footer to this message match those
+ // dumped by debuggerd in the success case.
+ dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
+ dprintf(fd, "Dump skipped for cached process.\n");
+ dprintf(fd, "---- end %d ----", pid);
+ continue;
+ }
+
const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
std::string exe;
if (!android::base::Readlink(link_name, &exe)) {
@@ -2219,8 +2239,7 @@
const uint64_t start = Nanotime();
const int ret = dump_backtrace_to_file_timeout(
- pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
- is_java_process ? 5 : 20, fd);
+ pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
if (ret == -1) {
// For consistency, the header and footer to this message match those
@@ -2791,6 +2810,7 @@
options->do_screenshot = false;
break;
case Dumpstate::BugreportMode::BUGREPORT_WEAR:
+ options->do_vibrate = false;
options->do_progress_updates = true;
options->do_screenshot = is_screenshot_requested;
break;
diff --git a/cmds/dumpstate/dumpstate.rc b/cmds/dumpstate/dumpstate.rc
index a80da4e..d0030dd 100644
--- a/cmds/dumpstate/dumpstate.rc
+++ b/cmds/dumpstate/dumpstate.rc
@@ -8,6 +8,7 @@
socket dumpstate stream 0660 shell log
disabled
oneshot
+ user root
# dumpstatez generates a zipped bugreport but also uses a socket to print the file location once
# it is finished.
@@ -16,9 +17,11 @@
class main
disabled
oneshot
+ user root
# bugreportd starts dumpstate binder service and makes it wait for a listener to connect.
service bugreportd /system/bin/dumpstate -w
class main
disabled
oneshot
+ user root
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 7234d41..0012177 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -285,8 +285,8 @@
// Other options retain default values
- EXPECT_TRUE(options_.do_vibrate);
EXPECT_FALSE(options_.progress_updates_to_socket);
+ EXPECT_FALSE(options_.do_vibrate);
EXPECT_FALSE(options_.show_header_only);
EXPECT_FALSE(options_.is_remote_mode);
EXPECT_FALSE(options_.stream_to_socket);
diff --git a/cmds/installd/installd.rc b/cmds/installd/installd.rc
index 5b08c77..525f0c8 100644
--- a/cmds/installd/installd.rc
+++ b/cmds/installd/installd.rc
@@ -1,6 +1,7 @@
service installd /system/bin/installd
class main
+ user root
capabilities CHOWN DAC_OVERRIDE DAC_READ_SEARCH FOWNER FSETID KILL SETGID SETUID SYS_ADMIN
on early-boot
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index 07f73b9..61fe316 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -77,10 +77,8 @@
},
}
-cc_test {
- name: "installd_service_test",
- test_suites: ["device-tests"],
- srcs: ["installd_service_test.cpp"],
+cc_defaults {
+ name: "installd_service_test_defaults",
cflags: [
"-Wall",
"-Werror",
@@ -106,8 +104,6 @@
"liblogwrap",
"libc++fs",
],
- test_config: "installd_service_test.xml",
-
product_variables: {
arc: {
exclude_srcs: [
@@ -125,6 +121,14 @@
}
cc_test {
+ name: "installd_service_test",
+ test_suites: ["device-tests"],
+ srcs: ["installd_service_test.cpp"],
+ defaults: ["installd_service_test_defaults"],
+ test_config: "installd_service_test.xml",
+}
+
+cc_test {
name: "installd_dexopt_test",
test_suites: ["device-tests"],
srcs: ["installd_dexopt_test.cpp"],
@@ -209,3 +213,19 @@
"liblog",
],
}
+
+cc_fuzz {
+ name: "installd_service_fuzzer",
+ defaults: [
+ "service_fuzzer_defaults",
+ "fuzzer_disable_leaks",
+ "installd_service_test_defaults",
+ ],
+ srcs: ["fuzzers/InstalldServiceFuzzer.cpp"],
+ fuzz_config: {
+ cc: [
+ "android-package-manager-team@google.com",
+ ],
+ triage_assignee: "waghpawan@google.com",
+ },
+}
diff --git a/cmds/installd/tests/fuzzers/InstalldServiceFuzzer.cpp b/cmds/installd/tests/fuzzers/InstalldServiceFuzzer.cpp
new file mode 100644
index 0000000..b1c6940
--- /dev/null
+++ b/cmds/installd/tests/fuzzers/InstalldServiceFuzzer.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2023 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 <fuzzbinder/libbinder_driver.h>
+
+#include "InstalldNativeService.h"
+#include "dexopt.h"
+
+using ::android::fuzzService;
+using ::android::sp;
+using ::android::installd::InstalldNativeService;
+
+namespace android {
+namespace installd {
+
+bool calculate_oat_file_path(char path[PKG_PATH_MAX], const char* oat_dir, const char* apk_path,
+ const char* instruction_set) {
+ return calculate_oat_file_path_default(path, oat_dir, apk_path, instruction_set);
+}
+
+bool calculate_odex_file_path(char path[PKG_PATH_MAX], const char* apk_path,
+ const char* instruction_set) {
+ return calculate_odex_file_path_default(path, apk_path, instruction_set);
+}
+
+bool create_cache_path(char path[PKG_PATH_MAX], const char* src, const char* instruction_set) {
+ return create_cache_path_default(path, src, instruction_set);
+}
+
+bool force_compile_without_image() {
+ return false;
+}
+
+} // namespace installd
+} // namespace android
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ auto service = sp<InstalldNativeService>::make();
+ fuzzService(service, FuzzedDataProvider(data, size));
+ return 0;
+}
\ No newline at end of file
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index be4ca43..c4071c6 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -203,6 +203,10 @@
std::string secondary_dex_de_;
virtual void SetUp() {
+ if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
+ GTEST_SKIP() << "Skipping legacy dexopt tests when ART Service is enabled";
+ }
+
setenv("ANDROID_LOG_TAGS", "*:v", 1);
android::base::InitLogging(nullptr);
// Initialize the globals holding the file system main paths (/data/, /system/ etc..).
@@ -223,6 +227,10 @@
}
virtual void TearDown() {
+ if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
+ GTEST_SKIP();
+ }
+
if (!kDebug) {
service_->controlDexOptBlocking(false);
service_->destroyAppData(
@@ -966,6 +974,10 @@
class PrimaryDexReCompilationTest : public DexoptTest {
public:
virtual void SetUp() {
+ if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
+ GTEST_SKIP() << "Skipping legacy dexopt tests when ART Service is enabled";
+ }
+
DexoptTest::SetUp();
CompilePrimaryDexOk("verify",
DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC,
@@ -980,6 +992,10 @@
}
virtual void TearDown() {
+ if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
+ GTEST_SKIP();
+ }
+
first_compilation_odex_fd_.reset(-1);
first_compilation_vdex_fd_.reset(-1);
DexoptTest::TearDown();
@@ -1002,6 +1018,10 @@
class ReconcileTest : public DexoptTest {
virtual void SetUp() {
+ if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
+ GTEST_SKIP() << "Skipping legacy dexopt tests when ART Service is enabled";
+ }
+
DexoptTest::SetUp();
CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE,
/*binder_ok*/ true, /*compile_ok*/ true);
@@ -1067,6 +1087,10 @@
static constexpr const char* kPrimaryProfile = "primary.prof";
virtual void SetUp() {
+ if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
+ GTEST_SKIP() << "Skipping legacy dexopt tests when ART Service is enabled";
+ }
+
DexoptTest::SetUp();
cur_profile_ = create_current_profile_path(
kTestUserId, package_name_, kPrimaryProfile, /*is_secondary_dex*/ false);
@@ -1440,6 +1464,9 @@
std::vector<int64_t> extra_ce_data_inodes_;
virtual void SetUp() {
+ if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
+ GTEST_SKIP() << "Skipping legacy dexopt tests when ART Service is enabled";
+ }
ProfileTest::SetUp();
intial_android_profiles_dir = android_profiles_dir;
@@ -1453,6 +1480,10 @@
}
virtual void TearDown() {
+ if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
+ GTEST_SKIP();
+ }
+
android_profiles_dir = intial_android_profiles_dir;
deleteAppProfilesForBootMerge();
ProfileTest::TearDown();
diff --git a/cmds/lshal/libprocpartition/Android.bp b/cmds/lshal/libprocpartition/Android.bp
index af85666..d0e4b74 100644
--- a/cmds/lshal/libprocpartition/Android.bp
+++ b/cmds/lshal/libprocpartition/Android.bp
@@ -37,4 +37,8 @@
"include",
],
min_sdk_version: "30",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.neuralnetworks",
+ ],
}
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index 1386660..fb69513 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -72,6 +72,7 @@
cc_test {
name: "servicemanager_test",
+ host_supported: true,
test_suites: ["device-tests"],
defaults: ["servicemanager_defaults"],
srcs: [
@@ -92,9 +93,22 @@
libfuzzer_options: [
"max_len=50000",
],
- cc: [
- "smoreland@google.com",
- "waghpawan@google.com",
+ },
+}
+
+// Adding this new fuzzer to test the corpus generated by record_binder
+cc_fuzz {
+ name: "servicemanager_test_fuzzer",
+ defaults: [
+ "servicemanager_defaults",
+ "service_fuzzer_defaults",
+ ],
+ host_supported: true,
+ srcs: ["fuzzers/ServiceManagerTestFuzzer.cpp"],
+ fuzz_config: {
+ libfuzzer_options: [
+ "max_len=50000",
],
},
+ corpus: ["fuzzers/servicemamanager_fuzzer_corpus/*"],
}
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index bec262e..98a70ed 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -301,7 +301,7 @@
}
if (!out && startIfNotFound) {
- tryStartService(name);
+ tryStartService(ctx, name);
}
if (out) {
@@ -337,39 +337,45 @@
auto ctx = mAccess->getCallingContext();
if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
- return Status::fromExceptionCode(Status::EX_SECURITY, "App UIDs cannot add services");
+ return Status::fromExceptionCode(Status::EX_SECURITY, "App UIDs cannot add services.");
}
if (!mAccess->canAdd(ctx, name)) {
- return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denial");
+ return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
}
if (binder == nullptr) {
- return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Null binder");
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Null binder.");
}
if (!isValidServiceName(name)) {
ALOGE("Invalid service name: %s", name.c_str());
- return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Invalid service name");
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Invalid service name.");
}
#ifndef VENDORSERVICEMANAGER
if (!meetsDeclarationRequirements(binder, name)) {
// already logged
- return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "VINTF declaration error");
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "VINTF declaration error.");
}
#endif // !VENDORSERVICEMANAGER
+ if ((dumpPriority & DUMP_FLAG_PRIORITY_ALL) == 0) {
+ ALOGW("Dump flag priority is not set when adding %s", name.c_str());
+ }
+
// implicitly unlinked when the binder is removed
if (binder->remoteBinder() != nullptr &&
binder->linkToDeath(sp<ServiceManager>::fromExisting(this)) != OK) {
ALOGE("Could not linkToDeath when adding %s", name.c_str());
- return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "linkToDeath failure");
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "Couldn't linkToDeath.");
}
auto it = mNameToService.find(name);
+ bool prevClients = false;
if (it != mNameToService.end()) {
const Service& existing = it->second;
+ prevClients = existing.hasClients;
// We could do better than this because if the other service dies, it
// may not have an entry here. However, this case is unlikely. We are
@@ -397,10 +403,13 @@
.binder = binder,
.allowIsolated = allowIsolated,
.dumpPriority = dumpPriority,
+ .hasClients = prevClients, // see b/279898063, matters if existing callbacks
+ .guaranteeClient = false, // handled below
.ctx = ctx,
};
if (auto it = mNameToRegistrationCallback.find(name); it != mNameToRegistrationCallback.end()) {
+ // TODO: this is only needed once
// See also getService - handles case where client never gets the service,
// we want the service to quit.
mNameToService[name].guaranteeClient = true;
@@ -418,7 +427,7 @@
Status ServiceManager::listServices(int32_t dumpPriority, std::vector<std::string>* outList) {
if (!mAccess->canList(mAccess->getCallingContext())) {
- return Status::fromExceptionCode(Status::EX_SECURITY);
+ return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
}
size_t toReserve = 0;
@@ -452,18 +461,18 @@
if (!isValidServiceName(name)) {
ALOGE("Invalid service name: %s", name.c_str());
- return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Invalid service name.");
}
if (callback == nullptr) {
- return Status::fromExceptionCode(Status::EX_NULL_POINTER);
+ return Status::fromExceptionCode(Status::EX_NULL_POINTER, "Null callback.");
}
if (OK !=
IInterface::asBinder(callback)->linkToDeath(
sp<ServiceManager>::fromExisting(this))) {
ALOGE("Could not linkToDeath when adding %s", name.c_str());
- return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "Couldn't link to death.");
}
mNameToRegistrationCallback[name].push_back(callback);
@@ -483,7 +492,7 @@
auto ctx = mAccess->getCallingContext();
if (!mAccess->canFind(ctx, name)) {
- return Status::fromExceptionCode(Status::EX_SECURITY);
+ return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
}
bool found = false;
@@ -495,7 +504,7 @@
if (!found) {
ALOGE("Trying to unregister callback, but none exists %s", name.c_str());
- return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "Nothing to unregister.");
}
return Status::ok();
@@ -505,7 +514,7 @@
auto ctx = mAccess->getCallingContext();
if (!mAccess->canFind(ctx, name)) {
- return Status::fromExceptionCode(Status::EX_SECURITY);
+ return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
}
*outReturn = false;
@@ -533,7 +542,7 @@
}
if (outReturn->size() == 0 && allInstances.size() != 0) {
- return Status::fromExceptionCode(Status::EX_SECURITY);
+ return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
}
return Status::ok();
@@ -544,7 +553,7 @@
auto ctx = mAccess->getCallingContext();
if (!mAccess->canFind(ctx, name)) {
- return Status::fromExceptionCode(Status::EX_SECURITY);
+ return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
}
*outReturn = std::nullopt;
@@ -573,7 +582,7 @@
}
if (outReturn->size() == 0 && apexUpdatableInstances.size() != 0) {
- return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denial");
+ return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
}
return Status::ok();
@@ -584,7 +593,7 @@
auto ctx = mAccess->getCallingContext();
if (!mAccess->canFind(ctx, name)) {
- return Status::fromExceptionCode(Status::EX_SECURITY);
+ return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
}
*outReturn = std::nullopt;
@@ -619,6 +628,14 @@
void ServiceManager::binderDied(const wp<IBinder>& who) {
for (auto it = mNameToService.begin(); it != mNameToService.end();) {
if (who == it->second.binder) {
+ // TODO: currently, this entry contains the state also
+ // associated with mNameToClientCallback. If we allowed
+ // other processes to register client callbacks, we
+ // would have to preserve hasClients (perhaps moving
+ // that state into mNameToClientCallback, which is complicated
+ // because those callbacks are associated w/ particular binder
+ // objects, though they are indexed by name now, they may
+ // need to be indexed by binder at that point).
it = mNameToService.erase(it);
} else {
++it;
@@ -634,10 +651,11 @@
}
}
-void ServiceManager::tryStartService(const std::string& name) {
- ALOGI("Since '%s' could not be found, trying to start it as a lazy AIDL service. (if it's not "
- "configured to be a lazy service, it may be stuck starting or still starting).",
- name.c_str());
+void ServiceManager::tryStartService(const Access::CallingContext& ctx, const std::string& name) {
+ ALOGI("Since '%s' could not be found (requested by debug pid %d), trying to start it as a lazy "
+ "AIDL service. (if it's not configured to be a lazy service, it may be stuck starting or "
+ "still starting).",
+ name.c_str(), ctx.debugPid);
std::thread([=] {
if (!base::SetProperty("ctl.interface_start", "aidl/" + name)) {
@@ -653,36 +671,45 @@
Status ServiceManager::registerClientCallback(const std::string& name, const sp<IBinder>& service,
const sp<IClientCallback>& cb) {
if (cb == nullptr) {
- return Status::fromExceptionCode(Status::EX_NULL_POINTER);
+ return Status::fromExceptionCode(Status::EX_NULL_POINTER, "Callback null.");
}
auto ctx = mAccess->getCallingContext();
if (!mAccess->canAdd(ctx, name)) {
- return Status::fromExceptionCode(Status::EX_SECURITY);
+ return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
}
auto serviceIt = mNameToService.find(name);
if (serviceIt == mNameToService.end()) {
ALOGE("Could not add callback for nonexistent service: %s", name.c_str());
- return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Service doesn't exist.");
}
if (serviceIt->second.ctx.debugPid != IPCThreadState::self()->getCallingPid()) {
ALOGW("Only a server can register for client callbacks (for %s)", name.c_str());
- return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION);
+ return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
+ "Only service can register client callback for itself.");
}
if (serviceIt->second.binder != service) {
ALOGW("Tried to register client callback for %s but a different service is registered "
"under this name.",
name.c_str());
- return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Service mismatch.");
}
if (OK !=
IInterface::asBinder(cb)->linkToDeath(sp<ServiceManager>::fromExisting(this))) {
ALOGE("Could not linkToDeath when adding client callback for %s", name.c_str());
- return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "Couldn't linkToDeath.");
+ }
+
+ // WARNING: binderDied makes an assumption about this. If we open up client
+ // callbacks to other services, certain race conditions may lead to services
+ // getting extra client callback notifications.
+ // Make sure all callbacks have been told about a consistent state - b/278038751
+ if (serviceIt->second.hasClients) {
+ cb->onClients(service, true);
}
mNameToClientCallback[name].push_back(cb);
@@ -796,24 +823,25 @@
Status ServiceManager::tryUnregisterService(const std::string& name, const sp<IBinder>& binder) {
if (binder == nullptr) {
- return Status::fromExceptionCode(Status::EX_NULL_POINTER);
+ return Status::fromExceptionCode(Status::EX_NULL_POINTER, "Null service.");
}
auto ctx = mAccess->getCallingContext();
if (!mAccess->canAdd(ctx, name)) {
- return Status::fromExceptionCode(Status::EX_SECURITY);
+ return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
}
auto serviceIt = mNameToService.find(name);
if (serviceIt == mNameToService.end()) {
ALOGW("Tried to unregister %s, but that service wasn't registered to begin with.",
name.c_str());
- return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "Service not registered.");
}
if (serviceIt->second.ctx.debugPid != IPCThreadState::self()->getCallingPid()) {
ALOGW("Only a server can unregister itself (for %s)", name.c_str());
- return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION);
+ return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
+ "Service can only unregister itself.");
}
sp<IBinder> storedBinder = serviceIt->second.binder;
@@ -821,14 +849,16 @@
if (binder != storedBinder) {
ALOGW("Tried to unregister %s, but a different service is registered under this name.",
name.c_str());
- return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE,
+ "Different service registered under this name.");
}
// important because we don't have timer-based guarantees, we don't want to clear
// this
if (serviceIt->second.guaranteeClient) {
ALOGI("Tried to unregister %s, but there is about to be a client.", name.c_str());
- return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE,
+ "Can't unregister, pending client.");
}
// - kernel driver will hold onto one refcount (during this transaction)
@@ -843,7 +873,8 @@
// help reduce thrashing, but we should be able to remove it.
serviceIt->second.guaranteeClient = true;
- return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE,
+ "Can't unregister, known client.");
}
ALOGI("Unregistering %s", name.c_str());
@@ -854,7 +885,7 @@
Status ServiceManager::getServiceDebugInfo(std::vector<ServiceDebugInfo>* outReturn) {
if (!mAccess->canList(mAccess->getCallingContext())) {
- return Status::fromExceptionCode(Status::EX_SECURITY);
+ return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
}
outReturn->reserve(mNameToService.size());
diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h
index 3aa6731..3b925a4 100644
--- a/cmds/servicemanager/ServiceManager.h
+++ b/cmds/servicemanager/ServiceManager.h
@@ -67,7 +67,7 @@
void clear();
protected:
- virtual void tryStartService(const std::string& name);
+ virtual void tryStartService(const Access::CallingContext& ctx, const std::string& name);
private:
struct Service {
diff --git a/cmds/servicemanager/fuzzers/ServiceManagerTestFuzzer.cpp b/cmds/servicemanager/fuzzers/ServiceManagerTestFuzzer.cpp
new file mode 100644
index 0000000..e19b6eb
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/ServiceManagerTestFuzzer.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 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 <fuzzbinder/libbinder_driver.h>
+#include <utils/StrongPointer.h>
+
+#include "Access.h"
+#include "ServiceManager.h"
+
+using ::android::Access;
+using ::android::Parcel;
+using ::android::ServiceManager;
+using ::android::sp;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FuzzedDataProvider provider(data, size);
+ auto accessPtr = std::make_unique<Access>();
+ auto serviceManager = sp<ServiceManager>::make(std::move(accessPtr));
+
+ // Reserved bytes
+ provider.ConsumeBytes<uint8_t>(8);
+ uint32_t code = provider.ConsumeIntegral<uint32_t>();
+ uint32_t flag = provider.ConsumeIntegral<uint32_t>();
+ std::vector<uint8_t> parcelData = provider.ConsumeRemainingBytes<uint8_t>();
+
+ Parcel inputParcel;
+ inputParcel.setData(parcelData.data(), parcelData.size());
+
+ Parcel reply;
+ serviceManager->transact(code, inputParcel, &reply, flag);
+
+ serviceManager->clear();
+
+ return 0;
+}
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_1 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_1
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_1
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_10 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_10
new file mode 100644
index 0000000..07319f8
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_10
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_11 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_11
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_11
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_12 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_12
new file mode 100644
index 0000000..07319f8
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_12
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_13 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_13
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_13
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_14 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_14
new file mode 100644
index 0000000..07319f8
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_14
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_15 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_15
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_15
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_16 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_16
new file mode 100644
index 0000000..07319f8
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_16
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_17 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_17
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_17
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_18 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_18
new file mode 100644
index 0000000..88ad474
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_18
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_19 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_19
new file mode 100644
index 0000000..fae15a2
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_19
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_2 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_2
new file mode 100644
index 0000000..e69ab49
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_2
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_20 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_20
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_20
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_21 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_21
new file mode 100644
index 0000000..88ad474
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_21
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_22 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_22
new file mode 100644
index 0000000..fae15a2
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_22
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_23 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_23
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_23
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_24 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_24
new file mode 100644
index 0000000..88ad474
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_24
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_25 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_25
new file mode 100644
index 0000000..fae15a2
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_25
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_26 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_26
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_26
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_27 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_27
new file mode 100644
index 0000000..88ad474
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_27
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_28 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_28
new file mode 100644
index 0000000..fae15a2
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_28
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_29 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_29
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_29
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_3 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_3
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_3
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_30 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_30
new file mode 100644
index 0000000..88ad474
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_30
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_31 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_31
new file mode 100644
index 0000000..fae15a2
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_31
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_32 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_32
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_32
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_33 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_33
new file mode 100644
index 0000000..88ad474
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_33
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_34 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_34
new file mode 100644
index 0000000..fae15a2
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_34
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_35 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_35
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_35
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_36 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_36
new file mode 100644
index 0000000..88ad474
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_36
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_37 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_37
new file mode 100644
index 0000000..fae15a2
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_37
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_38 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_38
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_38
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_39 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_39
new file mode 100644
index 0000000..b326907
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_39
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_4 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_4
new file mode 100644
index 0000000..05b27bf
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_4
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_40 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_40
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_40
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_41 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_41
new file mode 100644
index 0000000..b326907
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_41
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_42 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_42
new file mode 100644
index 0000000..cdaa1f0
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_42
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_43 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_43
new file mode 100644
index 0000000..ff0941b
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_43
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_44 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_44
new file mode 100644
index 0000000..cdaa1f0
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_44
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_45 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_45
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_45
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_46 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_46
new file mode 100644
index 0000000..7e5f948
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_46
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_5 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_5
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_5
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_6 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_6
new file mode 100644
index 0000000..07319f8
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_6
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_7 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_7
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_7
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_8 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_8
new file mode 100644
index 0000000..07319f8
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_8
Binary files differ
diff --git a/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_9 b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_9
new file mode 100644
index 0000000..39e5104
--- /dev/null
+++ b/cmds/servicemanager/fuzzers/servicemanager_fuzzer_corpus/Transaction_9
Binary files differ
diff --git a/cmds/servicemanager/main.cpp b/cmds/servicemanager/main.cpp
index c1a04dd..86a45e61 100644
--- a/cmds/servicemanager/main.cpp
+++ b/cmds/servicemanager/main.cpp
@@ -131,7 +131,9 @@
}
IPCThreadState::self()->setTheContextObject(manager);
- ps->becomeContextManager();
+ if (!ps->becomeContextManager()) {
+ LOG(FATAL) << "Could not become context manager";
+ }
sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);
diff --git a/cmds/servicemanager/servicemanager.recovery.rc b/cmds/servicemanager/servicemanager.recovery.rc
index b927c01..6354fd7 100644
--- a/cmds/servicemanager/servicemanager.recovery.rc
+++ b/cmds/servicemanager/servicemanager.recovery.rc
@@ -1,5 +1,6 @@
service servicemanager /system/bin/servicemanager
disabled
group system readproc
+ user root
onrestart setprop servicemanager.ready false
seclabel u:r:servicemanager:s0
diff --git a/cmds/servicemanager/test_sm.cpp b/cmds/servicemanager/test_sm.cpp
index 0fd8d8e..9e5b8a4 100644
--- a/cmds/servicemanager/test_sm.cpp
+++ b/cmds/servicemanager/test_sm.cpp
@@ -27,11 +27,14 @@
#include "Access.h"
#include "ServiceManager.h"
-using android::sp;
using android::Access;
using android::BBinder;
using android::IBinder;
using android::ServiceManager;
+using android::sp;
+using android::base::EndsWith;
+using android::base::GetProperty;
+using android::base::StartsWith;
using android::binder::Status;
using android::os::BnServiceCallback;
using android::os::IServiceManager;
@@ -62,7 +65,7 @@
class MockServiceManager : public ServiceManager {
public:
MockServiceManager(std::unique_ptr<Access>&& access) : ServiceManager(std::move(access)) {}
- MOCK_METHOD1(tryStartService, void(const std::string& name));
+ MOCK_METHOD2(tryStartService, void(const Access::CallingContext&, const std::string& name));
};
static sp<ServiceManager> getPermissiveServiceManager() {
@@ -77,9 +80,11 @@
return sm;
}
-static bool isCuttlefish() {
- return android::base::StartsWith(android::base::GetProperty("ro.product.vendor.device", ""),
- "vsoc_");
+// Determines if test device is a cuttlefish phone device
+static bool isCuttlefishPhone() {
+ auto device = GetProperty("ro.product.vendor.device", "");
+ auto product = GetProperty("ro.product.vendor.name", "");
+ return StartsWith(device, "vsoc_") && EndsWith(product, "_phone");
}
TEST(AddService, HappyHappy) {
@@ -314,7 +319,7 @@
}
TEST(Vintf, UpdatableViaApex) {
- if (!isCuttlefish()) GTEST_SKIP() << "Skipping non-Cuttlefish devices";
+ if (!isCuttlefishPhone()) GTEST_SKIP() << "Skipping non-Cuttlefish-phone devices";
auto sm = getPermissiveServiceManager();
std::optional<std::string> updatableViaApex;
@@ -326,7 +331,7 @@
}
TEST(Vintf, UpdatableViaApex_InvalidNameReturnsNullOpt) {
- if (!isCuttlefish()) GTEST_SKIP() << "Skipping non-Cuttlefish devices";
+ if (!isCuttlefishPhone()) GTEST_SKIP() << "Skipping non-Cuttlefish-phone devices";
auto sm = getPermissiveServiceManager();
std::optional<std::string> updatableViaApex;
@@ -337,7 +342,7 @@
}
TEST(Vintf, GetUpdatableNames) {
- if (!isCuttlefish()) GTEST_SKIP() << "Skipping non-Cuttlefish devices";
+ if (!isCuttlefishPhone()) GTEST_SKIP() << "Skipping non-Cuttlefish-phone devices";
auto sm = getPermissiveServiceManager();
std::vector<std::string> names;
@@ -348,7 +353,7 @@
}
TEST(Vintf, GetUpdatableNames_InvalidApexNameReturnsEmpty) {
- if (!isCuttlefish()) GTEST_SKIP() << "Skipping non-Cuttlefish devices";
+ if (!isCuttlefishPhone()) GTEST_SKIP() << "Skipping non-Cuttlefish-phone devices";
auto sm = getPermissiveServiceManager();
std::vector<std::string> names;
diff --git a/include/android/input.h b/include/android/input.h
index 38b27bc..2a7cea6 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -249,13 +249,13 @@
AKEY_EVENT_FLAG_LONG_PRESS = 0x80,
/**
- * Set when a key event has AKEY_EVENT_FLAG_CANCELED set because a long
+ * Set when a key event has #AKEY_EVENT_FLAG_CANCELED set because a long
* press action was executed while it was down.
*/
AKEY_EVENT_FLAG_CANCELED_LONG_PRESS = 0x100,
/**
- * Set for AKEY_EVENT_ACTION_UP when this event's key code is still being
+ * Set for #AKEY_EVENT_ACTION_UP when this event's key code is still being
* tracked from its initial down. That is, somebody requested that tracking
* started on the key down and a long press has not caused
* the tracking to be canceled.
@@ -275,7 +275,7 @@
/**
* Bit shift for the action bits holding the pointer index as
- * defined by AMOTION_EVENT_ACTION_POINTER_INDEX_MASK.
+ * defined by #AMOTION_EVENT_ACTION_POINTER_INDEX_MASK.
*/
#define AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT 8
@@ -286,8 +286,8 @@
/**
* Bits in the action code that represent a pointer index, used with
- * AMOTION_EVENT_ACTION_POINTER_DOWN and AMOTION_EVENT_ACTION_POINTER_UP. Shifting
- * down by AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT provides the actual pointer
+ * #AMOTION_EVENT_ACTION_POINTER_DOWN and AMOTION_EVENT_ACTION_POINTER_UP. Shifting
+ * down by #AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT provides the actual pointer
* index where the data for the pointer going up or down can be found.
*/
AMOTION_EVENT_ACTION_POINTER_INDEX_MASK = 0xff00,
@@ -302,8 +302,8 @@
AMOTION_EVENT_ACTION_UP = 1,
/**
- * A change has happened during a press gesture (between AMOTION_EVENT_ACTION_DOWN and
- * AMOTION_EVENT_ACTION_UP). The motion contains the most recent point, as well as
+ * A change has happened during a press gesture (between #AMOTION_EVENT_ACTION_DOWN and
+ * #AMOTION_EVENT_ACTION_UP). The motion contains the most recent point, as well as
* any intermediate points since the last down or move event.
*/
AMOTION_EVENT_ACTION_MOVE = 2,
@@ -323,18 +323,18 @@
/**
* A non-primary pointer has gone down.
- * The bits in AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed.
+ * The bits in #AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed.
*/
AMOTION_EVENT_ACTION_POINTER_DOWN = 5,
/**
* A non-primary pointer has gone up.
- * The bits in AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed.
+ * The bits in #AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed.
*/
AMOTION_EVENT_ACTION_POINTER_UP = 6,
/**
- * A change happened but the pointer is not down (unlike AMOTION_EVENT_ACTION_MOVE).
+ * A change happened but the pointer is not down (unlike #AMOTION_EVENT_ACTION_MOVE).
* The motion contains the most recent point, as well as any intermediate points since
* the last hover move event.
*/
@@ -342,8 +342,8 @@
/**
* The motion event contains relative vertical and/or horizontal scroll offsets.
- * Use getAxisValue to retrieve the information from AMOTION_EVENT_AXIS_VSCROLL
- * and AMOTION_EVENT_AXIS_HSCROLL.
+ * Use {@link AMotionEvent_getAxisValue} to retrieve the information from
+ * #AMOTION_EVENT_AXIS_VSCROLL and #AMOTION_EVENT_AXIS_HSCROLL.
* The pointer may or may not be down when this event is dispatched.
* This action is always delivered to the winder under the pointer, which
* may not be the window currently touched.
@@ -528,7 +528,7 @@
* is pointing in relation to the vertical axis of the current orientation of the screen.
* The range is from -PI radians to PI radians, where 0 is pointing up,
* -PI/2 radians is pointing left, -PI or PI radians is pointing down, and PI/2 radians
- * is pointing right. See also {@link AMOTION_EVENT_AXIS_TILT}.
+ * is pointing right. See also #AMOTION_EVENT_AXIS_TILT.
*/
AMOTION_EVENT_AXIS_ORIENTATION = 8,
/**
@@ -681,7 +681,7 @@
/**
* Axis constant: The movement of y position of a motion event.
*
- * Same as {@link AMOTION_EVENT_AXIS_RELATIVE_X}, but for y position.
+ * Same as #AMOTION_EVENT_AXIS_RELATIVE_X, but for y position.
*/
AMOTION_EVENT_AXIS_RELATIVE_Y = 28,
/**
@@ -821,7 +821,8 @@
* Classification constant: Ambiguous gesture.
*
* The user's intent with respect to the current event stream is not yet determined. Events
- * starting in AMBIGUOUS_GESTURE will eventually resolve into either DEEP_PRESS or NONE.
+ * starting in #AMOTION_EVENT_CLASSIFICATION_AMBIGUOUS_GESTURE will eventually resolve into
+ * either #AMOTION_EVENT_CLASSIFICATION_DEEP_PRESS or #AMOTION_EVENT_CLASSIFICATION_NONE.
* Gestural actions, such as scrolling, should be inhibited until the classification resolves
* to another value or the event stream ends.
*/
@@ -923,7 +924,8 @@
* Refer to the documentation on android.view.InputDevice for more details about input sources
* and their correct interpretation.
*
- * @deprecated These constants are deprecated. Use {@link AMOTION_EVENT_AXIS AMOTION_EVENT_AXIS_*} constants instead.
+ * @deprecated These constants are deprecated. Use {@link AMOTION_EVENT_AXIS AMOTION_EVENT_AXIS_*}
+ * constants instead.
*/
enum {
/** x */
@@ -977,8 +979,8 @@
/**
* Releases interface objects created by {@link AKeyEvent_fromJava()}
* and {@link AMotionEvent_fromJava()}.
- * After returning, the specified AInputEvent* object becomes invalid and should no longer be used.
- * The underlying Java object remains valid and does not change its state.
+ * After returning, the specified {@link AInputEvent}* object becomes invalid and should no longer
+ * be used. The underlying Java object remains valid and does not change its state.
*
* Available since API level 31.
*/
@@ -1031,9 +1033,10 @@
int64_t AKeyEvent_getEventTime(const AInputEvent* key_event);
/**
- * Creates a native AInputEvent* object that is a copy of the specified Java android.view.KeyEvent.
- * The result may be used with generic and KeyEvent-specific AInputEvent_* functions. The object
- * returned by this function must be disposed using {@link AInputEvent_release()}.
+ * Creates a native {@link AInputEvent}* object that is a copy of the specified Java
+ * android.view.KeyEvent. The result may be used with generic and KeyEvent-specific AInputEvent_*
+ * functions. The object returned by this function must be disposed using
+ * {@link AInputEvent_release()}.
*
* Available since API level 31.
*/
@@ -1221,7 +1224,7 @@
/**
* Get the number of historical points in this event. These are movements that
* have occurred between this event and the previous event. This only applies
- * to AMOTION_EVENT_ACTION_MOVE events -- all other actions will have a size of 0.
+ * to #AMOTION_EVENT_ACTION_MOVE events -- all other actions will have a size of 0.
* Historical samples are indexed from oldest to newest.
*/
size_t AMotionEvent_getHistorySize(const AInputEvent* motion_event);
@@ -1382,7 +1385,7 @@
__INTRODUCED_IN(__ANDROID_API_T__);
/**
- * Creates a native AInputEvent* object that is a copy of the specified Java
+ * Creates a native {@link AInputEvent}* object that is a copy of the specified Java
* android.view.MotionEvent. The result may be used with generic and MotionEvent-specific
* AInputEvent_* functions. The object returned by this function must be disposed using
* {@link AInputEvent_release()}.
@@ -1402,7 +1405,7 @@
/**
* Add this input queue to a looper for processing. See
- * ALooper_addFd() for information on the ident, callback, and data params.
+ * {@link ALooper_addFd()} for information on the ident, callback, and data params.
*/
void AInputQueue_attachLooper(AInputQueue* queue, ALooper* looper,
int ident, ALooper_callbackFunc callback, void* data);
@@ -1437,12 +1440,12 @@
/**
* Report that dispatching has finished with the given event.
- * This must be called after receiving an event with AInputQueue_get_event().
+ * This must be called after receiving an event with {@link AInputQueue_getEvent()}.
*/
void AInputQueue_finishEvent(AInputQueue* queue, AInputEvent* event, int handled);
/**
- * Returns the AInputQueue* object associated with the supplied Java InputQueue
+ * Returns the {@link AInputQueue}* object associated with the supplied Java InputQueue
* object. The returned native object holds a weak reference to the Java object,
* and is only valid as long as the Java object has not yet been disposed. You
* should ensure that there is a strong reference to the Java object and that it
diff --git a/include/input/KeyLayoutMap.h b/include/input/KeyLayoutMap.h
index 1da78aa..d36d28c 100644
--- a/include/input/KeyLayoutMap.h
+++ b/include/input/KeyLayoutMap.h
@@ -73,6 +73,7 @@
int32_t* outKeyCode, uint32_t* outFlags) const;
std::vector<int32_t> findScanCodesForKey(int32_t keyCode) const;
std::optional<int32_t> findScanCodeForLed(int32_t ledCode) const;
+ std::vector<int32_t> findUsageCodesForKey(int32_t keyCode) const;
std::optional<int32_t> findUsageCodeForLed(int32_t ledCode) const;
std::optional<AxisInfo> mapAxis(int32_t scanCode) const;
diff --git a/libs/arect/Android.bp b/libs/arect/Android.bp
index 5e539f2..1a9766d 100644
--- a/libs/arect/Android.bp
+++ b/libs/arect/Android.bp
@@ -72,6 +72,7 @@
"//apex_available:platform",
"com.android.media",
"com.android.media.swcodec",
+ "com.android.neuralnetworks",
],
}
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 2f58e12..3433138 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -144,10 +144,6 @@
"-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
],
product_variables: {
- binder32bit: {
- cflags: ["-DBINDER_IPC_32BIT=1"],
- },
-
debuggable: {
cflags: [
"-DBINDER_RPC_DEV_SERVERS",
@@ -285,14 +281,6 @@
cflags: [
"-DBINDER_WITH_KERNEL_IPC",
],
- arch: {
- // TODO(b/254713216): undefined symbol in BufferedTextOutput::getBuffer
- riscv64: {
- lto: {
- thin: false,
- },
- },
- },
}
cc_library {
@@ -359,6 +347,7 @@
cc_library_static {
name: "libbinder_rpc_no_kernel",
+ vendor_available: true,
defaults: [
"libbinder_common_defaults",
"libbinder_android_defaults",
@@ -411,6 +400,7 @@
cc_defaults {
name: "libbinder_tls_defaults",
defaults: ["libbinder_tls_shared_deps"],
+ vendor_available: true,
host_supported: true,
header_libs: [
@@ -437,7 +427,7 @@
defaults: ["libbinder_tls_defaults"],
}
-cc_library_shared {
+cc_library {
name: "libbinder_trusty",
vendor: true,
srcs: [
@@ -552,6 +542,7 @@
":__subpackages__",
"//packages/modules/Virtualization/javalib/jni",
"//packages/modules/Virtualization/vm_payload",
+ "//packages/modules/Virtualization/demo_native",
"//device/google/cuttlefish/shared/minidroid:__subpackages__",
"//system/software_defined_vehicle:__subpackages__",
],
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 3e49656..0f4a6ca 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -58,15 +58,15 @@
// global b/c b/230079120 - consistent symbol table
#ifdef BINDER_RPC_DEV_SERVERS
-bool kEnableRpcDevServers = true;
+constexpr bool kEnableRpcDevServers = true;
#else
-bool kEnableRpcDevServers = false;
+constexpr bool kEnableRpcDevServers = false;
#endif
#ifdef BINDER_ENABLE_RECORDING
-bool kEnableRecording = true;
+constexpr bool kEnableRecording = true;
#else
-bool kEnableRecording = false;
+constexpr bool kEnableRecording = false;
#endif
// Log any reply transactions for which the data exceeds this size
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 53852d8..8d9955d 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -47,7 +47,7 @@
binder_proxy_limit_callback BpBinder::sLimitCallback;
bool BpBinder::sBinderProxyThrottleCreate = false;
-static StaticString16 kDescriptorUninit(u"<uninit descriptor>");
+static StaticString16 kDescriptorUninit(u"");
// Arbitrarily high value that probably distinguishes a bad behaving app
uint32_t BpBinder::sBinderProxyCountHighWatermark = 2500;
diff --git a/libs/binder/LazyServiceRegistrar.cpp b/libs/binder/LazyServiceRegistrar.cpp
index f66993f..7644806 100644
--- a/libs/binder/LazyServiceRegistrar.cpp
+++ b/libs/binder/LazyServiceRegistrar.cpp
@@ -324,6 +324,10 @@
return *registrarInstance;
}
+LazyServiceRegistrar LazyServiceRegistrar::createExtraTestInstance() {
+ return LazyServiceRegistrar();
+}
+
status_t LazyServiceRegistrar::registerService(const sp<IBinder>& service, const std::string& name,
bool allowIsolated, int dumpFlags) {
if (!mClientCC->registerService(service, name, allowIsolated, dumpFlags)) {
diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp
index 8fe1d2b..3da06ba 100644
--- a/libs/binder/MemoryHeapBase.cpp
+++ b/libs/binder/MemoryHeapBase.cpp
@@ -78,7 +78,7 @@
if (SEAL_FLAGS && (fcntl(fd, F_ADD_SEALS, SEAL_FLAGS) == -1)) {
ALOGE("MemoryHeapBase: MemFD %s sealing with flags %x failed with error %s", name,
SEAL_FLAGS, strerror(errno));
- munmap(mBase, mSize);
+ if (mNeedUnmap) munmap(mBase, mSize);
mBase = nullptr;
mSize = 0;
close(fd);
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 5f1f506..3fa6867 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -104,14 +104,7 @@
return access("/vendor/bin/vndservicemanager", R_OK) == 0;
}
-sp<ProcessState> ProcessState::init(const char *driver, bool requireDefault)
-{
-#ifdef BINDER_IPC_32BIT
- LOG_ALWAYS_FATAL("32-bit binder IPC is not supported for new devices starting in Android P. If "
- "you do need to use this mode, please see b/232423610 or file an issue with "
- "AOSP upstream as otherwise this will be removed soon.");
-#endif
-
+sp<ProcessState> ProcessState::init(const char* driver, bool requireDefault) {
if (driver == nullptr) {
std::lock_guard<std::mutex> l(gProcessMutex);
if (gProcess) {
diff --git a/libs/binder/RecordedTransaction.cpp b/libs/binder/RecordedTransaction.cpp
index ef58ed3..44a9e3b 100644
--- a/libs/binder/RecordedTransaction.cpp
+++ b/libs/binder/RecordedTransaction.cpp
@@ -131,12 +131,12 @@
return std::nullopt;
}
- if (t.mSent.setData(dataParcel.data(), dataParcel.dataSize()) != android::NO_ERROR) {
+ if (t.mSent.setData(dataParcel.data(), dataParcel.dataBufferSize()) != android::NO_ERROR) {
LOG(ERROR) << "Failed to set sent parcel data.";
return std::nullopt;
}
- if (t.mReply.setData(replyParcel.data(), replyParcel.dataSize()) != android::NO_ERROR) {
+ if (t.mReply.setData(replyParcel.data(), replyParcel.dataBufferSize()) != android::NO_ERROR) {
LOG(ERROR) << "Failed to set reply parcel data.";
return std::nullopt;
}
@@ -161,17 +161,6 @@
constexpr uint32_t kMaxChunkDataSize = 0xfffffff0;
typedef uint64_t transaction_checksum_t;
-static android::status_t readChunkDescriptor(borrowed_fd fd, ChunkDescriptor* chunkOut,
- transaction_checksum_t* sum) {
- if (!android::base::ReadFully(fd, chunkOut, sizeof(ChunkDescriptor))) {
- LOG(ERROR) << "Failed to read Chunk Descriptor from fd " << fd.get();
- return android::UNKNOWN_ERROR;
- }
-
- *sum ^= *reinterpret_cast<transaction_checksum_t*>(chunkOut);
- return android::NO_ERROR;
-}
-
std::optional<RecordedTransaction> RecordedTransaction::fromFile(const unique_fd& fd) {
RecordedTransaction t;
ChunkDescriptor chunk;
@@ -192,11 +181,13 @@
LOG(ERROR) << "Not enough file remains to contain expected chunk descriptor";
return std::nullopt;
}
- transaction_checksum_t checksum = 0;
- if (NO_ERROR != readChunkDescriptor(fd, &chunk, &checksum)) {
- LOG(ERROR) << "Failed to read chunk descriptor.";
+
+ if (!android::base::ReadFully(fd, &chunk, sizeof(ChunkDescriptor))) {
+ LOG(ERROR) << "Failed to read ChunkDescriptor from fd " << fd.get() << ". "
+ << strerror(errno);
return std::nullopt;
}
+ transaction_checksum_t checksum = *reinterpret_cast<transaction_checksum_t*>(&chunk);
fdCurrentPosition = lseek(fd.get(), 0, SEEK_CUR);
if (fdCurrentPosition == -1) {
@@ -349,11 +340,11 @@
return UNKNOWN_ERROR;
}
- if (NO_ERROR != writeChunk(fd, DATA_PARCEL_CHUNK, mSent.dataSize(), mSent.data())) {
+ if (NO_ERROR != writeChunk(fd, DATA_PARCEL_CHUNK, mSent.dataBufferSize(), mSent.data())) {
LOG(ERROR) << "Failed to write sent Parcel to fd " << fd.get();
return UNKNOWN_ERROR;
}
- if (NO_ERROR != writeChunk(fd, REPLY_PARCEL_CHUNK, mReply.dataSize(), mReply.data())) {
+ if (NO_ERROR != writeChunk(fd, REPLY_PARCEL_CHUNK, mReply.dataBufferSize(), mReply.data())) {
LOG(ERROR) << "Failed to write reply Parcel to fd " << fd.get();
return UNKNOWN_ERROR;
}
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 0d06e9e..55fc16d 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -81,6 +81,7 @@
auto aiStart = InetSocketAddress::getAddrInfo(address, port);
if (aiStart == nullptr) return UNKNOWN_ERROR;
for (auto ai = aiStart.get(); ai != nullptr; ai = ai->ai_next) {
+ if (ai->ai_addr == nullptr) continue;
InetSocketAddress socketAddress(ai->ai_addr, ai->ai_addrlen, address, port);
if (status_t status = setupSocketServer(socketAddress); status != OK) {
continue;
@@ -123,8 +124,13 @@
return mMaxThreads;
}
-void RpcServer::setProtocolVersion(uint32_t version) {
+bool RpcServer::setProtocolVersion(uint32_t version) {
+ if (!RpcState::validateProtocolVersion(version)) {
+ return false;
+ }
+
mProtocolVersion = version;
+ return true;
}
void RpcServer::setSupportedFileDescriptorTransportModes(
@@ -148,7 +154,7 @@
mRootObjectWeak = binder;
}
void RpcServer::setPerSessionRootObject(
- std::function<sp<IBinder>(const void*, size_t)>&& makeObject) {
+ std::function<sp<IBinder>(wp<RpcSession> session, const void*, size_t)>&& makeObject) {
RpcMutexLockGuard _l(mLock);
mRootObject.clear();
mRootObjectWeak.clear();
@@ -161,6 +167,12 @@
mConnectionFilter = std::move(filter);
}
+void RpcServer::setServerSocketModifier(std::function<void(base::borrowed_fd)>&& modifier) {
+ RpcMutexLockGuard _l(mLock);
+ LOG_ALWAYS_FATAL_IF(mServer.fd != -1, "Already started");
+ mServerSocketModifier = std::move(modifier);
+}
+
sp<IBinder> RpcServer::getRootObject() {
RpcMutexLockGuard _l(mLock);
bool hasWeak = mRootObjectWeak.unsafe_get();
@@ -295,7 +307,8 @@
bool RpcServer::shutdown() {
RpcMutexUniqueLock _l(mLock);
if (mShutdownTrigger == nullptr) {
- LOG_RPC_DETAIL("Cannot shutdown. No shutdown trigger installed (already shutdown?)");
+ LOG_RPC_DETAIL("Cannot shutdown. No shutdown trigger installed (already shutdown, or not "
+ "joined yet?)");
return false;
}
@@ -334,6 +347,8 @@
mJoinThread.reset();
}
+ mServer = RpcTransportFd();
+
LOG_RPC_DETAIL("Finished waiting on shutdown.");
mShutdownTrigger = nullptr;
@@ -500,7 +515,8 @@
// if null, falls back to server root
sp<IBinder> sessionSpecificRoot;
if (server->mRootObjectFactory != nullptr) {
- sessionSpecificRoot = server->mRootObjectFactory(addr.data(), addrLen);
+ sessionSpecificRoot =
+ server->mRootObjectFactory(wp<RpcSession>(session), addr.data(), addrLen);
if (sessionSpecificRoot == nullptr) {
ALOGE("Warning: server returned null from root object factory");
}
@@ -552,9 +568,17 @@
socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)));
if (!socket_fd.ok()) {
int savedErrno = errno;
- ALOGE("Could not create socket: %s", strerror(savedErrno));
+ ALOGE("Could not create socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
return -savedErrno;
}
+
+ {
+ RpcMutexLockGuard _l(mLock);
+ if (mServerSocketModifier != nullptr) {
+ mServerSocketModifier(socket_fd);
+ }
+ }
+
if (0 != TEMP_FAILURE_RETRY(bind(socket_fd.get(), addr.addr(), addr.addrSize()))) {
int savedErrno = errno;
ALOGE("Could not bind socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index fbad0f7..c3dee16 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -104,11 +104,7 @@
}
bool RpcSession::setProtocolVersionInternal(uint32_t version, bool checkStarted) {
- if (version >= RPC_WIRE_PROTOCOL_VERSION_NEXT &&
- version != RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL) {
- ALOGE("Cannot start RPC session with version %u which is unknown (current protocol version "
- "is %u).",
- version, RPC_WIRE_PROTOCOL_VERSION);
+ if (!RpcState::validateProtocolVersion(version)) {
return false;
}
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index ed3ce24..ff35f5f 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -398,6 +398,18 @@
return OK;
}
+bool RpcState::validateProtocolVersion(uint32_t version) {
+ if (version >= RPC_WIRE_PROTOCOL_VERSION_NEXT &&
+ version != RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL) {
+ ALOGE("Cannot use RPC binder protocol version %u which is unknown (current protocol "
+ "version "
+ "is %u).",
+ version, RPC_WIRE_PROTOCOL_VERSION);
+ return false;
+ }
+ return true;
+}
+
status_t RpcState::readNewSessionResponse(const sp<RpcSession::RpcConnection>& connection,
const sp<RpcSession>& session, uint32_t* version) {
RpcNewSessionResponse response;
@@ -928,7 +940,7 @@
transactionData.size() -
offsetof(RpcWireTransaction, data)};
Span<const uint32_t> objectTableSpan;
- if (session->getProtocolVersion().value() >
+ if (session->getProtocolVersion().value() >=
RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_FEATURE_EXPLICIT_PARCEL_SIZE) {
std::optional<Span<const uint8_t>> objectTableBytes =
parcelSpan.splitOff(transaction->parcelDataSize);
diff --git a/libs/binder/RpcState.h b/libs/binder/RpcState.h
index 0e23ea7..1fe71a5 100644
--- a/libs/binder/RpcState.h
+++ b/libs/binder/RpcState.h
@@ -63,6 +63,8 @@
RpcState();
~RpcState();
+ [[nodiscard]] static bool validateProtocolVersion(uint32_t version);
+
[[nodiscard]] status_t readNewSessionResponse(const sp<RpcSession::RpcConnection>& connection,
const sp<RpcSession>& session, uint32_t* version);
[[nodiscard]] status_t sendConnectionInit(const sp<RpcSession::RpcConnection>& connection,
diff --git a/libs/binder/RpcTransportRaw.cpp b/libs/binder/RpcTransportRaw.cpp
index cd067bf..f3575cc 100644
--- a/libs/binder/RpcTransportRaw.cpp
+++ b/libs/binder/RpcTransportRaw.cpp
@@ -29,8 +29,6 @@
namespace android {
-namespace {
-
// RpcTransport with TLS disabled.
class RpcTransportRaw : public RpcTransport {
public:
@@ -96,8 +94,6 @@
std::vector<uint8_t> getCertificate(RpcCertificateFormat) const override { return {}; }
};
-} // namespace
-
std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryRaw::newServerCtx() const {
return std::make_unique<RpcTransportCtxRaw>();
}
diff --git a/libs/binder/RpcTransportTipcAndroid.cpp b/libs/binder/RpcTransportTipcAndroid.cpp
index 8b3ddfb..0c81d83 100644
--- a/libs/binder/RpcTransportTipcAndroid.cpp
+++ b/libs/binder/RpcTransportTipcAndroid.cpp
@@ -31,8 +31,6 @@
namespace android {
-namespace {
-
// RpcTransport for writing Trusty IPC clients in Android.
class RpcTransportTipcAndroid : public RpcTransport {
public:
@@ -54,7 +52,7 @@
}
LOG_RPC_DETAIL("RpcTransport poll(): %s", strerror(savedErrno));
- return -savedErrno;
+ return adjustStatus(-savedErrno);
}
if (pfd.revents & POLLNVAL) {
@@ -87,8 +85,10 @@
"File descriptors are not supported on Trusty yet");
return TEMP_FAILURE_RETRY(tipc_send(mSocket.fd.get(), iovs, niovs, nullptr, 0));
};
- return interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, writeFn, "tipc_send",
- POLLOUT, altPoll);
+
+ status_t status = interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, writeFn,
+ "tipc_send", POLLOUT, altPoll);
+ return adjustStatus(status);
}
status_t interruptableReadFully(
@@ -121,13 +121,26 @@
return processSize;
};
- return interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, readFn, "read", POLLIN,
- altPoll);
+
+ status_t status = interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, readFn, "read",
+ POLLIN, altPoll);
+ return adjustStatus(status);
}
bool isWaiting() override { return mSocket.isInPollingState(); }
private:
+ status_t adjustStatus(status_t status) {
+ if (status == -ENOTCONN) {
+ // TIPC returns ENOTCONN on disconnect, but that's basically
+ // the same as DEAD_OBJECT and the latter is the common libbinder
+ // error code for dead connections
+ return DEAD_OBJECT;
+ }
+
+ return status;
+ }
+
status_t fillReadBuffer() {
if (mReadBufferPos < mReadBufferSize) {
return OK;
@@ -167,7 +180,7 @@
continue;
} else {
LOG_RPC_DETAIL("RpcTransport fillBuffer(): %s", strerror(savedErrno));
- return -savedErrno;
+ return adjustStatus(-savedErrno);
}
} else {
mReadBufferSize = static_cast<size_t>(processSize);
@@ -202,8 +215,6 @@
std::vector<uint8_t> getCertificate(RpcCertificateFormat) const override { return {}; }
};
-} // namespace
-
std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTipcAndroid::newServerCtx() const {
return std::make_unique<RpcTransportCtxTipcAndroid>();
}
diff --git a/libs/binder/RpcTransportTls.cpp b/libs/binder/RpcTransportTls.cpp
index 3e98ecc..785f6ce 100644
--- a/libs/binder/RpcTransportTls.cpp
+++ b/libs/binder/RpcTransportTls.cpp
@@ -275,6 +275,8 @@
bssl::UniquePtr<SSL> mSsl;
};
+} // namespace
+
class RpcTransportTls : public RpcTransport {
public:
RpcTransportTls(RpcTransportFd socket, Ssl ssl)
@@ -411,7 +413,8 @@
}
// For |ssl|, set internal FD to |fd|, and do handshake. Handshake is triggerable by |fdTrigger|.
-bool setFdAndDoHandshake(Ssl* ssl, const android::RpcTransportFd& socket, FdTrigger* fdTrigger) {
+static bool setFdAndDoHandshake(Ssl* ssl, const android::RpcTransportFd& socket,
+ FdTrigger* fdTrigger) {
bssl::UniquePtr<BIO> bio = newSocketBio(socket.fd);
TEST_AND_RETURN(false, bio != nullptr);
auto [_, errorQueue] = ssl->call(SSL_set_bio, bio.get(), bio.get());
@@ -540,8 +543,6 @@
}
};
-} // namespace
-
std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTls::newServerCtx() const {
return android::RpcTransportCtxTls::create<RpcTransportCtxTlsServer>(mCertVerifier,
mAuth.get());
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index 07b38d7..2b3ff44 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -16,9 +16,15 @@
"name": "binderDriverInterfaceTest"
},
{
+ "name": "binderRecordReplayTest"
+ },
+ {
"name": "binderHostDeviceTest"
},
{
+ "name": "binderParcelBenchmark"
+ },
+ {
"name": "binderTextOutputTest"
},
{
@@ -58,6 +64,9 @@
"name": "libbinderthreadstateutils_test"
},
{
+ "name": "fuzz_service_test"
+ },
+ {
"name": "CtsOsTestCases",
"options": [
{
@@ -79,6 +88,12 @@
},
{
"name": "rustBinderSerializationTest"
+ },
+ {
+ "name": "libbinder_ndk_bindgen_test"
+ },
+ {
+ "name": "libbinder_rpc_unstable_bindgen_test"
}
],
"presubmit-large": [
@@ -86,12 +101,6 @@
"name": "binderRpcTest"
},
{
- "name": "CtsRootRollbackManagerHostTestCases"
- },
- {
- "name": "StagedRollbackTest"
- },
- {
"name": "binderRpcTestNoKernel"
},
{
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index d960a0b..744da0f 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -105,12 +105,6 @@
[[nodiscard]] status_t setRpcClientDebug(android::base::unique_fd clientFd,
const sp<IBinder>& keepAliveBinder);
- // Start recording transactions to the unique_fd in data.
- // See RecordedTransaction.h for more details.
- [[nodiscard]] status_t startRecordingTransactions(const Parcel& data);
- // Stop the current recording.
- [[nodiscard]] status_t stopRecordingTransactions();
-
protected:
virtual ~BBinder();
@@ -131,6 +125,8 @@
[[nodiscard]] status_t setRpcClientDebug(const Parcel& data);
void removeRpcServerLink(const sp<RpcServerLink>& link);
+ [[nodiscard]] status_t startRecordingTransactions(const Parcel& data);
+ [[nodiscard]] status_t stopRecordingTransactions();
std::atomic<Extras*> mExtras;
diff --git a/libs/binder/include/binder/LazyServiceRegistrar.h b/libs/binder/include/binder/LazyServiceRegistrar.h
index 2e22b84..bda3d19 100644
--- a/libs/binder/include/binder/LazyServiceRegistrar.h
+++ b/libs/binder/include/binder/LazyServiceRegistrar.h
@@ -93,7 +93,17 @@
*/
void reRegister();
- private:
+ /**
+ * Create a second instance of lazy service registrar.
+ *
+ * WARNING: dangerous! DO NOT USE THIS - LazyServiceRegistrar
+ * should be single-instanced, so that the service will only
+ * shut down when all services are unused. A separate instance
+ * is only used to test race conditions.
+ */
+ static LazyServiceRegistrar createExtraTestInstance();
+
+ private:
std::shared_ptr<internal::ClientCounterCallback> mClientCC;
LazyServiceRegistrar();
};
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 162cd40..e28d374 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -34,13 +34,8 @@
#include <binder/IInterface.h>
#include <binder/Parcelable.h>
-#ifdef BINDER_IPC_32BIT
-//NOLINTNEXTLINE(google-runtime-int) b/173188702
-typedef unsigned int binder_size_t;
-#else
//NOLINTNEXTLINE(google-runtime-int) b/173188702
typedef unsigned long long binder_size_t;
-#endif
struct flat_binder_object;
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index ce578e3..81391e9 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -55,7 +55,7 @@
// For main functions - dangerous for libraries to use
void startThreadPool();
- bool becomeContextManager();
+ [[nodiscard]] bool becomeContextManager();
sp<IBinder> getStrongProxyForHandle(int32_t handle);
void expungeHandle(int32_t handle, IBinder* binder);
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index 1001b64..b804f7b 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -137,7 +137,7 @@
* used. However, this can be used in order to prevent newer protocol
* versions from ever being used. This is expected to be useful for testing.
*/
- void setProtocolVersion(uint32_t version);
+ [[nodiscard]] bool setProtocolVersion(uint32_t version);
/**
* Set the supported transports for sending and receiving file descriptors.
@@ -163,14 +163,18 @@
* Allows a root object to be created for each session.
*
* Takes one argument: a callable that is invoked once per new session.
- * The callable takes two arguments: a type-erased pointer to an OS- and
- * transport-specific address structure, e.g., sockaddr_vm for vsock, and
- * an integer representing the size in bytes of that structure. The
- * callable should validate the size, then cast the type-erased pointer
- * to a pointer to the actual type of the address, e.g., const void* to
- * const sockaddr_vm*.
+ * The callable takes three arguments:
+ * - a weak pointer to the session. If you want to hold onto this in the root object, then
+ * you should keep a weak pointer, and promote it when needed. For instance, if you refer
+ * to this from the root object, then you could get ahold of transport-specific information.
+ * - a type-erased pointer to an OS- and transport-specific address structure, e.g.,
+ * sockaddr_vm for vsock
+ * - an integer representing the size in bytes of that structure. The callable should
+ * validate the size, then cast the type-erased pointer to a pointer to the actual type of the
+ * address, e.g., const void* to const sockaddr_vm*.
*/
- void setPerSessionRootObject(std::function<sp<IBinder>(const void*, size_t)>&& object);
+ void setPerSessionRootObject(
+ std::function<sp<IBinder>(wp<RpcSession> session, const void*, size_t)>&& object);
sp<IBinder> getRootObject();
/**
@@ -184,6 +188,13 @@
void setConnectionFilter(std::function<bool(const void*, size_t)>&& filter);
/**
+ * Set optional modifier of each newly created server socket.
+ *
+ * The only argument is a successfully created file descriptor, not bound to an address yet.
+ */
+ void setServerSocketModifier(std::function<void(base::borrowed_fd)>&& modifier);
+
+ /**
* See RpcTransportCtx::getCertificate
*/
std::vector<uint8_t> getCertificate(RpcCertificateFormat);
@@ -265,8 +276,9 @@
sp<IBinder> mRootObject;
wp<IBinder> mRootObjectWeak;
- std::function<sp<IBinder>(const void*, size_t)> mRootObjectFactory;
+ std::function<sp<IBinder>(wp<RpcSession>, const void*, size_t)> mRootObjectFactory;
std::function<bool(const void*, size_t)> mConnectionFilter;
+ std::function<void(base::borrowed_fd)> mServerSocketModifier;
std::map<std::vector<uint8_t>, sp<RpcSession>> mSessions;
std::unique_ptr<FdTrigger> mShutdownTrigger;
RpcConditionVariable mShutdownCv;
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index a323feb..cb64603 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -37,9 +37,9 @@
class RpcTransport;
class FdTrigger;
-constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_NEXT = 1;
+constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_NEXT = 2;
constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL = 0xF0000000;
-constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION = RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL;
+constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION = 1;
// Starting with this version:
//
diff --git a/libs/binder/include/binder/RpcTransport.h b/libs/binder/include/binder/RpcTransport.h
index fd52a3a..6db9ad9 100644
--- a/libs/binder/include/binder/RpcTransport.h
+++ b/libs/binder/include/binder/RpcTransport.h
@@ -39,6 +39,16 @@
class FdTrigger;
struct RpcTransportFd;
+// for 'friend'
+class RpcTransportRaw;
+class RpcTransportTls;
+class RpcTransportTipcAndroid;
+class RpcTransportTipcTrusty;
+class RpcTransportCtxRaw;
+class RpcTransportCtxTls;
+class RpcTransportCtxTipcAndroid;
+class RpcTransportCtxTipcTrusty;
+
// Represents a socket connection.
// No thread-safety is guaranteed for these APIs.
class RpcTransport {
@@ -92,7 +102,21 @@
*/
[[nodiscard]] virtual bool isWaiting() = 0;
-protected:
+private:
+ // limit the classes which can implement RpcTransport. Being able to change this
+ // interface is important to allow development of RPC binder. In the past, we
+ // changed this interface to use iovec for efficiency, and we added FDs to the
+ // interface. If another transport is needed, it should be added directly here.
+ // non-socket FDs likely also need changes in RpcSession in order to get
+ // connected, and similarly to how addrinfo was type-erased from RPC binder
+ // interfaces when RpcTransportTipc* was added, other changes may be needed
+ // to add more transports.
+
+ friend class ::android::RpcTransportRaw;
+ friend class ::android::RpcTransportTls;
+ friend class ::android::RpcTransportTipcAndroid;
+ friend class ::android::RpcTransportTipcTrusty;
+
RpcTransport() = default;
};
@@ -117,7 +141,13 @@
[[nodiscard]] virtual std::vector<uint8_t> getCertificate(
RpcCertificateFormat format) const = 0;
-protected:
+private:
+ // see comment on RpcTransport
+ friend class ::android::RpcTransportCtxRaw;
+ friend class ::android::RpcTransportCtxTls;
+ friend class ::android::RpcTransportCtxTipcAndroid;
+ friend class ::android::RpcTransportCtxTipcTrusty;
+
RpcTransportCtx() = default;
};
@@ -140,7 +170,7 @@
RpcTransportCtxFactory() = default;
};
-struct RpcTransportFd {
+struct RpcTransportFd final {
private:
mutable bool isPolling{false};
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
index 43159d8..89fd7a3 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -56,12 +56,12 @@
*
* \param binder object to register globally with the service manager.
* \param instance identifier of the service. This will be used to lookup the service.
- * \param flag an AServiceManager_AddServiceFlag enum to denote how the service should be added.
+ * \param flags an AServiceManager_AddServiceFlag enum to denote how the service should be added.
*
* \return EX_NONE on success.
*/
-__attribute__((warn_unused_result)) binder_exception_t AServiceManager_addServiceWithFlag(
- AIBinder* binder, const char* instance, const AServiceManager_AddServiceFlag flag)
+__attribute__((warn_unused_result)) binder_exception_t AServiceManager_addServiceWithFlags(
+ AIBinder* binder, const char* instance, const AServiceManager_AddServiceFlag flags)
__INTRODUCED_IN(34);
/**
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 1078fb2..1c5f79f 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -158,7 +158,7 @@
AServiceManager_getUpdatableApexName; # systemapi
AServiceManager_registerForServiceNotifications; # systemapi llndk
AServiceManager_NotificationRegistration_delete; # systemapi llndk
- AServiceManager_addServiceWithFlag; # systemapi llndk
+ AServiceManager_addServiceWithFlags; # systemapi llndk
};
LIBBINDER_NDK_PLATFORM {
diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp
index 84da459..2977786 100644
--- a/libs/binder/ndk/service_manager.cpp
+++ b/libs/binder/ndk/service_manager.cpp
@@ -42,15 +42,15 @@
return PruneException(exception);
}
-binder_exception_t AServiceManager_addServiceWithFlag(AIBinder* binder, const char* instance,
- const AServiceManager_AddServiceFlag flag) {
+binder_exception_t AServiceManager_addServiceWithFlags(AIBinder* binder, const char* instance,
+ const AServiceManager_AddServiceFlag flags) {
if (binder == nullptr || instance == nullptr) {
return EX_ILLEGAL_ARGUMENT;
}
sp<IServiceManager> sm = defaultServiceManager();
- bool allowIsolated = flag & AServiceManager_AddServiceFlag::ADD_SERVICE_ALLOW_ISOLATED;
+ bool allowIsolated = flags & AServiceManager_AddServiceFlag::ADD_SERVICE_ALLOW_ISOLATED;
status_t exception = sm->addService(String16(instance), binder->getBinder(), allowIsolated);
return PruneException(exception);
}
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 882f1d6..8c9844c 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -51,8 +51,9 @@
constexpr char kLazyBinderNdkUnitTestService[] = "LazyBinderNdkUnitTest";
constexpr char kForcePersistNdkUnitTestService[] = "ForcePersistNdkUnitTestService";
constexpr char kActiveServicesNdkUnitTestService[] = "ActiveServicesNdkUnitTestService";
+constexpr char kBinderNdkUnitTestServiceFlagged[] = "BinderNdkUnitTestFlagged";
-constexpr unsigned int kShutdownWaitTime = 11;
+constexpr unsigned int kShutdownWaitTime = 20;
constexpr uint64_t kContextTestValue = 0xb4e42fb4d9a1d715;
class MyTestFoo : public IFoo {
@@ -158,6 +159,24 @@
return 1; // should not return
}
+int generatedFlaggedService(const AServiceManager_AddServiceFlag flags, const char* instance) {
+ ABinderProcess_setThreadPoolMaxThreadCount(0);
+
+ auto service = ndk::SharedRefBase::make<MyBinderNdkUnitTest>();
+ auto binder = service->asBinder();
+
+ binder_exception_t exception =
+ AServiceManager_addServiceWithFlags(binder.get(), instance, flags);
+
+ if (exception != EX_NONE) {
+ LOG(FATAL) << "Could not register: " << exception << " " << instance;
+ }
+
+ ABinderProcess_joinThreadPool();
+
+ return 1; // should not return
+}
+
// manually-written parceling class considered bad practice
class MyFoo : public IFoo {
binder_status_t doubleNumber(int32_t in, int32_t* out) override {
@@ -478,14 +497,28 @@
struct DeathRecipientCookie {
std::function<void(void)>*onDeath, *onUnlink;
+
+ // may contain additional data
+ // - if it contains AIBinder, then you must call AIBinder_unlinkToDeath manually,
+ // because it would form a strong reference cycle
+ // - if it points to a data member of another structure, this should have a weak
+ // promotable reference or a strong reference, in case that object is deleted
+ // while the death recipient is firing
};
void LambdaOnDeath(void* cookie) {
auto funcs = static_cast<DeathRecipientCookie*>(cookie);
+
+ // may reference other cookie members
+
(*funcs->onDeath)();
};
void LambdaOnUnlink(void* cookie) {
auto funcs = static_cast<DeathRecipientCookie*>(cookie);
(*funcs->onUnlink)();
+
+ // may reference other cookie members
+
+ delete funcs;
};
TEST(NdkBinder, DeathRecipient) {
using namespace std::chrono_literals;
@@ -517,12 +550,12 @@
unlinkCv.notify_one();
};
- DeathRecipientCookie cookie = {&onDeath, &onUnlink};
+ DeathRecipientCookie* cookie = new DeathRecipientCookie{&onDeath, &onUnlink};
AIBinder_DeathRecipient* recipient = AIBinder_DeathRecipient_new(LambdaOnDeath);
AIBinder_DeathRecipient_setOnUnlinked(recipient, LambdaOnUnlink);
- EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, recipient, static_cast<void*>(&cookie)));
+ EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, recipient, static_cast<void*>(cookie)));
// the binder driver should return this if the service dies during the transaction
EXPECT_EQ(STATUS_DEAD_OBJECT, foo->die());
@@ -847,6 +880,12 @@
EXPECT_EQ("CMD", shellCmdToString(testService, {"C", "M", "D"}));
}
+TEST(NdkBinder, FlaggedServiceAccessible) {
+ static const sp<android::IServiceManager> sm(android::defaultServiceManager());
+ sp<IBinder> testService = sm->getService(String16(kBinderNdkUnitTestServiceFlagged));
+ ASSERT_NE(nullptr, testService);
+}
+
TEST(NdkBinder, GetClassInterfaceDescriptor) {
ASSERT_STREQ(IFoo::kIFooDescriptor, AIBinder_Class_getDescriptor(IFoo::kClass));
}
@@ -901,6 +940,13 @@
prctl(PR_SET_PDEATHSIG, SIGHUP);
return generatedService();
}
+ if (fork() == 0) {
+ prctl(PR_SET_PDEATHSIG, SIGHUP);
+ // We may want to change this flag to be more generic ones for the future
+ AServiceManager_AddServiceFlag test_flags =
+ AServiceManager_AddServiceFlag::ADD_SERVICE_ALLOW_ISOLATED;
+ return generatedFlaggedService(test_flags, kBinderNdkUnitTestServiceFlagged);
+ }
ABinderProcess_setThreadPoolMaxThreadCount(1); // to receive death notifications/callbacks
ABinderProcess_startThreadPool();
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
index d0e35de..b90b40b 100644
--- a/libs/binder/rust/src/binder.rs
+++ b/libs/binder/rust/src/binder.rs
@@ -1122,6 +1122,10 @@
}
impl $crate::binder_impl::Deserialize for $enum {
+ type UninitType = Self;
+ fn uninit() -> Self::UninitType { Self::UninitType::default() }
+ fn from_init(value: Self) -> Self::UninitType { value }
+
fn deserialize(parcel: &$crate::binder_impl::BorrowedParcel<'_>) -> std::result::Result<Self, $crate::StatusCode> {
parcel.read().map(Self)
}
diff --git a/libs/binder/rust/src/error.rs b/libs/binder/rust/src/error.rs
index f6b09ed..ba26062 100644
--- a/libs/binder/rust/src/error.rs
+++ b/libs/binder/rust/src/error.rs
@@ -20,6 +20,7 @@
use std::error;
use std::ffi::{CStr, CString};
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
+use std::ptr;
use std::result;
pub use sys::binder_status_t as status_t;
@@ -92,7 +93,7 @@
/// track of and chain binder errors along with service specific errors.
///
/// Used in AIDL transactions to represent failed transactions.
-pub struct Status(*mut sys::AStatus);
+pub struct Status(ptr::NonNull<sys::AStatus>);
// Safety: The `AStatus` that the `Status` points to must have an entirely thread-safe API for the
// duration of the `Status` object's lifetime. We ensure this by not allowing mutation of a `Status`
@@ -119,7 +120,7 @@
// Rust takes ownership of the returned pointer.
sys::AStatus_newOk()
};
- Self(ptr)
+ Self(ptr::NonNull::new(ptr).expect("Unexpected null AStatus pointer"))
}
/// Create a status object from a service specific error
@@ -147,7 +148,7 @@
sys::AStatus_fromServiceSpecificError(err)
}
};
- Self(ptr)
+ Self(ptr::NonNull::new(ptr).expect("Unexpected null AStatus pointer"))
}
/// Creates a status object from a service specific error.
@@ -161,7 +162,7 @@
let ptr = unsafe {
sys::AStatus_fromExceptionCodeWithMessage(exception as i32, message.as_ptr())
};
- Self(ptr)
+ Self(ptr::NonNull::new(ptr).expect("Unexpected null AStatus pointer"))
} else {
exception.into()
}
@@ -181,7 +182,7 @@
///
/// This constructor is safe iff `ptr` is a valid pointer to an `AStatus`.
pub(crate) unsafe fn from_ptr(ptr: *mut sys::AStatus) -> Self {
- Self(ptr)
+ Self(ptr::NonNull::new(ptr).expect("Unexpected null AStatus pointer"))
}
/// Returns `true` if this status represents a successful transaction.
@@ -326,7 +327,7 @@
// UNKNOWN_ERROR.
sys::AStatus_fromStatus(status)
};
- Self(ptr)
+ Self(ptr::NonNull::new(ptr).expect("Unexpected null AStatus pointer"))
}
}
@@ -338,7 +339,7 @@
// Unknown values will be coerced into EX_TRANSACTION_FAILED.
sys::AStatus_fromExceptionCode(code as i32)
};
- Self(ptr)
+ Self(ptr::NonNull::new(ptr).expect("Unexpected null AStatus pointer"))
}
}
@@ -367,7 +368,7 @@
// pointee, so we need to delete it here. We know that the pointer
// will be valid here since `Status` always contains a valid pointer
// while it is alive.
- sys::AStatus_delete(self.0);
+ sys::AStatus_delete(self.0.as_mut());
}
}
}
@@ -381,11 +382,15 @@
/// `Status` object is still alive.
unsafe impl AsNative<sys::AStatus> for Status {
fn as_native(&self) -> *const sys::AStatus {
- self.0
+ self.0.as_ptr()
}
fn as_native_mut(&mut self) -> *mut sys::AStatus {
- self.0
+ unsafe {
+ // Safety: The pointer will be valid here since `Status` always
+ // contains a valid and initialized pointer while it is alive.
+ self.0.as_mut()
+ }
}
}
diff --git a/libs/binder/rust/src/parcel/file_descriptor.rs b/libs/binder/rust/src/parcel/file_descriptor.rs
index de6d649..7fe37f3 100644
--- a/libs/binder/rust/src/parcel/file_descriptor.rs
+++ b/libs/binder/rust/src/parcel/file_descriptor.rs
@@ -132,6 +132,14 @@
}
impl Deserialize for ParcelFileDescriptor {
+ type UninitType = Option<Self>;
+ fn uninit() -> Self::UninitType {
+ Self::UninitType::default()
+ }
+ fn from_init(value: Self) -> Self::UninitType {
+ Some(value)
+ }
+
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
Deserialize::deserialize(parcel).transpose().unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
}
diff --git a/libs/binder/rust/src/parcel/parcelable.rs b/libs/binder/rust/src/parcel/parcelable.rs
index 4b658fc..5d8c11c 100644
--- a/libs/binder/rust/src/parcel/parcelable.rs
+++ b/libs/binder/rust/src/parcel/parcelable.rs
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-use crate::binder::{AsNative, FromIBinder, Stability, Strong};
+use crate::binder::{AsNative, FromIBinder, Interface, Stability, Strong};
use crate::error::{status_result, status_t, Result, Status, StatusCode};
use crate::parcel::BorrowedParcel;
use crate::proxy::SpIBinder;
@@ -22,7 +22,7 @@
use std::convert::{TryFrom, TryInto};
use std::ffi::c_void;
-use std::mem::{self, ManuallyDrop, MaybeUninit};
+use std::mem::{self, ManuallyDrop};
use std::os::raw::c_char;
use std::ptr;
use std::slice;
@@ -60,6 +60,26 @@
/// A struct whose instances can be restored from a [`Parcel`].
// Might be able to hook this up as a serde backend in the future?
pub trait Deserialize: Sized {
+ /// Type for the uninitialized value of this type. Will be either `Self`
+ /// if the type implements `Default`, `Option<Self>` otherwise.
+ type UninitType;
+
+ /// Assert at compile-time that `Self` and `Self::UninitType` have the same
+ /// size and alignment. This will either fail to compile or evaluate to `true`.
+ /// The only two macros that work here are `panic!` and `assert!`, so we cannot
+ /// use `assert_eq!`.
+ const ASSERT_UNINIT_SIZE_AND_ALIGNMENT: bool = {
+ assert!(std::mem::size_of::<Self>() == std::mem::size_of::<Self::UninitType>());
+ assert!(std::mem::align_of::<Self>() == std::mem::align_of::<Self::UninitType>());
+ true
+ };
+
+ /// Return an uninitialized or default-initialized value for this type.
+ fn uninit() -> Self::UninitType;
+
+ /// Convert an initialized value of type `Self` into `Self::UninitType`.
+ fn from_init(value: Self) -> Self::UninitType;
+
/// Deserialize an instance from the given [`Parcel`].
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self>;
@@ -121,7 +141,7 @@
pub trait DeserializeArray: Deserialize {
/// Deserialize an array of type from the given parcel.
fn deserialize_array(parcel: &BorrowedParcel<'_>) -> Result<Option<Vec<Self>>> {
- let mut vec: Option<Vec<MaybeUninit<Self>>> = None;
+ let mut vec: Option<Vec<Self::UninitType>> = None;
let res = unsafe {
// Safety: Safe FFI, vec is the correct opaque type expected by
// allocate_vec and deserialize_element.
@@ -136,8 +156,8 @@
let vec: Option<Vec<Self>> = unsafe {
// Safety: We are assuming that the NDK correctly initialized every
// element of the vector by now, so we know that all the
- // MaybeUninits are now properly initialized. We can transmute from
- // Vec<MaybeUninit<T>> to Vec<T> because MaybeUninit<T> has the same
+ // UninitTypes are now properly initialized. We can transmute from
+ // Vec<T::UninitType> to Vec<T> because T::UninitType has the same
// alignment and size as T, so the pointer to the vector allocation
// will be compatible.
mem::transmute(vec)
@@ -149,14 +169,14 @@
/// Callback to deserialize a parcelable element.
///
/// The opaque array data pointer must be a mutable pointer to an
-/// `Option<Vec<MaybeUninit<T>>>` with at least enough elements for `index` to be valid
+/// `Option<Vec<T::UninitType>>` with at least enough elements for `index` to be valid
/// (zero-based).
unsafe extern "C" fn deserialize_element<T: Deserialize>(
parcel: *const sys::AParcel,
array: *mut c_void,
index: usize,
) -> status_t {
- let vec = &mut *(array as *mut Option<Vec<MaybeUninit<T>>>);
+ let vec = &mut *(array as *mut Option<Vec<T::UninitType>>);
let vec = match vec {
Some(v) => v,
None => return StatusCode::BAD_INDEX as status_t,
@@ -170,7 +190,7 @@
Ok(e) => e,
Err(code) => return code as status_t,
};
- ptr::write(vec[index].as_mut_ptr(), element);
+ vec[index] = T::from_init(element);
StatusCode::OK as status_t
}
@@ -233,15 +253,15 @@
/// # Safety
///
/// The opaque data pointer passed to the array read function must be a mutable
-/// pointer to an `Option<Vec<MaybeUninit<T>>>`. `buffer` will be assigned a mutable pointer
+/// pointer to an `Option<Vec<T::UninitType>>`. `buffer` will be assigned a mutable pointer
/// to the allocated vector data if this function returns true.
-unsafe extern "C" fn allocate_vec_with_buffer<T>(
+unsafe extern "C" fn allocate_vec_with_buffer<T: Deserialize>(
data: *mut c_void,
len: i32,
buffer: *mut *mut T,
) -> bool {
let res = allocate_vec::<T>(data, len);
- let vec = &mut *(data as *mut Option<Vec<MaybeUninit<T>>>);
+ let vec = &mut *(data as *mut Option<Vec<T::UninitType>>);
if let Some(new_vec) = vec {
*buffer = new_vec.as_mut_ptr() as *mut T;
}
@@ -253,20 +273,18 @@
/// # Safety
///
/// The opaque data pointer passed to the array read function must be a mutable
-/// pointer to an `Option<Vec<MaybeUninit<T>>>`.
-unsafe extern "C" fn allocate_vec<T>(data: *mut c_void, len: i32) -> bool {
- let vec = &mut *(data as *mut Option<Vec<MaybeUninit<T>>>);
+/// pointer to an `Option<Vec<T::UninitType>>`.
+unsafe extern "C" fn allocate_vec<T: Deserialize>(data: *mut c_void, len: i32) -> bool {
+ let vec = &mut *(data as *mut Option<Vec<T::UninitType>>);
if len < 0 {
*vec = None;
return true;
}
- let mut new_vec: Vec<MaybeUninit<T>> = Vec::with_capacity(len as usize);
- // Safety: We are filling the vector with uninitialized data here, but this
- // is safe because the vector contains MaybeUninit elements which can be
- // uninitialized. We're putting off the actual unsafe bit, transmuting the
- // vector to a Vec<T> until the contents are initialized.
- new_vec.set_len(len as usize);
+ // Assert at compile time that `T` and `T::UninitType` have the same size and alignment.
+ let _ = T::ASSERT_UNINIT_SIZE_AND_ALIGNMENT;
+ let mut new_vec: Vec<T::UninitType> = Vec::with_capacity(len as usize);
+ new_vec.resize_with(len as usize, T::uninit);
ptr::write(vec, Some(new_vec));
true
@@ -283,8 +301,11 @@
}
/// Safety: All elements in the vector must be properly initialized.
-unsafe fn vec_assume_init<T>(vec: Vec<MaybeUninit<T>>) -> Vec<T> {
- // We can convert from Vec<MaybeUninit<T>> to Vec<T> because MaybeUninit<T>
+unsafe fn vec_assume_init<T: Deserialize>(vec: Vec<T::UninitType>) -> Vec<T> {
+ // Assert at compile time that `T` and `T::UninitType` have the same size and alignment.
+ let _ = T::ASSERT_UNINIT_SIZE_AND_ALIGNMENT;
+
+ // We can convert from Vec<T::UninitType> to Vec<T> because T::UninitType
// has the same alignment and size as T, so the pointer to the vector
// allocation will be compatible.
let mut vec = ManuallyDrop::new(vec);
@@ -307,6 +328,9 @@
{Deserialize, $ty:ty, $read_fn:path} => {
impl Deserialize for $ty {
+ type UninitType = Self;
+ fn uninit() -> Self::UninitType { Self::UninitType::default() }
+ fn from_init(value: Self) -> Self::UninitType { value }
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
let mut val = Self::default();
unsafe {
@@ -348,11 +372,11 @@
{DeserializeArray, $ty:ty, $read_array_fn:path} => {
impl DeserializeArray for $ty {
fn deserialize_array(parcel: &BorrowedParcel<'_>) -> Result<Option<Vec<Self>>> {
- let mut vec: Option<Vec<MaybeUninit<Self>>> = None;
+ let mut vec: Option<Vec<Self::UninitType>> = None;
let status = unsafe {
// Safety: `Parcel` always contains a valid pointer to an
// `AParcel`. `allocate_vec<T>` expects the opaque pointer to
- // be of type `*mut Option<Vec<MaybeUninit<T>>>`, so `&mut vec` is
+ // be of type `*mut Option<Vec<T::UninitType>>`, so `&mut vec` is
// correct for it.
$read_array_fn(
parcel.as_native(),
@@ -364,7 +388,7 @@
let vec: Option<Vec<Self>> = unsafe {
// Safety: We are assuming that the NDK correctly
// initialized every element of the vector by now, so we
- // know that all the MaybeUninits are now properly
+ // know that all the UninitTypes are now properly
// initialized.
vec.map(|vec| vec_assume_init(vec))
};
@@ -440,6 +464,14 @@
}
impl Deserialize for u8 {
+ type UninitType = Self;
+ fn uninit() -> Self::UninitType {
+ Self::UninitType::default()
+ }
+ fn from_init(value: Self) -> Self::UninitType {
+ value
+ }
+
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
i8::deserialize(parcel).map(|v| v as u8)
}
@@ -471,6 +503,14 @@
}
impl Deserialize for i16 {
+ type UninitType = Self;
+ fn uninit() -> Self::UninitType {
+ Self::UninitType::default()
+ }
+ fn from_init(value: Self) -> Self::UninitType {
+ value
+ }
+
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
u16::deserialize(parcel).map(|v| v as i16)
}
@@ -547,6 +587,14 @@
}
impl Deserialize for Option<String> {
+ type UninitType = Self;
+ fn uninit() -> Self::UninitType {
+ Self::UninitType::default()
+ }
+ fn from_init(value: Self) -> Self::UninitType {
+ value
+ }
+
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
let mut vec: Option<Vec<u8>> = None;
let status = unsafe {
@@ -575,6 +623,14 @@
impl DeserializeArray for Option<String> {}
impl Deserialize for String {
+ type UninitType = Self;
+ fn uninit() -> Self::UninitType {
+ Self::UninitType::default()
+ }
+ fn from_init(value: Self) -> Self::UninitType {
+ value
+ }
+
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
Deserialize::deserialize(parcel).transpose().unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
}
@@ -611,6 +667,14 @@
}
impl<T: DeserializeArray> Deserialize for Vec<T> {
+ type UninitType = Self;
+ fn uninit() -> Self::UninitType {
+ Self::UninitType::default()
+ }
+ fn from_init(value: Self) -> Self::UninitType {
+ value
+ }
+
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
DeserializeArray::deserialize_array(parcel)
.transpose()
@@ -640,6 +704,14 @@
impl<T: SerializeArray, const N: usize> SerializeArray for [T; N] {}
impl<T: DeserializeArray, const N: usize> Deserialize for [T; N] {
+ type UninitType = [T::UninitType; N];
+ fn uninit() -> Self::UninitType {
+ [(); N].map(|_| T::uninit())
+ }
+ fn from_init(value: Self) -> Self::UninitType {
+ value.map(T::from_init)
+ }
+
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
let vec = DeserializeArray::deserialize_array(parcel)
.transpose()
@@ -664,6 +736,14 @@
}
impl Deserialize for Stability {
+ type UninitType = Self;
+ fn uninit() -> Self::UninitType {
+ Self::UninitType::default()
+ }
+ fn from_init(value: Self) -> Self::UninitType {
+ value
+ }
+
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
i32::deserialize(parcel).and_then(Stability::try_from)
}
@@ -682,6 +762,14 @@
}
impl Deserialize for Status {
+ type UninitType = Option<Self>;
+ fn uninit() -> Self::UninitType {
+ Self::UninitType::default()
+ }
+ fn from_init(value: Self) -> Self::UninitType {
+ Some(value)
+ }
+
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
let mut status_ptr = ptr::null_mut();
let ret_status = unsafe {
@@ -717,12 +805,29 @@
impl<T: Serialize + FromIBinder + ?Sized> SerializeArray for Strong<T> {}
impl<T: FromIBinder + ?Sized> Deserialize for Strong<T> {
+ type UninitType = Option<Strong<T>>;
+ fn uninit() -> Self::UninitType {
+ Self::UninitType::default()
+ }
+ fn from_init(value: Self) -> Self::UninitType {
+ Some(value)
+ }
+
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
let ibinder: SpIBinder = parcel.read()?;
FromIBinder::try_from(ibinder)
}
}
+struct AssertIBinder;
+impl Interface for AssertIBinder {}
+impl FromIBinder for AssertIBinder {
+ // This is only needed so we can assert on the size of Strong<AssertIBinder>
+ fn try_from(_: SpIBinder) -> Result<Strong<Self>> {
+ unimplemented!()
+ }
+}
+
impl<T: FromIBinder + ?Sized> DeserializeOption for Strong<T> {
fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<Self>> {
let ibinder: Option<SpIBinder> = parcel.read()?;
@@ -752,6 +857,14 @@
}
impl<T: DeserializeOption> Deserialize for Option<T> {
+ type UninitType = Self;
+ fn uninit() -> Self::UninitType {
+ Self::UninitType::default()
+ }
+ fn from_init(value: Self) -> Self::UninitType {
+ value
+ }
+
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
DeserializeOption::deserialize_option(parcel)
}
@@ -821,6 +934,9 @@
};
($parcelable:ident < $( $param:ident ),* > ) => {
impl < $($param: Default),* > $crate::binder_impl::Deserialize for $parcelable < $($param),* > {
+ type UninitType = Self;
+ fn uninit() -> Self::UninitType { Self::UninitType::default() }
+ fn from_init(value: Self) -> Self::UninitType { value }
fn deserialize(
parcel: &$crate::binder_impl::BorrowedParcel<'_>,
) -> std::result::Result<Self, $crate::StatusCode> {
@@ -876,6 +992,14 @@
}
impl<T: Deserialize> Deserialize for Box<T> {
+ type UninitType = Option<Self>;
+ fn uninit() -> Self::UninitType {
+ Self::UninitType::default()
+ }
+ fn from_init(value: Self) -> Self::UninitType {
+ Some(value)
+ }
+
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
Deserialize::deserialize(parcel).map(Box::new)
}
@@ -900,6 +1024,7 @@
#[test]
fn test_custom_parcelable() {
+ #[derive(Default)]
struct Custom(u32, bool, String, Vec<String>);
impl Serialize for Custom {
@@ -912,6 +1037,14 @@
}
impl Deserialize for Custom {
+ type UninitType = Self;
+ fn uninit() -> Self::UninitType {
+ Self::UninitType::default()
+ }
+ fn from_init(value: Self) -> Self::UninitType {
+ value
+ }
+
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
Ok(Custom(
parcel.read()?,
diff --git a/libs/binder/rust/src/parcel/parcelable_holder.rs b/libs/binder/rust/src/parcel/parcelable_holder.rs
index c829d37..383cc83 100644
--- a/libs/binder/rust/src/parcel/parcelable_holder.rs
+++ b/libs/binder/rust/src/parcel/parcelable_holder.rs
@@ -169,6 +169,14 @@
}
impl Deserialize for ParcelableHolder {
+ type UninitType = Self;
+ fn uninit() -> Self::UninitType {
+ Self::new(Default::default())
+ }
+ fn from_init(value: Self) -> Self::UninitType {
+ value
+ }
+
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self, StatusCode> {
let status: i32 = parcel.read()?;
if status == NULL_PARCELABLE_FLAG {
diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs
index 254efae..036f6b4 100644
--- a/libs/binder/rust/src/proxy.rs
+++ b/libs/binder/rust/src/proxy.rs
@@ -439,6 +439,14 @@
impl SerializeArray for SpIBinder {}
impl Deserialize for SpIBinder {
+ type UninitType = Option<Self>;
+ fn uninit() -> Self::UninitType {
+ Self::UninitType::default()
+ }
+ fn from_init(value: Self) -> Self::UninitType {
+ Some(value)
+ }
+
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<SpIBinder> {
parcel.read_binder().transpose().unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
}
diff --git a/libs/binder/rust/tests/parcel_fuzzer/Android.bp b/libs/binder/rust/tests/parcel_fuzzer/Android.bp
index df8a2af..ac96823 100644
--- a/libs/binder/rust/tests/parcel_fuzzer/Android.bp
+++ b/libs/binder/rust/tests/parcel_fuzzer/Android.bp
@@ -21,6 +21,7 @@
"waghpawan@google.com",
"smoreland@google.com",
],
+ triage_assignee: "waghpawan@google.com",
// hotlist "AIDL fuzzers bugs" on buganizer
hotlists: ["4637097"],
},
diff --git a/libs/binder/rust/tests/parcel_fuzzer/random_parcel/fuzz_service_test/Android.bp b/libs/binder/rust/tests/parcel_fuzzer/random_parcel/fuzz_service_test/Android.bp
index 5cb406a..89126ca 100644
--- a/libs/binder/rust/tests/parcel_fuzzer/random_parcel/fuzz_service_test/Android.bp
+++ b/libs/binder/rust/tests/parcel_fuzzer/random_parcel/fuzz_service_test/Android.bp
@@ -19,6 +19,11 @@
srcs: [
"service_fuzzer.rs",
],
+ shared_libs: [
+ "libbinder",
+ "libbinder_ndk",
+ "libutils",
+ ],
rustlibs: [
"libbinder_rs",
"libbinder_random_parcel_rs",
@@ -29,6 +34,7 @@
"waghpawan@google.com",
"smoreland@google.com",
],
+ triage_assignee: "waghpawan@google.com",
// hotlist "AIDL fuzzers bugs" on buganizer
hotlists: ["4637097"],
},
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 0f0d64a..41856f9 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -32,28 +32,8 @@
}
cc_test {
- name: "binderDriverInterfaceTest_IPC_32",
- defaults: ["binder_test_defaults"],
- srcs: ["binderDriverInterfaceTest.cpp"],
- header_libs: ["libbinder_headers"],
- compile_multilib: "32",
- multilib: {
- lib32: {
- suffix: "",
- },
- },
- cflags: ["-DBINDER_IPC_32BIT=1"],
- test_suites: ["vts"],
-}
-
-cc_test {
name: "binderDriverInterfaceTest",
defaults: ["binder_test_defaults"],
- product_variables: {
- binder32bit: {
- cflags: ["-DBINDER_IPC_32BIT=1"],
- },
- },
header_libs: ["libbinder_headers"],
srcs: ["binderDriverInterfaceTest.cpp"],
test_suites: [
@@ -62,30 +42,6 @@
],
}
-cc_test {
- name: "binderLibTest_IPC_32",
- defaults: ["binder_test_defaults"],
- srcs: ["binderLibTest.cpp"],
- shared_libs: [
- "libbase",
- "libbinder",
- "liblog",
- "libutils",
- ],
- static_libs: [
- "libgmock",
- ],
- compile_multilib: "32",
- multilib: {
- lib32: {
- suffix: "",
- },
- },
- cflags: ["-DBINDER_IPC_32BIT=1"],
- test_suites: ["vts"],
- require_root: true,
-}
-
// unit test only, which can run on host and doesn't use /dev/binder
cc_test {
name: "binderUnitTest",
@@ -111,13 +67,39 @@
}
cc_test {
- name: "binderLibTest",
- defaults: ["binder_test_defaults"],
- product_variables: {
- binder32bit: {
- cflags: ["-DBINDER_IPC_32BIT=1"],
+ name: "binderRecordReplayTest",
+ srcs: ["binderRecordReplayTest.cpp"],
+ shared_libs: [
+ "libbinder",
+ "libcutils",
+ "libutils",
+ ],
+ static_libs: [
+ "binderRecordReplayTestIface-cpp",
+ "binderReadParcelIface-cpp",
+ ],
+ test_suites: ["general-tests"],
+ require_root: true,
+}
+
+aidl_interface {
+ name: "binderRecordReplayTestIface",
+ unstable: true,
+ srcs: [
+ "IBinderRecordReplayTest.aidl",
+ ],
+ imports: ["binderReadParcelIface"],
+ backend: {
+ java: {
+ enabled: true,
+ platform_apis: true,
},
},
+}
+
+cc_test {
+ name: "binderLibTest",
+ defaults: ["binder_test_defaults"],
srcs: ["binderLibTest.cpp"],
shared_libs: [
@@ -138,6 +120,7 @@
aidl_interface {
name: "binderRpcTestIface",
+ vendor_available: true,
host_supported: true,
unstable: true,
srcs: [
@@ -159,6 +142,7 @@
cc_library_static {
name: "libbinder_tls_test_utils",
host_supported: true,
+ vendor_available: true,
target: {
darwin: {
enabled: false,
@@ -236,6 +220,13 @@
"binderRpcUniversalTests.cpp",
],
+ // This test uses a lot of resources and takes a long time. Due to
+ // design of several tests, it is also very sensitive to resource
+ // contention on the device. b/276820894
+ test_options: {
+ unit_test: false,
+ },
+
test_suites: ["general-tests"],
require_root: true,
@@ -441,6 +432,37 @@
}
cc_test {
+ name: "binderRpcToTrustyTest",
+ vendor: true,
+ host_supported: false,
+ defaults: [
+ "binderRpcTest_common_defaults",
+ "binderRpcTest_static_defaults",
+ ],
+
+ srcs: [
+ "binderRpcTest.cpp",
+ "binderRpcTestCommon.cpp",
+ "binderRpcUniversalTests.cpp",
+ ],
+
+ cflags: [
+ "-DBINDER_RPC_TO_TRUSTY_TEST",
+ ],
+
+ static_libs: [
+ // We want to link libbinder statically so we can push the binary
+ // to the device for testing independently of the library
+ "libbinder_rpc_no_kernel",
+ "libbinder_trusty",
+ "libtrusty",
+ ],
+
+ test_suites: ["device-tests"],
+ require_root: true,
+}
+
+cc_test {
name: "RpcTlsUtilsTest",
host_supported: true,
target: {
@@ -676,6 +698,7 @@
"liblog",
"libutils",
],
+ test_suites: ["general-tests"],
}
cc_test_host {
@@ -778,3 +801,15 @@
hotlists: ["4637097"],
},
}
+
+cc_defaults {
+ name: "fuzzer_disable_leaks",
+ fuzz_config: {
+ asan_options: [
+ "detect_leaks=0",
+ ],
+ hwasan_options: [
+ "detect_leaks=0",
+ ],
+ },
+}
diff --git a/libs/binder/tests/IBinderRecordReplayTest.aidl b/libs/binder/tests/IBinderRecordReplayTest.aidl
new file mode 100644
index 0000000..bd6b03c
--- /dev/null
+++ b/libs/binder/tests/IBinderRecordReplayTest.aidl
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+import parcelables.SingleDataParcelable;
+
+interface IBinderRecordReplayTest {
+ void setByte(byte input);
+ byte getByte();
+
+ void setChar(char input);
+ char getChar();
+
+ void setBoolean(boolean input);
+ boolean getBoolean();
+
+ void setInt(int input);
+ int getInt();
+
+ void setFloat(float input);
+ float getFloat();
+
+ void setLong(long input);
+ long getLong();
+
+ void setDouble(double input);
+ double getDouble();
+
+ void setString(String input);
+ String getString();
+
+ void setSingleDataParcelable(in SingleDataParcelable p);
+ SingleDataParcelable getSingleDataParcelable();
+
+ void setByteArray(in byte[] input);
+ byte[] getByteArray();
+
+ void setCharArray(in char[] input);
+ char[] getCharArray();
+
+ void setBooleanArray(in boolean[] input);
+ boolean[] getBooleanArray();
+
+ void setIntArray(in int[] input);
+ int[] getIntArray();
+
+ void setFloatArray(in float[] input);
+ float[] getFloatArray();
+
+ void setLongArray(in long[] input);
+ long[] getLongArray();
+
+ void setDoubleArray(in double[] input);
+ double[] getDoubleArray();
+
+ void setStringArray(in String[] input);
+ String[] getStringArray();
+
+ void setSingleDataParcelableArray(in SingleDataParcelable[] input);
+ SingleDataParcelable[] getSingleDataParcelableArray();
+}
diff --git a/libs/binder/tests/binderAbiHelper.h b/libs/binder/tests/binderAbiHelper.h
deleted file mode 100644
index 369b55d..0000000
--- a/libs/binder/tests/binderAbiHelper.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-#pragma once
-
-#include <stdlib.h>
-#include <iostream>
-
-#ifdef BINDER_IPC_32BIT
-static constexpr bool kBuild32Abi = true;
-#else
-static constexpr bool kBuild32Abi = false;
-#endif
-
-// TODO: remove when CONFIG_ANDROID_BINDER_IPC_32BIT is no longer supported
-static inline bool ReadKernelConfigIs32BitAbi() {
- // failure case implies we run with standard ABI
- return 0 == system("zcat /proc/config.gz | grep -E \"^CONFIG_ANDROID_BINDER_IPC_32BIT=y$\"");
-}
-
-static inline void ExitIfWrongAbi() {
- bool runtime32Abi = ReadKernelConfigIs32BitAbi();
-
- if (kBuild32Abi != runtime32Abi) {
- std::cout << "[==========] Running 1 test from 1 test suite." << std::endl;
- std::cout << "[----------] Global test environment set-up." << std::endl;
- std::cout << "[----------] 1 tests from BinderLibTest" << std::endl;
- std::cout << "[ RUN ] BinderTest.AbortForWrongAbi" << std::endl;
- std::cout << "[ INFO ] test build abi 32: " << kBuild32Abi << " runtime abi 32: " << runtime32Abi << " so, skipping tests " << std::endl;
- std::cout << "[ OK ] BinderTest.AbortForWrongAbi (0 ms) " << std::endl;
- std::cout << "[----------] 1 tests from BinderTest (0 ms total)" << std::endl;
- std::cout << "" << std::endl;
- std::cout << "[----------] Global test environment tear-down" << std::endl;
- std::cout << "[==========] 1 test from 1 test suite ran. (0 ms total)" << std::endl;
- std::cout << "[ PASSED ] 1 tests." << std::endl;
- exit(0);
- }
-}
-
diff --git a/libs/binder/tests/binderDriverInterfaceTest.cpp b/libs/binder/tests/binderDriverInterfaceTest.cpp
index 8cc3054..cf23a46 100644
--- a/libs/binder/tests/binderDriverInterfaceTest.cpp
+++ b/libs/binder/tests/binderDriverInterfaceTest.cpp
@@ -25,8 +25,6 @@
#include <sys/mman.h>
#include <poll.h>
-#include "binderAbiHelper.h"
-
#define BINDER_DEV_NAME "/dev/binder"
testing::Environment* binder_env;
@@ -362,8 +360,7 @@
binderTestReadEmpty();
}
-int main(int argc, char **argv) {
- ExitIfWrongAbi();
+int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
binder_env = AddGlobalTestEnvironment(new BinderDriverInterfaceTestEnv());
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 8974ad7..abc423b 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -48,7 +48,6 @@
#include <sys/un.h>
#include "../binder_module.h"
-#include "binderAbiHelper.h"
#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
@@ -2022,9 +2021,7 @@
return 1; /* joinThreadPool should not return */
}
-int main(int argc, char **argv) {
- ExitIfWrongAbi();
-
+int main(int argc, char** argv) {
if (argc == 4 && !strcmp(argv[1], "--servername")) {
binderservername = argv[2];
} else {
diff --git a/libs/binder/tests/binderRecordReplayTest.cpp b/libs/binder/tests/binderRecordReplayTest.cpp
new file mode 100644
index 0000000..17d5c8a
--- /dev/null
+++ b/libs/binder/tests/binderRecordReplayTest.cpp
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2023 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 <BnBinderRecordReplayTest.h>
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+#include <binder/Binder.h>
+#include <binder/BpBinder.h>
+#include <binder/IBinder.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/RecordedTransaction.h>
+#include <gtest/gtest.h>
+
+#include <sys/prctl.h>
+
+#include "parcelables/SingleDataParcelable.h"
+
+using namespace android;
+using android::binder::Status;
+using android::binder::debug::RecordedTransaction;
+using parcelables::SingleDataParcelable;
+
+const String16 kServerName = String16("binderRecordReplay");
+
+#define GENERATE_GETTER_SETTER_PRIMITIVE(name, T) \
+ Status set##name(T input) { \
+ m##name = input; \
+ return Status::ok(); \
+ } \
+ \
+ Status get##name(T* output) { \
+ *output = m##name; \
+ return Status::ok(); \
+ } \
+ T m##name
+
+#define GENERATE_GETTER_SETTER(name, T) \
+ Status set##name(const T& input) { \
+ m##name = input; \
+ return Status::ok(); \
+ } \
+ \
+ Status get##name(T* output) { \
+ *output = m##name; \
+ return Status::ok(); \
+ } \
+ T m##name
+
+class MyRecordReplay : public BnBinderRecordReplayTest {
+public:
+ GENERATE_GETTER_SETTER_PRIMITIVE(Boolean, bool);
+ GENERATE_GETTER_SETTER_PRIMITIVE(Byte, int8_t);
+ GENERATE_GETTER_SETTER_PRIMITIVE(Int, int);
+ GENERATE_GETTER_SETTER_PRIMITIVE(Char, char16_t);
+ GENERATE_GETTER_SETTER_PRIMITIVE(Long, int64_t);
+ GENERATE_GETTER_SETTER_PRIMITIVE(Float, float);
+ GENERATE_GETTER_SETTER_PRIMITIVE(Double, double);
+
+ GENERATE_GETTER_SETTER(String, String16);
+ GENERATE_GETTER_SETTER(SingleDataParcelable, SingleDataParcelable);
+
+ GENERATE_GETTER_SETTER(BooleanArray, std::vector<bool>);
+ GENERATE_GETTER_SETTER(ByteArray, std::vector<uint8_t>);
+ GENERATE_GETTER_SETTER(IntArray, std::vector<int>);
+ GENERATE_GETTER_SETTER(CharArray, std::vector<char16_t>);
+ GENERATE_GETTER_SETTER(LongArray, std::vector<int64_t>);
+ GENERATE_GETTER_SETTER(FloatArray, std::vector<float>);
+ GENERATE_GETTER_SETTER(DoubleArray, std::vector<double>);
+ GENERATE_GETTER_SETTER(StringArray, std::vector<::android::String16>);
+ GENERATE_GETTER_SETTER(SingleDataParcelableArray, std::vector<SingleDataParcelable>);
+};
+
+class BinderRecordReplayTest : public ::testing::Test {
+public:
+ void SetUp() override {
+ // get the remote service
+ auto binder = defaultServiceManager()->getService(kServerName);
+ ASSERT_NE(nullptr, binder);
+ mInterface = interface_cast<IBinderRecordReplayTest>(binder);
+ mBpBinder = binder->remoteBinder();
+ ASSERT_NE(nullptr, mBpBinder);
+ }
+
+ template <typename T, typename U>
+ void recordReplay(Status (IBinderRecordReplayTest::*set)(T), U recordedValue,
+ Status (IBinderRecordReplayTest::*get)(U*), U changedValue) {
+ base::unique_fd fd(open("/data/local/tmp/binderRecordReplayTest.rec",
+ O_RDWR | O_CREAT | O_CLOEXEC, 0666));
+ ASSERT_TRUE(fd.ok());
+
+ // record a transaction
+ mBpBinder->startRecordingBinder(fd);
+ auto status = (*mInterface.*set)(recordedValue);
+ EXPECT_TRUE(status.isOk());
+ mBpBinder->stopRecordingBinder();
+
+ // test transaction does the thing we expect it to do
+ U output;
+ status = (*mInterface.*get)(&output);
+ EXPECT_TRUE(status.isOk());
+ EXPECT_EQ(output, recordedValue);
+
+ // write over the existing state
+ status = (*mInterface.*set)(changedValue);
+ EXPECT_TRUE(status.isOk());
+
+ status = (*mInterface.*get)(&output);
+ EXPECT_TRUE(status.isOk());
+
+ EXPECT_EQ(output, changedValue);
+
+ // replay transaction
+ ASSERT_EQ(0, lseek(fd.get(), 0, SEEK_SET));
+ std::optional<RecordedTransaction> transaction = RecordedTransaction::fromFile(fd);
+ ASSERT_NE(transaction, std::nullopt);
+
+ // TODO: move logic to replay RecordedTransaction into RecordedTransaction
+ Parcel data;
+ data.setData(transaction->getDataParcel().data(), transaction->getDataParcel().dataSize());
+ auto result =
+ mBpBinder->transact(transaction->getCode(), data, nullptr, transaction->getFlags());
+
+ // make sure recording does the thing we expect it to do
+ EXPECT_EQ(OK, result);
+
+ status = (*mInterface.*get)(&output);
+ EXPECT_TRUE(status.isOk());
+ EXPECT_EQ(output, recordedValue);
+ }
+
+private:
+ sp<BpBinder> mBpBinder;
+ sp<IBinderRecordReplayTest> mInterface;
+};
+
+TEST_F(BinderRecordReplayTest, ReplayByte) {
+ recordReplay(&IBinderRecordReplayTest::setByte, int8_t{122}, &IBinderRecordReplayTest::getByte,
+ int8_t{90});
+}
+
+TEST_F(BinderRecordReplayTest, ReplayBoolean) {
+ recordReplay(&IBinderRecordReplayTest::setBoolean, true, &IBinderRecordReplayTest::getBoolean,
+ false);
+}
+
+TEST_F(BinderRecordReplayTest, ReplayChar) {
+ recordReplay(&IBinderRecordReplayTest::setChar, char16_t{'G'},
+ &IBinderRecordReplayTest::getChar, char16_t{'K'});
+}
+
+TEST_F(BinderRecordReplayTest, ReplayInt) {
+ recordReplay(&IBinderRecordReplayTest::setInt, 3, &IBinderRecordReplayTest::getInt, 5);
+}
+
+TEST_F(BinderRecordReplayTest, ReplayFloat) {
+ recordReplay(&IBinderRecordReplayTest::setFloat, 1.1f, &IBinderRecordReplayTest::getFloat,
+ 22.0f);
+}
+
+TEST_F(BinderRecordReplayTest, ReplayLong) {
+ recordReplay(&IBinderRecordReplayTest::setLong, int64_t{1LL << 55},
+ &IBinderRecordReplayTest::getLong, int64_t{1LL << 12});
+}
+
+TEST_F(BinderRecordReplayTest, ReplayDouble) {
+ recordReplay(&IBinderRecordReplayTest::setDouble, 0.00, &IBinderRecordReplayTest::getDouble,
+ 1.11);
+}
+
+TEST_F(BinderRecordReplayTest, ReplayString) {
+ const ::android::String16& input1 = String16("This is saved string");
+ const ::android::String16& input2 = String16("This is changed string");
+ recordReplay(&IBinderRecordReplayTest::setString, input1, &IBinderRecordReplayTest::getString,
+ input2);
+}
+
+TEST_F(BinderRecordReplayTest, ReplaySingleDataParcelable) {
+ SingleDataParcelable saved, changed;
+ saved.data = 3;
+ changed.data = 5;
+ recordReplay(&IBinderRecordReplayTest::setSingleDataParcelable, saved,
+ &IBinderRecordReplayTest::getSingleDataParcelable, changed);
+}
+
+TEST_F(BinderRecordReplayTest, ReplayByteArray) {
+ std::vector<uint8_t> savedArray = {uint8_t{255}, uint8_t{0}, uint8_t{127}};
+ std::vector<uint8_t> changedArray = {uint8_t{2}, uint8_t{7}, uint8_t{117}};
+ recordReplay(&IBinderRecordReplayTest::setByteArray, savedArray,
+ &IBinderRecordReplayTest::getByteArray, changedArray);
+}
+
+TEST_F(BinderRecordReplayTest, ReplayBooleanArray) {
+ std::vector<bool> savedArray = {true, false, true};
+ std::vector<bool> changedArray = {false, true, false};
+ recordReplay(&IBinderRecordReplayTest::setBooleanArray, savedArray,
+ &IBinderRecordReplayTest::getBooleanArray, changedArray);
+}
+
+TEST_F(BinderRecordReplayTest, ReplayCharArray) {
+ std::vector<char16_t> savedArray = {char16_t{'G'}, char16_t{'L'}, char16_t{'K'}, char16_t{'T'}};
+ std::vector<char16_t> changedArray = {char16_t{'X'}, char16_t{'Y'}, char16_t{'Z'}};
+ recordReplay(&IBinderRecordReplayTest::setCharArray, savedArray,
+ &IBinderRecordReplayTest::getCharArray, changedArray);
+}
+
+TEST_F(BinderRecordReplayTest, ReplayIntArray) {
+ std::vector<int> savedArray = {12, 45, 178};
+ std::vector<int> changedArray = {32, 14, 78, 1899};
+ recordReplay(&IBinderRecordReplayTest::setIntArray, savedArray,
+ &IBinderRecordReplayTest::getIntArray, changedArray);
+}
+
+TEST_F(BinderRecordReplayTest, ReplayFloatArray) {
+ std::vector<float> savedArray = {12.14f, 45.56f, 123.178f};
+ std::vector<float> changedArray = {0.00f, 14.0f, 718.1f, 1899.122f, 3268.123f};
+ recordReplay(&IBinderRecordReplayTest::setFloatArray, savedArray,
+ &IBinderRecordReplayTest::getFloatArray, changedArray);
+}
+
+TEST_F(BinderRecordReplayTest, ReplayLongArray) {
+ std::vector<int64_t> savedArray = {int64_t{1LL << 11}, int64_t{1LL << 55}, int64_t{1LL << 45}};
+ std::vector<int64_t> changedArray = {int64_t{1LL << 1}, int64_t{1LL << 21}, int64_t{1LL << 33},
+ int64_t{1LL << 62}};
+ recordReplay(&IBinderRecordReplayTest::setLongArray, savedArray,
+ &IBinderRecordReplayTest::getLongArray, changedArray);
+}
+
+TEST_F(BinderRecordReplayTest, ReplayDoubleArray) {
+ std::vector<double> savedArray = {12.1412313, 45.561232, 123.1781111};
+ std::vector<double> changedArray = {0.00111, 14.32130, 712312318.19, 1899212.122,
+ 322168.122123};
+ recordReplay(&IBinderRecordReplayTest::setDoubleArray, savedArray,
+ &IBinderRecordReplayTest::getDoubleArray, changedArray);
+}
+
+TEST_F(BinderRecordReplayTest, ReplayStringArray) {
+ std::vector<String16> savedArray = {String16("This is saved value"), String16(),
+ String16("\0\0", 2), String16("\xF3\x01\xAC\xAD\x21\xAF")};
+
+ std::vector<String16> changedArray = {String16("This is changed value"),
+ String16("\xF0\x90\x90\xB7\xE2\x82\xAC")};
+ recordReplay(&IBinderRecordReplayTest::setStringArray, savedArray,
+ &IBinderRecordReplayTest::getStringArray, changedArray);
+}
+
+TEST_F(BinderRecordReplayTest, ReplaySingleDataParcelableArray) {
+ SingleDataParcelable s1, s2, s3, s4, s5;
+ s1.data = 5213;
+ s2.data = 1512;
+ s3.data = 4233;
+ s4.data = 123124;
+ s5.data = 0;
+ std::vector<SingleDataParcelable> saved = {s1, s2, s3};
+ std::vector<SingleDataParcelable> changed = {s4, s5};
+
+ recordReplay(&IBinderRecordReplayTest::setSingleDataParcelableArray, saved,
+ &IBinderRecordReplayTest::getSingleDataParcelableArray, changed);
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+
+ if (fork() == 0) {
+ prctl(PR_SET_PDEATHSIG, SIGHUP);
+
+ auto server = sp<MyRecordReplay>::make();
+ android::defaultServiceManager()->addService(kServerName, server.get());
+
+ IPCThreadState::self()->joinThreadPool(true);
+ exit(1); // should not reach
+ }
+
+ // not racey, but getService sleeps for 1s
+ usleep(100000);
+
+ return RUN_ALL_TESTS();
+}
diff --git a/libs/binder/tests/binderRpcBenchmark.cpp b/libs/binder/tests/binderRpcBenchmark.cpp
index 5939273..9c96c41 100644
--- a/libs/binder/tests/binderRpcBenchmark.cpp
+++ b/libs/binder/tests/binderRpcBenchmark.cpp
@@ -129,12 +129,33 @@
}
}
+static void SetLabel(benchmark::State& state) {
+ Transport transport = static_cast<Transport>(state.range(0));
+ switch (transport) {
+#ifdef __BIONIC__
+ case KERNEL:
+ state.SetLabel("kernel");
+ break;
+#endif
+ case RPC:
+ state.SetLabel("rpc");
+ break;
+ case RPC_TLS:
+ state.SetLabel("rpc_tls");
+ break;
+ default:
+ LOG(FATAL) << "Unknown transport value: " << transport;
+ }
+}
+
void BM_pingTransaction(benchmark::State& state) {
sp<IBinder> binder = getBinderForOptions(state);
while (state.KeepRunning()) {
CHECK_EQ(OK, binder->pingBinder());
}
+
+ SetLabel(state);
}
BENCHMARK(BM_pingTransaction)->ArgsProduct({kTransportList});
@@ -164,6 +185,8 @@
Status ret = iface->repeatString(str, &out);
CHECK(ret.isOk()) << ret;
}
+
+ SetLabel(state);
}
BENCHMARK(BM_repeatTwoPageString)->ArgsProduct({kTransportList});
@@ -182,6 +205,8 @@
Status ret = iface->repeatBytes(bytes, &out);
CHECK(ret.isOk()) << ret;
}
+
+ SetLabel(state);
}
BENCHMARK(BM_throughputForTransportAndBytes)
->ArgsProduct({kTransportList,
@@ -201,6 +226,8 @@
Status ret = iface->repeatBinder(binder, &out);
CHECK(ret.isOk()) << ret;
}
+
+ SetLabel(state);
}
BENCHMARK(BM_repeatBinder)->ArgsProduct({kTransportList});
@@ -228,11 +255,6 @@
::benchmark::Initialize(&argc, argv);
if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1;
- std::cerr << "Tests suffixes:" << std::endl;
- std::cerr << "\t.../" << Transport::KERNEL << " is KERNEL" << std::endl;
- std::cerr << "\t.../" << Transport::RPC << " is RPC" << std::endl;
- std::cerr << "\t.../" << Transport::RPC_TLS << " is RPC with TLS" << std::endl;
-
#ifdef __BIONIC__
if (0 == fork()) {
prctl(PR_SET_PDEATHSIG, SIGHUP); // racey, okay
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index d563cfc..f88cfd6 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -28,10 +28,10 @@
#include <sys/prctl.h>
#include <sys/socket.h>
-#ifdef __ANDROID_VENDOR__
+#ifdef BINDER_RPC_TO_TRUSTY_TEST
#include <binder/RpcTransportTipcAndroid.h>
#include <trusty/tipc.h>
-#endif // __ANDROID_VENDOR__
+#endif // BINDER_RPC_TO_TRUSTY_TEST
#include "binderRpcTestCommon.h"
#include "binderRpcTestFixture.h"
@@ -50,7 +50,7 @@
constexpr bool kEnableSharedLibs = true;
#endif
-#ifdef __ANDROID_VENDOR__
+#ifdef BINDER_RPC_TO_TRUSTY_TEST
constexpr char kTrustyIpcDevice[] = "/dev/trusty-ipc-dev0";
#endif
@@ -214,6 +214,7 @@
return serverFd;
}
+#ifndef BINDER_RPC_TO_TRUSTY_TEST
static base::unique_fd connectToUnixBootstrap(const RpcTransportFd& transportFd) {
base::unique_fd sockClient, sockServer;
if (!base::Socketpair(SOCK_STREAM, &sockClient, &sockServer)) {
@@ -232,6 +233,7 @@
}
return std::move(sockClient);
}
+#endif // BINDER_RPC_TO_TRUSTY_TEST
std::unique_ptr<RpcTransportCtxFactory> BinderRpc::newFactory(RpcSecurity rpcSecurity) {
return newTlsFactory(rpcSecurity);
@@ -308,7 +310,7 @@
for (size_t i = 0; i < options.numSessions; i++) {
std::unique_ptr<RpcTransportCtxFactory> factory;
if (socketType == SocketType::TIPC) {
-#ifdef __ANDROID_VENDOR__
+#ifdef BINDER_RPC_TO_TRUSTY_TEST
factory = RpcTransportCtxFactoryTipcAndroid::make();
#else
LOG_ALWAYS_FATAL("TIPC socket type only supported on vendor");
@@ -378,11 +380,18 @@
break;
case SocketType::TIPC:
status = session->setupPreconnectedClient({}, [=]() {
-#ifdef __ANDROID_VENDOR__
+#ifdef BINDER_RPC_TO_TRUSTY_TEST
auto port = trustyIpcPort(serverVersion);
- int tipcFd = tipc_connect(kTrustyIpcDevice, port.c_str());
- return tipcFd >= 0 ? android::base::unique_fd(tipcFd)
- : android::base::unique_fd();
+ for (size_t i = 0; i < 5; i++) {
+ // Try to connect several times,
+ // in case the service is slow to start
+ int tipcFd = tipc_connect(kTrustyIpcDevice, port.c_str());
+ if (tipcFd >= 0) {
+ return android::base::unique_fd(tipcFd);
+ }
+ usleep(50000);
+ }
+ return android::base::unique_fd();
#else
LOG_ALWAYS_FATAL("Tried to connect to Trusty outside of vendor");
return android::base::unique_fd();
@@ -452,8 +461,11 @@
EXPECT_GE(epochMsAfter, epochMsBefore + 2 * sleepMs);
- // Potential flake, but make sure calls are handled in parallel.
- EXPECT_LE(epochMsAfter, epochMsBefore + 3 * sleepMs);
+ // Potential flake, but make sure calls are handled in parallel. Due
+ // to past flakes, this only checks that the amount of time taken has
+ // some parallelism. Other tests such as ThreadPoolGreaterThanEqualRequested
+ // check this more exactly.
+ EXPECT_LE(epochMsAfter, epochMsBefore + (numCalls - 1) * sleepMs);
}
TEST_P(BinderRpc, ThreadPoolOverSaturated) {
@@ -464,7 +476,9 @@
constexpr size_t kNumThreads = 10;
constexpr size_t kNumCalls = kNumThreads + 3;
auto proc = createRpcTestSocketServerProcess({.numThreads = kNumThreads});
- testThreadPoolOverSaturated(proc.rootIface, kNumCalls, 250 /*ms*/);
+
+ // b/272429574 - below 500ms, the test fails
+ testThreadPoolOverSaturated(proc.rootIface, kNumCalls, 500 /*ms*/);
}
TEST_P(BinderRpc, ThreadPoolLimitOutgoing) {
@@ -477,7 +491,9 @@
constexpr size_t kNumCalls = kNumOutgoingConnections + 3;
auto proc = createRpcTestSocketServerProcess(
{.numThreads = kNumThreads, .numOutgoingConnections = kNumOutgoingConnections});
- testThreadPoolOverSaturated(proc.rootIface, kNumCalls, 250 /*ms*/);
+
+ // b/272429574 - below 500ms, the test fails
+ testThreadPoolOverSaturated(proc.rootIface, kNumCalls, 500 /*ms*/);
}
TEST_P(BinderRpc, ThreadingStressTest) {
@@ -674,6 +690,8 @@
}
EXPECT_EQ(nullptr, session.promote());
+
+ sleep(1); // give time for remote session to shutdown
}
TEST_P(BinderRpc, SingleDeathRecipient) {
@@ -1098,12 +1116,26 @@
ASSERT_EQ(beforeFds, countFds()) << (system("ls -l /proc/self/fd/"), "fd leak?");
}
+#ifdef BINDER_RPC_TO_TRUSTY_TEST
+INSTANTIATE_TEST_CASE_P(Trusty, BinderRpc,
+ ::testing::Combine(::testing::Values(SocketType::TIPC),
+ ::testing::Values(RpcSecurity::RAW),
+ ::testing::ValuesIn(testVersions()),
+ ::testing::ValuesIn(testVersions()),
+ ::testing::Values(true), ::testing::Values(true)),
+ BinderRpc::PrintParamInfo);
+#else // BINDER_RPC_TO_TRUSTY_TEST
static bool testSupportVsockLoopback() {
// We don't need to enable TLS to know if vsock is supported.
unsigned int vsockPort = allocateVsockPort();
android::base::unique_fd serverFd(
TEMP_FAILURE_RETRY(socket(AF_VSOCK, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)));
+
+ if (errno == EAFNOSUPPORT) {
+ return false;
+ }
+
LOG_ALWAYS_FATAL_IF(serverFd == -1, "Could not create socket: %s", strerror(errno));
sockaddr_vm serverAddr{
@@ -1202,21 +1234,6 @@
return ret;
}
-static std::vector<SocketType> testTipcSocketTypes() {
-#ifdef __ANDROID_VENDOR__
- auto port = trustyIpcPort(RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL);
- int tipcFd = tipc_connect(kTrustyIpcDevice, port.c_str());
- if (tipcFd >= 0) {
- close(tipcFd);
- return {SocketType::TIPC};
- }
-#endif // __ANDROID_VENDOR__
-
- // TIPC is not supported on this device, most likely
- // because /dev/trusty-ipc-dev0 is missing
- return {};
-}
-
INSTANTIATE_TEST_CASE_P(PerSocket, BinderRpc,
::testing::Combine(::testing::ValuesIn(testSocketTypes()),
::testing::ValuesIn(RpcSecurityValues()),
@@ -1226,14 +1243,6 @@
::testing::Values(false, true)),
BinderRpc::PrintParamInfo);
-INSTANTIATE_TEST_CASE_P(Trusty, BinderRpc,
- ::testing::Combine(::testing::ValuesIn(testTipcSocketTypes()),
- ::testing::Values(RpcSecurity::RAW),
- ::testing::ValuesIn(testVersions()),
- ::testing::ValuesIn(testVersions()),
- ::testing::Values(true), ::testing::Values(true)),
- BinderRpc::PrintParamInfo);
-
class BinderRpcServerRootObject
: public ::testing::TestWithParam<std::tuple<bool, bool, RpcSecurity>> {};
@@ -1349,7 +1358,7 @@
base::unique_fd sink(TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR)));
int sinkFd = sink.get();
auto server = RpcServer::make(newTlsFactory(std::get<0>(GetParam())));
- server->setProtocolVersion(std::get<1>(GetParam()));
+ ASSERT_TRUE(server->setProtocolVersion(std::get<1>(GetParam())));
ASSERT_FALSE(server->hasServer());
ASSERT_EQ(OK, server->setupExternalServer(std::move(sink)));
ASSERT_TRUE(server->hasServer());
@@ -1365,7 +1374,7 @@
auto addr = allocateSocketAddress();
auto server = RpcServer::make(newTlsFactory(std::get<0>(GetParam())));
- server->setProtocolVersion(std::get<1>(GetParam()));
+ ASSERT_TRUE(server->setProtocolVersion(std::get<1>(GetParam())));
ASSERT_EQ(OK, server->setupUnixDomainServer(addr.c_str()));
auto joinEnds = std::make_shared<OneOffSignal>();
@@ -1414,7 +1423,9 @@
std::unique_ptr<RpcAuth> auth = std::make_unique<RpcAuthSelfSigned>()) {
auto [socketType, rpcSecurity, certificateFormat, serverVersion] = param;
auto rpcServer = RpcServer::make(newTlsFactory(rpcSecurity));
- rpcServer->setProtocolVersion(serverVersion);
+ if (!rpcServer->setProtocolVersion(serverVersion)) {
+ return AssertionFailure() << "Invalid protocol version: " << serverVersion;
+ }
switch (socketType) {
case SocketType::PRECONNECTED: {
return AssertionFailure() << "Not supported by this test";
@@ -2002,6 +2013,7 @@
testing::Values(RpcKeyFormat::PEM, RpcKeyFormat::DER),
testing::ValuesIn(testVersions())),
RpcTransportTlsKeyTest::PrintParamInfo);
+#endif // BINDER_RPC_TO_TRUSTY_TEST
} // namespace android
diff --git a/libs/binder/tests/binderRpcTestService.cpp b/libs/binder/tests/binderRpcTestService.cpp
index a9736d5..cb09a7f 100644
--- a/libs/binder/tests/binderRpcTestService.cpp
+++ b/libs/binder/tests/binderRpcTestService.cpp
@@ -118,7 +118,7 @@
auto certVerifier = std::make_shared<RpcCertificateVerifierSimple>();
sp<RpcServer> server = RpcServer::make(newTlsFactory(rpcSecurity, certVerifier));
- server->setProtocolVersion(serverConfig.serverVersion);
+ CHECK(server->setProtocolVersion(serverConfig.serverVersion));
server->setMaxThreads(serverConfig.numThreads);
server->setSupportedFileDescriptorTransportModes(serverSupportedFileDescriptorTransportModes);
@@ -164,7 +164,12 @@
}
}
- server->setPerSessionRootObject([&](const void* addrPtr, size_t len) {
+ server->setPerSessionRootObject([&](wp<RpcSession> session, const void* addrPtr, size_t len) {
+ {
+ sp<RpcSession> spSession = session.promote();
+ CHECK_NE(nullptr, spSession.get());
+ }
+
// UNIX sockets with abstract addresses return
// sizeof(sa_family_t)==2 in addrlen
CHECK_GE(len, sizeof(sa_family_t));
diff --git a/libs/binder/tests/binderRpcTestServiceTrusty.cpp b/libs/binder/tests/binderRpcTestServiceTrusty.cpp
index 8557389..cb632e9 100644
--- a/libs/binder/tests/binderRpcTestServiceTrusty.cpp
+++ b/libs/binder/tests/binderRpcTestServiceTrusty.cpp
@@ -90,15 +90,18 @@
auto server = std::move(*serverOrErr);
serverInfo.server = server;
- serverInfo.server->setProtocolVersion(serverVersion);
- serverInfo.server->setPerSessionRootObject([=](const void* /*addrPtr*/, size_t /*len*/) {
- auto service = sp<MyBinderRpcTestTrusty>::make();
- // Assign a unique connection identifier to service->port so
- // getClientPort returns a unique value per connection
- service->port = ++gConnectionCounter;
- service->server = server;
- return service;
- });
+ if (!serverInfo.server->setProtocolVersion(serverVersion)) {
+ return EXIT_FAILURE;
+ }
+ serverInfo.server->setPerSessionRootObject(
+ [=](wp<RpcSession> /*session*/, const void* /*addrPtr*/, size_t /*len*/) {
+ auto service = sp<MyBinderRpcTestTrusty>::make();
+ // Assign a unique connection identifier to service->port so
+ // getClientPort returns a unique value per connection
+ service->port = ++gConnectionCounter;
+ service->server = server;
+ return service;
+ });
servers.push_back(std::move(serverInfo));
}
diff --git a/libs/binder/tests/binderRpcWireProtocolTest.cpp b/libs/binder/tests/binderRpcWireProtocolTest.cpp
index 3dab2c7..642cea4 100644
--- a/libs/binder/tests/binderRpcWireProtocolTest.cpp
+++ b/libs/binder/tests/binderRpcWireProtocolTest.cpp
@@ -237,14 +237,25 @@
checkRepr(kCurrentRepr, 0);
}
+TEST(RpcWire, V1) {
+ checkRepr(kCurrentRepr, 1);
+}
+
TEST(RpcWire, CurrentVersion) {
checkRepr(kCurrentRepr, RPC_WIRE_PROTOCOL_VERSION);
}
-static_assert(RPC_WIRE_PROTOCOL_VERSION == RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL,
+static_assert(RPC_WIRE_PROTOCOL_VERSION == 1,
"If the binder wire protocol is updated, this test should test additional versions. "
"The binder wire protocol should only be updated on upstream AOSP.");
+TEST(RpcWire, NextIsPlusOneReminder) {
+ if (RPC_WIRE_PROTOCOL_VERSION != RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL) {
+ EXPECT_EQ(RPC_WIRE_PROTOCOL_VERSION + 1, RPC_WIRE_PROTOCOL_VERSION_NEXT)
+ << "Make sure to note what the next version should be.";
+ }
+}
+
TEST(RpcWire, ReleaseBranchHasFrozenRpcWireProtocol) {
if (RPC_WIRE_PROTOCOL_VERSION == RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL) {
EXPECT_FALSE(base::GetProperty("ro.build.version.codename", "") == "REL")
diff --git a/libs/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp
index c857d62..5e8a32a 100644
--- a/libs/binder/tests/binderSafeInterfaceTest.cpp
+++ b/libs/binder/tests/binderSafeInterfaceTest.cpp
@@ -35,6 +35,7 @@
#include <optional>
+#include <inttypes.h>
#include <sys/eventfd.h>
#include <sys/prctl.h>
@@ -686,10 +687,12 @@
// Determine the maximum number of fds this process can have open
struct rlimit limit {};
ASSERT_EQ(0, getrlimit(RLIMIT_NOFILE, &limit));
- uint32_t maxFds = static_cast<uint32_t>(limit.rlim_cur);
+ uint64_t maxFds = limit.rlim_cur;
+
+ ALOG(LOG_INFO, "SafeInterfaceTest", "%s max FDs: %" PRIu64, __PRETTY_FUNCTION__, maxFds);
// Perform this test enough times to rule out fd leaks
- for (uint32_t iter = 0; iter < (2 * maxFds); ++iter) {
+ for (uint32_t iter = 0; iter < (maxFds + 100); ++iter) {
native_handle* handle = native_handle_create(1 /*numFds*/, 1 /*numInts*/);
ASSERT_NE(nullptr, handle);
handle->data[0] = dup(eventFd.get());
diff --git a/libs/binder/tests/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp
index 768fbe1..46d387c 100644
--- a/libs/binder/tests/parcel_fuzzer/binder.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder.cpp
@@ -367,13 +367,15 @@
FUZZ_LOG() << "about to call readFromParcel() with status for SingleDataParcelable";
parcelables::SingleDataParcelable singleDataParcelable;
status_t status = singleDataParcelable.readFromParcel(&p);
- FUZZ_LOG() <<" status: " << status;
+ FUZZ_LOG() << " status: " << status;
},
[] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) {
FUZZ_LOG() << "about to call readFromParcel() with status for GenericDataParcelable";
parcelables::GenericDataParcelable genericDataParcelable;
status_t status = genericDataParcelable.readFromParcel(&p);
- FUZZ_LOG() <<" status: " << status;
+ FUZZ_LOG() << " status: " << status;
+ std::string toString = genericDataParcelable.toString();
+ FUZZ_LOG() << " toString() result: " << toString;
},
};
// clang-format on
diff --git a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
index 08eb27a..3a1471e 100644
--- a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
@@ -198,6 +198,8 @@
aidl::parcelables::GenericDataParcelable genericDataParcelable;
binder_status_t status = genericDataParcelable.readFromParcel(p.aParcel());
FUZZ_LOG() << "status: " << status;
+ std::string toString = genericDataParcelable.toString();
+ FUZZ_LOG() << "toString() result: " << toString;
},
[](const NdkParcelAdapter& p, FuzzedDataProvider& provider) {
FUZZ_LOG() << "about to marshal AParcel";
diff --git a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_driver.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_driver.h
index a9a6197..cb37cfa 100644
--- a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_driver.h
+++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_driver.h
@@ -19,7 +19,17 @@
#include <binder/IBinder.h>
#include <fuzzer/FuzzedDataProvider.h>
+#include <vector>
+
namespace android {
+
+/**
+ * See fuzzService, but fuzzes multiple services at the same time.
+ *
+ * Consumes providers.
+ */
+void fuzzService(const std::vector<sp<IBinder>>& binders, FuzzedDataProvider&& provider);
+
/**
* Based on the random data in provider, construct an arbitrary number of
* Parcel objects and send them to the service in serial.
@@ -34,4 +44,5 @@
* }
*/
void fuzzService(const sp<IBinder>& binder, FuzzedDataProvider&& provider);
+
} // namespace android
diff --git a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_ndk_driver.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_ndk_driver.h
index f2b7823..d8bf87a 100644
--- a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_ndk_driver.h
+++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_ndk_driver.h
@@ -16,10 +16,21 @@
#pragma once
+#include <android/binder_auto_utils.h>
#include <android/binder_parcel.h>
#include <fuzzer/FuzzedDataProvider.h>
+#include <vector>
+
namespace android {
+
+/**
+ * See fuzzService, but fuzzes multiple services at the same time.
+ *
+ * Consumes providers.
+ */
+void fuzzService(const std::vector<ndk::SpAIBinder>& binders, FuzzedDataProvider&& provider);
+
/**
* Based on the random data in provider, construct an arbitrary number of
* Parcel objects and send them to the service in serial.
diff --git a/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp b/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp
index 8bef33f..0b3902d 100644
--- a/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp
+++ b/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp
@@ -24,60 +24,92 @@
namespace android {
void fuzzService(const sp<IBinder>& binder, FuzzedDataProvider&& provider) {
- sp<IBinder> target;
+ fuzzService(std::vector<sp<IBinder>>{binder}, std::move(provider));
+}
+void fuzzService(const std::vector<sp<IBinder>>& binders, FuzzedDataProvider&& provider) {
RandomParcelOptions options{
- .extraBinders = {binder},
+ .extraBinders = binders,
.extraFds = {},
};
+ // Always take so that a perturbation of just the one ConsumeBool byte will always
+ // take the same path, but with a different UID. Without this, the fuzzer needs to
+ // guess both the change in value and the shift at the same time.
+ int64_t maybeSetUid = provider.ConsumeIntegral<int64_t>();
if (provider.ConsumeBool()) {
// set calling uid
- IPCThreadState::self()->restoreCallingIdentity(provider.ConsumeIntegral<int64_t>());
+ IPCThreadState::self()->restoreCallingIdentity(maybeSetUid);
}
while (provider.remaining_bytes() > 0) {
- // Most of the AIDL services will have small set of transaction codes.
- uint32_t code = provider.ConsumeBool() ? provider.ConsumeIntegral<uint32_t>()
- : provider.ConsumeIntegralInRange<uint32_t>(0, 100);
- uint32_t flags = provider.ConsumeIntegral<uint32_t>();
- Parcel data;
- // for increased fuzz coverage
- data.setEnforceNoDataAvail(provider.ConsumeBool());
+ provider.PickValueInArray<std::function<void()>>({
+ [&]() {
+ // Most of the AIDL services will have small set of transaction codes.
+ uint32_t code = provider.ConsumeBool()
+ ? provider.ConsumeIntegral<uint32_t>()
+ : provider.ConsumeIntegralInRange<uint32_t>(0, 100);
+ uint32_t flags = provider.ConsumeIntegral<uint32_t>();
+ Parcel data;
+ // for increased fuzz coverage
+ data.setEnforceNoDataAvail(provider.ConsumeBool());
- sp<IBinder> target = options.extraBinders.at(
- provider.ConsumeIntegralInRange<size_t>(0, options.extraBinders.size() - 1));
- options.writeHeader = [&target](Parcel* p, FuzzedDataProvider& provider) {
- // most code will be behind checks that the head of the Parcel
- // is exactly this, so make it easier for fuzzers to reach this
- if (provider.ConsumeBool()) {
- p->writeInterfaceToken(target->getInterfaceDescriptor());
- }
- };
+ sp<IBinder> target = options.extraBinders.at(
+ provider.ConsumeIntegralInRange<size_t>(0,
+ options.extraBinders.size() -
+ 1));
+ options.writeHeader = [&target](Parcel* p, FuzzedDataProvider& provider) {
+ // most code will be behind checks that the head of the Parcel
+ // is exactly this, so make it easier for fuzzers to reach this
+ if (provider.ConsumeBool()) {
+ p->writeInterfaceToken(target->getInterfaceDescriptor());
+ }
+ };
- std::vector<uint8_t> subData = provider.ConsumeBytes<uint8_t>(
- provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes()));
- fillRandomParcel(&data, FuzzedDataProvider(subData.data(), subData.size()), &options);
+ std::vector<uint8_t> subData = provider.ConsumeBytes<uint8_t>(
+ provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes()));
+ fillRandomParcel(&data, FuzzedDataProvider(subData.data(), subData.size()),
+ &options);
- Parcel reply;
- // for increased fuzz coverage
- reply.setEnforceNoDataAvail(provider.ConsumeBool());
- (void)target->transact(code, data, &reply, flags);
+ Parcel reply;
+ // for increased fuzz coverage
+ reply.setEnforceNoDataAvail(provider.ConsumeBool());
+ (void)target->transact(code, data, &reply, flags);
- // feed back in binders and fds that are returned from the service, so that
- // we can fuzz those binders, and use the fds and binders to feed back into
- // the binders
- auto retBinders = reply.debugReadAllStrongBinders();
- options.extraBinders.insert(options.extraBinders.end(), retBinders.begin(),
- retBinders.end());
- auto retFds = reply.debugReadAllFileDescriptors();
- for (size_t i = 0; i < retFds.size(); i++) {
- options.extraFds.push_back(base::unique_fd(dup(retFds[i])));
- }
+ // feed back in binders and fds that are returned from the service, so that
+ // we can fuzz those binders, and use the fds and binders to feed back into
+ // the binders
+ auto retBinders = reply.debugReadAllStrongBinders();
+ options.extraBinders.insert(options.extraBinders.end(), retBinders.begin(),
+ retBinders.end());
+ auto retFds = reply.debugReadAllFileDescriptors();
+ for (size_t i = 0; i < retFds.size(); i++) {
+ options.extraFds.push_back(base::unique_fd(dup(retFds[i])));
+ }
+ },
+ [&]() {
+ if (options.extraFds.size() == 0) {
+ return;
+ }
+ uint32_t toDelete =
+ provider.ConsumeIntegralInRange<uint32_t>(0,
+ options.extraFds.size() - 1);
+ options.extraFds.erase(options.extraFds.begin() + toDelete);
+ },
+ [&]() {
+ if (options.extraBinders.size() <= 1) {
+ return;
+ }
+ uint32_t toDelete =
+ provider.ConsumeIntegralInRange<uint32_t>(0,
+ options.extraBinders.size() -
+ 1);
+ options.extraBinders.erase(options.extraBinders.begin() + toDelete);
+ },
+ })();
}
// invariants
-
auto ps = ProcessState::selfOrNull();
if (ps) {
CHECK_EQ(0, ps->getThreadPoolMaxTotalThreadCount())
diff --git a/libs/binder/tests/parcel_fuzzer/libbinder_ndk_driver.cpp b/libs/binder/tests/parcel_fuzzer/libbinder_ndk_driver.cpp
index a1fb701..0b0ca34 100644
--- a/libs/binder/tests/parcel_fuzzer/libbinder_ndk_driver.cpp
+++ b/libs/binder/tests/parcel_fuzzer/libbinder_ndk_driver.cpp
@@ -24,6 +24,15 @@
namespace android {
+void fuzzService(const std::vector<ndk::SpAIBinder>& binders, FuzzedDataProvider&& provider) {
+ std::vector<sp<IBinder>> cppBinders;
+ for (const auto& binder : binders) {
+ cppBinders.push_back(binder.get()->getBinder());
+ }
+
+ fuzzService(cppBinders, std::move(provider));
+}
+
void fuzzService(AIBinder* binder, FuzzedDataProvider&& provider) {
fuzzService(binder->getBinder(), std::move(provider));
}
diff --git a/libs/binder/tests/parcel_fuzzer/parcelables/GenericDataParcelable.aidl b/libs/binder/tests/parcel_fuzzer/parcelables/GenericDataParcelable.aidl
index f1079e9..dd08f72 100644
--- a/libs/binder/tests/parcel_fuzzer/parcelables/GenericDataParcelable.aidl
+++ b/libs/binder/tests/parcel_fuzzer/parcelables/GenericDataParcelable.aidl
@@ -16,10 +16,23 @@
package parcelables;
parcelable GenericDataParcelable {
+ enum JustSomeEnum {
+ SOME_ENUMERATOR,
+ ANOTHER_ENUMERATOR,
+ MAYBE_ONE_MORE_ENUMERATOR,
+ }
+
+ const int COOL_CONSTANT = 0x1234;
+
int data;
float majorVersion;
float minorVersion;
IBinder binder;
ParcelFileDescriptor fileDescriptor;
int[] array;
-}
\ No newline at end of file
+ String greatString;
+ @utf8InCpp
+ String greaterString;
+ @nullable String nullableString;
+ JustSomeEnum gretEnum = JustSomeEnum.ANOTHER_ENUMERATOR;
+}
diff --git a/libs/binder/tests/parcel_fuzzer/test_fuzzer/Android.bp b/libs/binder/tests/parcel_fuzzer/test_fuzzer/Android.bp
new file mode 100644
index 0000000..690c39a
--- /dev/null
+++ b/libs/binder/tests/parcel_fuzzer/test_fuzzer/Android.bp
@@ -0,0 +1,64 @@
+package {
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
+aidl_interface {
+ name: "testServiceIface",
+ host_supported: true,
+ unstable: true,
+ srcs: [
+ "ITestService.aidl",
+ ],
+ backend: {
+ java: {
+ enabled: true,
+ platform_apis: true,
+ },
+ rust: {
+ enabled: true,
+ },
+ },
+}
+
+// Adding this fuzzer to test the fuzzService functionality
+cc_fuzz {
+ name: "test_service_fuzzer_should_crash",
+ defaults: [
+ "service_fuzzer_defaults",
+ ],
+ static_libs: [
+ "liblog",
+ "testServiceIface-cpp",
+ ],
+ host_supported: true,
+ srcs: ["TestServiceFuzzer.cpp"],
+ fuzz_config: {
+ triage_assignee: "waghpawan@google.com",
+
+ // This fuzzer should be used only test fuzzService locally
+ fuzz_on_haiku_host: false,
+ fuzz_on_haiku_device: false,
+ },
+}
+
+sh_test_host {
+ name: "fuzz_service_test",
+ src: "run_fuzz_service_test.sh",
+ filename: "run_fuzz_service_test.sh",
+ test_config: "fuzz_service_test_config.xml",
+ data_bins: [
+ "test_service_fuzzer_should_crash",
+ ],
+ required: [
+ "test_service_fuzzer_should_crash",
+ ],
+ target: {
+ linux_bionic: {
+ enabled: false,
+ },
+ darwin: {
+ enabled: false,
+ },
+ },
+ test_suites: ["general-tests"],
+}
diff --git a/libs/binder/tests/parcel_fuzzer/test_fuzzer/ITestService.aidl b/libs/binder/tests/parcel_fuzzer/test_fuzzer/ITestService.aidl
new file mode 100644
index 0000000..3eadc02
--- /dev/null
+++ b/libs/binder/tests/parcel_fuzzer/test_fuzzer/ITestService.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+interface ITestService {
+
+ void setIntData(int input);
+
+ void setCharData(char input);
+
+ void setBooleanData(boolean input);
+}
\ No newline at end of file
diff --git a/libs/binder/tests/parcel_fuzzer/test_fuzzer/TestServiceFuzzer.cpp b/libs/binder/tests/parcel_fuzzer/test_fuzzer/TestServiceFuzzer.cpp
new file mode 100644
index 0000000..8907ea0
--- /dev/null
+++ b/libs/binder/tests/parcel_fuzzer/test_fuzzer/TestServiceFuzzer.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2023 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 <BnTestService.h>
+#include <fuzzbinder/libbinder_driver.h>
+
+#include <log/log.h>
+
+using android::fuzzService;
+using android::sp;
+using android::binder::Status;
+
+namespace android {
+// This service is to verify that fuzzService is functioning properly
+class TestService : public BnTestService {
+public:
+ Status setIntData(int /*input*/) {
+ LOG_ALWAYS_FATAL("Expected crash in setIntData");
+ return Status::ok();
+ }
+
+ Status setCharData(char16_t /*input*/) {
+ LOG_ALWAYS_FATAL("Expected crash in setCharData");
+ return Status::ok();
+ }
+
+ Status setBooleanData(bool /*input*/) {
+ LOG_ALWAYS_FATAL("Expected crash in setBooleanData");
+ return Status::ok();
+ }
+};
+} // namespace android
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ auto service = sp<android::TestService>::make();
+ fuzzService(service, FuzzedDataProvider(data, size));
+ return 0;
+}
diff --git a/libs/binder/tests/parcel_fuzzer/test_fuzzer/fuzz_service_test_config.xml b/libs/binder/tests/parcel_fuzzer/test_fuzzer/fuzz_service_test_config.xml
new file mode 100644
index 0000000..19eb33a
--- /dev/null
+++ b/libs/binder/tests/parcel_fuzzer/test_fuzzer/fuzz_service_test_config.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+<configuration description="Runs fuzzService test">
+ <option name="null-device" value="true" />
+ <test class="com.android.tradefed.testtype.binary.ExecutableHostTest" >
+ <option name="binary" value="run_fuzz_service_test.sh"/>
+ <option name="relative-path-execution" value="true" />
+ </test>
+</configuration>
diff --git a/libs/binder/tests/parcel_fuzzer/test_fuzzer/run_fuzz_service_test.sh b/libs/binder/tests/parcel_fuzzer/test_fuzzer/run_fuzz_service_test.sh
new file mode 100644
index 0000000..cec52fd
--- /dev/null
+++ b/libs/binder/tests/parcel_fuzzer/test_fuzzer/run_fuzz_service_test.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# Copyright (C) 2023 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.
+
+color_success=$'\E'"[0;32m"
+color_failed=$'\E'"[0;31m"
+color_reset=$'\E'"[00m"
+
+FUZZER_NAME=test_service_fuzzer_should_crash
+FUZZER_OUT=fuzzer-output
+
+if [ ! -f "$FUZZER_NAME" ]
+then
+ echo -e "${color_failed}Binary $FUZZER_NAME does not exist"
+ echo "${color_reset}"
+ exit 1
+fi
+
+echo "INFO: Running fuzzer : test_service_fuzzer_should_crash"
+
+./test_service_fuzzer_should_crash -max_total_time=30 &>${FUZZER_OUT}
+
+echo "INFO: Searching fuzzer output for expected crashes"
+if grep -q "Expected crash in set" ${FUZZER_OUT};
+then
+ echo -e "${color_success}Success: Found expected crash. fuzzService test successful!"
+else
+ echo -e "${color_failed}Failed: Unable to find successful fuzzing output from test_service_fuzzer_should_crash"
+ echo "${color_reset}"
+ exit 1
+fi
diff --git a/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp b/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp
index 910c9dc..a6fd487 100644
--- a/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp
+++ b/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp
@@ -51,8 +51,10 @@
sp<RpcSession> session = RpcSession::make();
session->setMaxIncomingThreads(1);
status_t status;
- for (size_t tries = 0; tries < 5; tries++) {
- usleep(10000);
+
+ // b/274084938 - ASAN may be slow, wait a while
+ for (size_t tries = 0; tries < 50; tries++) {
+ usleep(100000);
status = session->setupUnixDomainClient(addr.c_str());
if (status == OK) break;
}
diff --git a/libs/binder/trusty/RpcServerTrusty.cpp b/libs/binder/trusty/RpcServerTrusty.cpp
index 109da75..8f64323 100644
--- a/libs/binder/trusty/RpcServerTrusty.cpp
+++ b/libs/binder/trusty/RpcServerTrusty.cpp
@@ -65,6 +65,10 @@
mTipcPort.msg_queue_len = 6; // Three each way
mTipcPort.priv = this;
+ // TODO(b/266741352): follow-up to prevent needing this in the future
+ // Trusty needs to be set to the latest stable version that is in prebuilts there.
+ LOG_ALWAYS_FATAL_IF(!mRpcServer->setProtocolVersion(0));
+
if (mPortAcl) {
// Initialize the array of pointers to uuids.
// The pointers in mUuidPtrs should stay valid across moves of
@@ -154,8 +158,18 @@
return NO_ERROR;
}
-void RpcServerTrusty::handleDisconnect(const tipc_port* /*port*/, handle_t /*chan*/,
- void* /*ctx*/) {}
+void RpcServerTrusty::handleDisconnect(const tipc_port* /*port*/, handle_t /*chan*/, void* ctx) {
+ auto* channelContext = reinterpret_cast<ChannelContext*>(ctx);
+ if (channelContext == nullptr) {
+ // Connections marked "incoming" (outgoing from the server's side)
+ // do not have a valid channel context because joinFn does not get
+ // called for them. We ignore them here.
+ return;
+ }
+
+ auto& session = channelContext->session;
+ (void)session->shutdownAndWait(false);
+}
void RpcServerTrusty::handleChannelCleanup(void* ctx) {
auto* channelContext = reinterpret_cast<ChannelContext*>(ctx);
diff --git a/libs/binder/trusty/RpcTransportTipcTrusty.cpp b/libs/binder/trusty/RpcTransportTipcTrusty.cpp
index d249b2e..692f82d 100644
--- a/libs/binder/trusty/RpcTransportTipcTrusty.cpp
+++ b/libs/binder/trusty/RpcTransportTipcTrusty.cpp
@@ -29,8 +29,6 @@
namespace android {
-namespace {
-
// RpcTransport for Trusty.
class RpcTransportTipcTrusty : public RpcTransport {
public:
@@ -282,8 +280,6 @@
std::vector<uint8_t> getCertificate(RpcCertificateFormat) const override { return {}; }
};
-} // namespace
-
std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTipcTrusty::newServerCtx() const {
return std::make_unique<RpcTransportCtxTipcTrusty>();
}
diff --git a/libs/binder/trusty/binderRpcTest/manifest.json b/libs/binder/trusty/binderRpcTest/manifest.json
index d8b080f..1cefac5 100644
--- a/libs/binder/trusty/binderRpcTest/manifest.json
+++ b/libs/binder/trusty/binderRpcTest/manifest.json
@@ -1,6 +1,6 @@
{
"uuid": "9dbe9fb8-60fd-4bdd-af86-03e95d7ad78b",
"app_name": "binderRpcTest",
- "min_heap": 163840,
+ "min_heap": 262144,
"min_stack": 16384
}
diff --git a/libs/binder/trusty/binderRpcTest/rules.mk b/libs/binder/trusty/binderRpcTest/rules.mk
index ae39492..975f689 100644
--- a/libs/binder/trusty/binderRpcTest/rules.mk
+++ b/libs/binder/trusty/binderRpcTest/rules.mk
@@ -32,4 +32,8 @@
trusty/user/base/lib/googletest \
trusty/user/base/lib/libstdc++-trusty \
+# TEST_P tests from binderRpcUniversalTests.cpp don't get linked in
+# unless we pass in --whole-archive to the linker (b/275620340).
+MODULE_USE_WHOLE_ARCHIVE := true
+
include make/trusted_app.mk
diff --git a/libs/binder/trusty/include/binder/RpcServerTrusty.h b/libs/binder/trusty/include/binder/RpcServerTrusty.h
index 6678eb8..8924b36 100644
--- a/libs/binder/trusty/include/binder/RpcServerTrusty.h
+++ b/libs/binder/trusty/include/binder/RpcServerTrusty.h
@@ -59,14 +59,17 @@
size_t msgMaxSize,
std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory = nullptr);
- void setProtocolVersion(uint32_t version) { mRpcServer->setProtocolVersion(version); }
+ [[nodiscard]] bool setProtocolVersion(uint32_t version) {
+ return mRpcServer->setProtocolVersion(version);
+ }
void setSupportedFileDescriptorTransportModes(
const std::vector<RpcSession::FileDescriptorTransportMode>& modes) {
mRpcServer->setSupportedFileDescriptorTransportModes(modes);
}
void setRootObject(const sp<IBinder>& binder) { mRpcServer->setRootObject(binder); }
void setRootObjectWeak(const wp<IBinder>& binder) { mRpcServer->setRootObjectWeak(binder); }
- void setPerSessionRootObject(std::function<sp<IBinder>(const void*, size_t)>&& object) {
+ void setPerSessionRootObject(
+ std::function<sp<IBinder>(wp<RpcSession> session, const void*, size_t)>&& object) {
mRpcServer->setPerSessionRootObject(std::move(object));
}
sp<IBinder> getRootObject() { return mRpcServer->getRootObject(); }
diff --git a/libs/binderdebug/BinderDebug.cpp b/libs/binderdebug/BinderDebug.cpp
index d086b49..a8f2cbf 100644
--- a/libs/binderdebug/BinderDebug.cpp
+++ b/libs/binderdebug/BinderDebug.cpp
@@ -48,14 +48,12 @@
return -errno;
}
}
- static const std::regex kContextLine("^context (\\w+)$");
bool isDesiredContext = false;
std::string line;
- std::smatch match;
while (getline(ifs, line)) {
- if (std::regex_search(line, match, kContextLine)) {
- isDesiredContext = match.str(1) == contextName;
+ if (base::StartsWith(line, "context")) {
+ isDesiredContext = base::Split(line, " ").back() == contextName;
continue;
}
if (!isDesiredContext) {
@@ -66,57 +64,72 @@
return OK;
}
+// Examples of what we are looking at:
+// node 66730: u00007590061890e0 c0000759036130950 pri 0:120 hs 1 hw 1 ls 0 lw 0 is 2 iw 2 tr 1 proc 2300 1790
+// thread 2999: l 00 need_return 1 tr 0
status_t getBinderPidInfo(BinderDebugContext context, pid_t pid, BinderPidInfo* pidInfo) {
std::smatch match;
static const std::regex kReferencePrefix("^\\s*node \\d+:\\s+u([0-9a-f]+)\\s+c([0-9a-f]+)\\s+");
static const std::regex kThreadPrefix("^\\s*thread \\d+:\\s+l\\s+(\\d)(\\d)");
std::string contextStr = contextToString(context);
status_t ret = scanBinderContext(pid, contextStr, [&](const std::string& line) {
- if (std::regex_search(line, match, kReferencePrefix)) {
- const std::string& ptrString = "0x" + match.str(2); // use number after c
- uint64_t ptr;
- if (!::android::base::ParseUint(ptrString.c_str(), &ptr)) {
- // Should not reach here, but just be tolerant.
- return;
- }
- const std::string proc = " proc ";
- auto pos = line.rfind(proc);
- if (pos != std::string::npos) {
- for (const std::string& pidStr : base::Split(line.substr(pos + proc.size()), " ")) {
- int32_t pid;
- if (!::android::base::ParseInt(pidStr, &pid)) {
+ if (base::StartsWith(line, " node")) {
+ std::vector<std::string> splitString = base::Tokenize(line, " ");
+ bool pids = false;
+ uint64_t ptr = 0;
+ for (const auto& token : splitString) {
+ if (base::StartsWith(token, "u")) {
+ const std::string ptrString = "0x" + token.substr(1);
+ if (!::android::base::ParseUint(ptrString.c_str(), &ptr)) {
+ LOG(ERROR) << "Failed to parse pointer: " << ptrString;
return;
}
- pidInfo->refPids[ptr].push_back(pid);
+ } else {
+ // The last numbers in the line after "proc" are all client PIDs
+ if (token == "proc") {
+ pids = true;
+ } else if (pids) {
+ int32_t pid;
+ if (!::android::base::ParseInt(token, &pid)) {
+ LOG(ERROR) << "Failed to parse pid int: " << token;
+ return;
+ }
+ if (ptr == 0) {
+ LOG(ERROR) << "We failed to parse the pointer, so we can't add the refPids";
+ return;
+ }
+ pidInfo->refPids[ptr].push_back(pid);
+ }
}
}
+ } else if (base::StartsWith(line, " thread")) {
+ auto pos = line.find("l ");
+ if (pos != std::string::npos) {
+ // "1" is waiting in binder driver
+ // "2" is poll. It's impossible to tell if these are in use.
+ // and HIDL default code doesn't use it.
+ bool isInUse = line.at(pos + 2) != '1';
+ // "0" is a thread that has called into binder
+ // "1" is looper thread
+ // "2" is main looper thread
+ bool isBinderThread = line.at(pos + 3) != '0';
+ if (!isBinderThread) {
+ return;
+ }
+ if (isInUse) {
+ pidInfo->threadUsage++;
+ }
- return;
- }
- if (std::regex_search(line, match, kThreadPrefix)) {
- // "1" is waiting in binder driver
- // "2" is poll. It's impossible to tell if these are in use.
- // and HIDL default code doesn't use it.
- bool isInUse = match.str(1) != "1";
- // "0" is a thread that has called into binder
- // "1" is looper thread
- // "2" is main looper thread
- bool isBinderThread = match.str(2) != "0";
- if (!isBinderThread) {
- return;
+ pidInfo->threadCount++;
}
- if (isInUse) {
- pidInfo->threadUsage++;
- }
-
- pidInfo->threadCount++;
- return;
}
- return;
});
return ret;
}
+// Examples of what we are looking at:
+// ref 52493: desc 910 node 52492 s 1 w 1 d 0000000000000000
+// node 29413: u00007803fc982e80 c000078042c982210 pri 0:139 hs 1 hw 1 ls 0 lw 0 is 2 iw 2 tr 1 proc 488 683
status_t getBinderClientPids(BinderDebugContext context, pid_t pid, pid_t servicePid,
int32_t handle, std::vector<pid_t>* pids) {
std::smatch match;
@@ -124,51 +137,64 @@
std::string contextStr = contextToString(context);
int32_t node;
status_t ret = scanBinderContext(pid, contextStr, [&](const std::string& line) {
- if (std::regex_search(line, match, kNodeNumber)) {
- const std::string& descString = match.str(1);
- int32_t desc;
- if (!::android::base::ParseInt(descString.c_str(), &desc)) {
- LOG(ERROR) << "Failed to parse desc int: " << descString;
- return;
- }
- if (handle != desc) {
- return;
- }
- const std::string& nodeString = match.str(2);
- if (!::android::base::ParseInt(nodeString.c_str(), &node)) {
- LOG(ERROR) << "Failed to parse node int: " << nodeString;
- return;
- }
+ if (!base::StartsWith(line, " ref")) return;
+
+ std::vector<std::string> splitString = base::Tokenize(line, " ");
+ if (splitString.size() < 12) {
+ LOG(ERROR) << "Failed to parse binder_logs ref entry. Expecting size greater than 11, but got: " << splitString.size();
return;
}
- return;
+ int32_t desc;
+ if (!::android::base::ParseInt(splitString[3].c_str(), &desc)) {
+ LOG(ERROR) << "Failed to parse desc int: " << splitString[3];
+ return;
+ }
+ if (handle != desc) {
+ return;
+ }
+ if (!::android::base::ParseInt(splitString[5].c_str(), &node)) {
+ LOG(ERROR) << "Failed to parse node int: " << splitString[5];
+ return;
+ }
+ LOG(INFO) << "Parsed the node: " << node;
});
if (ret != OK) {
return ret;
}
- static const std::regex kClients("^\\s+node\\s+(\\d+).*proc\\s+([\\d+\\s*]*)");
+
ret = scanBinderContext(servicePid, contextStr, [&](const std::string& line) {
- if (std::regex_search(line, match, kClients)) {
- const std::string nodeString = match.str(1);
- int32_t matchedNode;
- if (!::android::base::ParseInt(nodeString.c_str(), &matchedNode)) {
- LOG(ERROR) << "Failed to parse node int: " << nodeString;
- return;
- }
- if (node != matchedNode) {
- return;
- }
- const std::string clients = match.str(2);
- for (const std::string& pidStr : base::Split(clients, " ")) {
+ if (!base::StartsWith(line, " node")) return;
+
+ std::vector<std::string> splitString = base::Tokenize(line, " ");
+ if (splitString.size() < 21) {
+ LOG(ERROR) << "Failed to parse binder_logs node entry. Expecting size greater than 20, but got: " << splitString.size();
+ return;
+ }
+
+ // remove the colon
+ const std::string nodeString = splitString[1].substr(0, splitString[1].size() - 1);
+ int32_t matchedNode;
+ if (!::android::base::ParseInt(nodeString.c_str(), &matchedNode)) {
+ LOG(ERROR) << "Failed to parse node int: " << nodeString;
+ return;
+ }
+
+ if (node != matchedNode) {
+ return;
+ }
+ bool pidsSection = false;
+ for (const auto& token : splitString) {
+ if (token == "proc") {
+ pidsSection = true;
+ } else if (pidsSection == true) {
int32_t pid;
- if (!::android::base::ParseInt(pidStr, &pid)) {
+ if (!::android::base::ParseInt(token.c_str(), &pid)) {
+ LOG(ERROR) << "Failed to parse PID int: " << token;
return;
}
pids->push_back(pid);
}
- return;
}
- return;
});
return ret;
}
diff --git a/libs/binderthreadstate/include/binderthreadstate/CallerUtils.h b/libs/binderthreadstate/include/binderthreadstate/CallerUtils.h
index a3e5026..54259d2 100644
--- a/libs/binderthreadstate/include/binderthreadstate/CallerUtils.h
+++ b/libs/binderthreadstate/include/binderthreadstate/CallerUtils.h
@@ -36,8 +36,12 @@
// Based on where we are in recursion of nested binder/hwbinder calls, determine
// which one we are closer to.
inline static BinderCallType getCurrentServingCall() {
- const void* hwbinderSp = android::hardware::IPCThreadState::self()->getServingStackPointer();
- const void* binderSp = android::IPCThreadState::self()->getServingStackPointer();
+ auto* hwState = android::hardware::IPCThreadState::selfOrNull();
+ auto* state = android::IPCThreadState::selfOrNull();
+
+ // getServingStackPointer can also return nullptr
+ const void* hwbinderSp = hwState ? hwState->getServingStackPointer() : nullptr;
+ const void* binderSp = state ? state->getServingStackPointer() : nullptr;
if (hwbinderSp == nullptr && binderSp == nullptr) return BinderCallType::NONE;
if (hwbinderSp == nullptr) return BinderCallType::BINDER;
diff --git a/libs/binderthreadstate/test.cpp b/libs/binderthreadstate/test.cpp
index df1f35d..b5c4010 100644
--- a/libs/binderthreadstate/test.cpp
+++ b/libs/binderthreadstate/test.cpp
@@ -16,11 +16,16 @@
#include <BnAidlStuff.h>
#include <android-base/logging.h>
+#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binderthreadstate/CallerUtils.h>
#include <binderthreadstateutilstest/1.0/IHidlStuff.h>
#include <gtest/gtest.h>
#include <hidl/HidlTransportSupport.h>
+#include <hwbinder/IPCThreadState.h>
+
+#include <thread>
+
#include <linux/prctl.h>
#include <sys/prctl.h>
@@ -154,6 +159,20 @@
EXPECT_TRUE(server->callLocal().isOk());
}
+TEST(BinderThreadState, DoesntInitializeBinderDriver) {
+ // this is on another thread, because it's testing thread-specific
+ // state and we expect it not to be initialized.
+ std::thread([&] {
+ EXPECT_EQ(nullptr, android::IPCThreadState::selfOrNull());
+ EXPECT_EQ(nullptr, android::hardware::IPCThreadState::selfOrNull());
+
+ (void)getCurrentServingCall();
+
+ EXPECT_EQ(nullptr, android::IPCThreadState::selfOrNull());
+ EXPECT_EQ(nullptr, android::hardware::IPCThreadState::selfOrNull());
+ }).join();
+}
+
TEST(BindThreadState, RemoteHidlCall) {
auto stuff = IHidlStuff::getService(id2name(kP1Id));
ASSERT_NE(nullptr, stuff);
diff --git a/libs/cputimeinstate/cputimeinstate.cpp b/libs/cputimeinstate/cputimeinstate.cpp
index 706704a..4a7bd36 100644
--- a/libs/cputimeinstate/cputimeinstate.cpp
+++ b/libs/cputimeinstate/cputimeinstate.cpp
@@ -55,6 +55,7 @@
static uint32_t gNCpus = 0;
static std::vector<std::vector<uint32_t>> gPolicyFreqs;
static std::vector<std::vector<uint32_t>> gPolicyCpus;
+static std::vector<uint32_t> gCpuIndexMap;
static std::set<uint32_t> gAllFreqs;
static unique_fd gTisTotalMapFd;
static unique_fd gTisMapFd;
@@ -108,7 +109,7 @@
free(dirlist[i]);
}
free(dirlist);
-
+ uint32_t max_cpu_number = 0;
for (const auto &policy : policyFileNames) {
std::vector<uint32_t> freqs;
for (const auto &name : {"available", "boost"}) {
@@ -127,8 +128,19 @@
std::string path = StringPrintf("%s/%s/%s", basepath, policy.c_str(), "related_cpus");
auto cpus = readNumbersFromFile(path);
if (!cpus) return false;
+ for (auto cpu : *cpus) {
+ if(cpu > max_cpu_number)
+ max_cpu_number = cpu;
+ }
gPolicyCpus.emplace_back(*cpus);
}
+ gCpuIndexMap = std::vector<uint32_t>(max_cpu_number+1, -1);
+ uint32_t cpuorder = 0;
+ for (const auto &cpuList : gPolicyCpus) {
+ for (auto cpu : cpuList) {
+ gCpuIndexMap[cpu] = cpuorder++;
+ }
+ }
gTisTotalMapFd =
unique_fd{bpf_obj_get(BPF_FS_PATH "map_timeInState_total_time_in_state_map")};
@@ -277,7 +289,7 @@
for (uint32_t policyIdx = 0; policyIdx < gNPolicies; ++policyIdx) {
if (freqIdx >= gPolicyFreqs[policyIdx].size()) continue;
for (const auto &cpu : gPolicyCpus[policyIdx]) {
- out[policyIdx][freqIdx] += vals[cpu];
+ out[policyIdx][freqIdx] += vals[gCpuIndexMap[cpu]];
}
}
}
@@ -316,7 +328,8 @@
auto end = nextOffset < gPolicyFreqs[j].size() ? begin + FREQS_PER_ENTRY : out[j].end();
for (const auto &cpu : gPolicyCpus[j]) {
- std::transform(begin, end, std::begin(vals[cpu].ar), begin, std::plus<uint64_t>());
+ std::transform(begin, end, std::begin(vals[gCpuIndexMap[cpu]].ar), begin,
+ std::plus<uint64_t>());
}
}
}
@@ -382,7 +395,8 @@
auto end = nextOffset < gPolicyFreqs[i].size() ? begin + FREQS_PER_ENTRY :
map[key.uid][i].end();
for (const auto &cpu : gPolicyCpus[i]) {
- std::transform(begin, end, std::begin(vals[cpu].ar), begin, std::plus<uint64_t>());
+ std::transform(begin, end, std::begin(vals[gCpuIndexMap[cpu]].ar), begin,
+ std::plus<uint64_t>());
}
}
prevKey = key;
@@ -437,8 +451,8 @@
: ret.policy[policy].end();
for (const auto &cpu : gPolicyCpus[policy]) {
- std::transform(policyBegin, policyEnd, std::begin(vals[cpu].policy), policyBegin,
- std::plus<uint64_t>());
+ std::transform(policyBegin, policyEnd, std::begin(vals[gCpuIndexMap[cpu]].policy),
+ policyBegin, std::plus<uint64_t>());
}
}
}
@@ -506,8 +520,8 @@
: ret[key.uid].policy[policy].end();
for (const auto &cpu : gPolicyCpus[policy]) {
- std::transform(policyBegin, policyEnd, std::begin(vals[cpu].policy), policyBegin,
- std::plus<uint64_t>());
+ std::transform(policyBegin, policyEnd, std::begin(vals[gCpuIndexMap[cpu]].policy),
+ policyBegin, std::plus<uint64_t>());
}
}
} while (prevKey = key, !getNextMapKey(gConcurrentMapFd, &prevKey, &key));
@@ -640,7 +654,7 @@
auto end = nextOffset < gPolicyFreqs[j].size() ? begin + FREQS_PER_ENTRY
: map[key.aggregation_key][j].end();
for (const auto &cpu : gPolicyCpus[j]) {
- std::transform(begin, end, std::begin(vals[cpu].ar), begin,
+ std::transform(begin, end, std::begin(vals[gCpuIndexMap[cpu]].ar), begin,
std::plus<uint64_t>());
}
}
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 067ce17..97cb810 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -16,6 +16,7 @@
#include <set>
#include <android-base/file.h>
+#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
@@ -210,3 +211,18 @@
return cmdline == "zygote" || cmdline == "zygote64" || cmdline == "usap32" ||
cmdline == "usap64" || cmdline == "webview_zygote";
}
+
+bool IsCached(int pid) {
+ std::string oom_score_adj;
+ if (!android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/oom_score_adj",
+ pid),
+ &oom_score_adj)) {
+ return false;
+ }
+ int32_t oom_score_adj_value;
+ if (!android::base::ParseInt(android::base::Trim(oom_score_adj), &oom_score_adj_value)) {
+ return false;
+ }
+ // An OOM score greater than 900 indicates a cached process.
+ return oom_score_adj_value >= 900;
+}
diff --git a/libs/dumputils/include/dumputils/dump_utils.h b/libs/dumputils/include/dumputils/dump_utils.h
index 7c5329d..f973d9f 100644
--- a/libs/dumputils/include/dumputils/dump_utils.h
+++ b/libs/dumputils/include/dumputils/dump_utils.h
@@ -25,4 +25,6 @@
bool IsZygote(int pid);
+bool IsCached(int pid);
+
#endif // DUMPUTILS_H_
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 2ac1174..0fe6f24 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -214,6 +214,7 @@
shared_libs: [
"libbinder",
+ "libGLESv2",
],
export_shared_lib_headers: [
@@ -326,7 +327,6 @@
"libbase",
"libcutils",
"libEGL",
- "libGLESv2",
"libhidlbase",
"liblog",
"libnativewindow",
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 9eb1a9f..f934680 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -615,7 +615,8 @@
BQ_LOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x",
*outSlot,
mSlots[*outSlot].mFrameNumber,
- mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);
+ mSlots[*outSlot].mGraphicBuffer != nullptr ?
+ mSlots[*outSlot].mGraphicBuffer->handle : nullptr, returnFlags);
if (outBufferAge) {
*outBufferAge = mCore->mBufferAge;
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 502031c..74e6ae6 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -353,6 +353,27 @@
}
}
+void DisplayState::sanitize(int32_t permissions) {
+ if (what & DisplayState::eLayerStackChanged) {
+ if (!(permissions & layer_state_t::Permission::ACCESS_SURFACE_FLINGER)) {
+ what &= ~DisplayState::eLayerStackChanged;
+ ALOGE("Stripped attempt to set eLayerStackChanged in sanitize");
+ }
+ }
+ if (what & DisplayState::eDisplayProjectionChanged) {
+ if (!(permissions & layer_state_t::Permission::ACCESS_SURFACE_FLINGER)) {
+ what &= ~DisplayState::eDisplayProjectionChanged;
+ ALOGE("Stripped attempt to set eDisplayProjectionChanged in sanitize");
+ }
+ }
+ if (what & DisplayState::eSurfaceChanged) {
+ if (!(permissions & layer_state_t::Permission::ACCESS_SURFACE_FLINGER)) {
+ what &= ~DisplayState::eSurfaceChanged;
+ ALOGE("Stripped attempt to set eSurfaceChanged in sanitize");
+ }
+ }
+}
+
void layer_state_t::sanitize(int32_t permissions) {
// TODO: b/109894387
//
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 3b13708..100e36e 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -792,11 +792,15 @@
return result;
}
- std::vector<CancelBufferInput> cancelBufferInputs(numBufferRequested);
+ std::vector<CancelBufferInput> cancelBufferInputs;
+ cancelBufferInputs.reserve(numBufferRequested);
std::vector<status_t> cancelBufferOutputs;
for (size_t i = 0; i < numBufferRequested; i++) {
- cancelBufferInputs[i].slot = dequeueOutput[i].slot;
- cancelBufferInputs[i].fence = dequeueOutput[i].fence;
+ if (dequeueOutput[i].result >= 0) {
+ CancelBufferInput& input = cancelBufferInputs.emplace_back();
+ input.slot = dequeueOutput[i].slot;
+ input.fence = dequeueOutput[i].fence;
+ }
}
for (const auto& output : dequeueOutput) {
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 0a9b75a..0071d48 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -320,6 +320,7 @@
DisplayState();
void merge(const DisplayState& other);
+ void sanitize(int32_t permissions);
uint32_t what = 0;
uint32_t flags = 0;
diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp
index d6b4579..250c0dd 100644
--- a/libs/input/KeyLayoutMap.cpp
+++ b/libs/input/KeyLayoutMap.cpp
@@ -230,6 +230,16 @@
return scanCodes;
}
+std::vector<int32_t> KeyLayoutMap::findUsageCodesForKey(int32_t keyCode) const {
+ std::vector<int32_t> usageCodes;
+ for (const auto& [usageCode, key] : mKeysByUsageCode) {
+ if (keyCode == key.keyCode) {
+ usageCodes.push_back(usageCode);
+ }
+ }
+ return usageCodes;
+}
+
std::optional<AxisInfo> KeyLayoutMap::mapAxis(int32_t scanCode) const {
auto it = mAxes.find(scanCode);
if (it == mAxes.end()) {
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index b2e069c..2e0add5 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -18,6 +18,7 @@
#include <android/hardware_buffer.h>
#include <android/hardware_buffer_aidl.h>
+#include <android/binder_libbinder.h>
#include <vndk/hardware_buffer.h>
#include <errno.h>
@@ -34,9 +35,6 @@
#include <android/hardware/graphics/common/1.1/types.h>
#include <aidl/android/hardware/graphics/common/PixelFormat.h>
-// TODO: Better way to handle this
-#include "../binder/ndk/parcel_internal.h"
-
static constexpr int kFdBufferSize = 128 * sizeof(int); // 128 ints
using namespace android;
@@ -421,7 +419,7 @@
AHardwareBuffer* _Nullable* _Nonnull outBuffer) {
if (!parcel || !outBuffer) return STATUS_BAD_VALUE;
auto buffer = sp<GraphicBuffer>::make();
- status_t status = parcel->get()->read(*buffer);
+ status_t status = AParcel_viewPlatformParcel(parcel)->read(*buffer);
if (status != STATUS_OK) return status;
*outBuffer = AHardwareBuffer_from_GraphicBuffer(buffer.get());
AHardwareBuffer_acquire(*outBuffer);
@@ -433,7 +431,7 @@
const GraphicBuffer* gb = AHardwareBuffer_to_GraphicBuffer(buffer);
if (!gb) return STATUS_BAD_VALUE;
if (!parcel) return STATUS_BAD_VALUE;
- return parcel->get()->write(*gb);
+ return AParcel_viewPlatformParcel(parcel)->write(*gb);
}
// ----------------------------------------------------------------------------
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index 85a5249..21798d0 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -177,14 +177,14 @@
/**
* Corresponding formats:
* Vulkan: VK_FORMAT_R16_UINT
- * OpenGL ES: GR_GL_R16UI
+ * OpenGL ES: GL_R16UI
*/
AHARDWAREBUFFER_FORMAT_R16_UINT = 0x39,
/**
* Corresponding formats:
* Vulkan: VK_FORMAT_R16G16_UINT
- * OpenGL ES: GR_GL_RG16UI
+ * OpenGL ES: GL_RG16UI
*/
AHARDWAREBUFFER_FORMAT_R16G16_UINT = 0x3a,
diff --git a/libs/sensor/ISensorServer.cpp b/libs/sensor/ISensorServer.cpp
index a6cacad..93c95b9 100644
--- a/libs/sensor/ISensorServer.cpp
+++ b/libs/sensor/ISensorServer.cpp
@@ -66,7 +66,11 @@
v.setCapacity(n);
while (n) {
n--;
- reply.read(s);
+ if(reply.read(s) != OK) {
+ ALOGE("Failed to read reply from getSensorList");
+ v.clear();
+ break;
+ }
v.add(s);
}
return v;
@@ -84,7 +88,11 @@
v.setCapacity(n);
while (n) {
n--;
- reply.read(s);
+ if(reply.read(s) != OK) {
+ ALOGE("Failed to read reply from getDynamicSensorList");
+ v.clear();
+ break;
+ }
v.add(s);
}
return v;
diff --git a/libs/sensor/Sensor.cpp b/libs/sensor/Sensor.cpp
index ec0ced8..b865c4d 100644
--- a/libs/sensor/Sensor.cpp
+++ b/libs/sensor/Sensor.cpp
@@ -632,7 +632,13 @@
return false;
}
outputString8.setTo(static_cast<char const*>(buffer), len);
+
+ if (size < FlattenableUtils::align<4>(len)) {
+ ALOGE("Malformed Sensor String8 field. Should be in a 4-byte aligned buffer but is not.");
+ return false;
+ }
FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(len));
+
return true;
}
diff --git a/libs/sensor/SensorManager.cpp b/libs/sensor/SensorManager.cpp
index 0ba9704..40061cd 100644
--- a/libs/sensor/SensorManager.cpp
+++ b/libs/sensor/SensorManager.cpp
@@ -92,6 +92,16 @@
return *sensorManager;
}
+void SensorManager::removeInstanceForPackage(const String16& packageName) {
+ Mutex::Autolock _l(sLock);
+ auto iterator = sPackageInstances.find(packageName);
+ if (iterator != sPackageInstances.end()) {
+ SensorManager* sensorManager = iterator->second;
+ delete sensorManager;
+ sPackageInstances.erase(iterator);
+ }
+}
+
SensorManager::SensorManager(const String16& opPackageName)
: mSensorList(nullptr), mOpPackageName(opPackageName), mDirectConnectionHandle(1) {
Mutex::Autolock _l(mLock);
@@ -166,6 +176,11 @@
mSensors = mSensorServer->getSensorList(mOpPackageName);
size_t count = mSensors.size();
+ if (count == 0) {
+ ALOGE("Failed to get Sensor list");
+ mSensorServer.clear();
+ return UNKNOWN_ERROR;
+ }
mSensorList =
static_cast<Sensor const**>(malloc(count * sizeof(Sensor*)));
LOG_ALWAYS_FATAL_IF(mSensorList == nullptr, "mSensorList NULL");
diff --git a/libs/sensor/include/sensor/SensorManager.h b/libs/sensor/include/sensor/SensorManager.h
index 8d0a8a4..7c9d604 100644
--- a/libs/sensor/include/sensor/SensorManager.h
+++ b/libs/sensor/include/sensor/SensorManager.h
@@ -54,6 +54,7 @@
{
public:
static SensorManager& getInstanceForPackage(const String16& packageName);
+ static void removeInstanceForPackage(const String16& packageName);
~SensorManager();
ssize_t getSensorList(Sensor const* const** list);
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index dd14bcf..6ea4007 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -21,6 +21,7 @@
#include <android-base/properties.h>
#include <android/dlext.h>
+#include <cutils/properties.h>
#include <dirent.h>
#include <dlfcn.h>
#include <graphicsenv/GraphicsEnv.h>
@@ -236,29 +237,22 @@
LOG_ALWAYS_FATAL("couldn't find an OpenGL ES implementation from %s",
android::GraphicsEnv::getInstance().getDriverPath().c_str());
}
- // Finally, try to load system driver. If ANGLE is the system driver
- // (i.e. we are forcing the legacy system driver instead of ANGLE), use
- // the driver suffix that was passed down from above.
- if (shouldForceLegacyDriver) {
- std::string suffix = android::GraphicsEnv::getInstance().getLegacySuffix();
- hnd = attempt_to_load_system_driver(cnx, suffix.c_str(), true);
- } else {
- // Start by searching for the library name appended by the system
- // properties of the GLES userspace driver in both locations.
- // i.e.:
- // libGLES_${prop}.so, or:
- // libEGL_${prop}.so, libGLESv1_CM_${prop}.so, libGLESv2_${prop}.so
- for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
- auto prop = base::GetProperty(key, "");
- if (prop.empty()) {
- continue;
- }
- hnd = attempt_to_load_system_driver(cnx, prop.c_str(), true);
- if (hnd) {
- break;
- } else if (strcmp(key, DRIVER_SUFFIX_PROPERTY) == 0) {
- failToLoadFromDriverSuffixProperty = true;
- }
+ // Finally, try to load system driver.
+ // Start by searching for the library name appended by the system
+ // properties of the GLES userspace driver in both locations.
+ // i.e.:
+ // libGLES_${prop}.so, or:
+ // libEGL_${prop}.so, libGLESv1_CM_${prop}.so, libGLESv2_${prop}.so
+ for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
+ auto prop = base::GetProperty(key, "");
+ if (prop.empty()) {
+ continue;
+ }
+ hnd = attempt_to_load_system_driver(cnx, prop.c_str(), true);
+ if (hnd) {
+ break;
+ } else if (strcmp(key, DRIVER_SUFFIX_PROPERTY) == 0) {
+ failToLoadFromDriverSuffixProperty = true;
}
}
}
@@ -272,7 +266,10 @@
hnd = attempt_to_load_system_driver(cnx, nullptr, true);
}
- if (!hnd && !failToLoadFromDriverSuffixProperty) {
+ if (!hnd && !failToLoadFromDriverSuffixProperty &&
+ property_get_int32("ro.vendor.api_level", 0) < __ANDROID_API_U__) {
+ // Still can't find the graphics drivers with the exact name. This time try to use wildcard
+ // matching if the device is launched before Android 14.
hnd = attempt_to_load_system_driver(cnx, nullptr, false);
}
diff --git a/opengl/libs/EGL/egl_angle_platform.cpp b/opengl/libs/EGL/egl_angle_platform.cpp
index d38f2ef..c0ead50 100644
--- a/opengl/libs/EGL/egl_angle_platform.cpp
+++ b/opengl/libs/EGL/egl_angle_platform.cpp
@@ -145,6 +145,7 @@
if (!angleGetDisplayPlatform) {
ALOGE("dlsym lookup of ANGLEGetDisplayPlatform in libEGL_angle failed!");
+ dlclose(so);
return false;
}
@@ -155,6 +156,7 @@
if (!((angleGetDisplayPlatform)(dpy, g_PlatformMethodNames, g_NumPlatformMethods, nullptr,
&platformMethods))) {
ALOGE("ANGLEGetDisplayPlatform call failed!");
+ dlclose(so);
return false;
}
if (platformMethods) {
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 0b755aa..6593c1b 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -322,6 +322,16 @@
mExtensionString = gBuiltinExtensionString;
+ // b/269060366 Conditionally enabled EGL_ANDROID_get_frame_timestamps extension if the
+ // device's present timestamps are reliable (which may not be the case on emulators).
+ if (cnx->useAngle) {
+ if (android::base::GetBoolProperty("service.sf.present_timestamp", false)) {
+ mExtensionString.append("EGL_ANDROID_get_frame_timestamps ");
+ }
+ } else {
+ mExtensionString.append("EGL_ANDROID_get_frame_timestamps ");
+ }
+
hasColorSpaceSupport = findExtension(disp.queryString.extensions, "EGL_KHR_gl_colorspace");
// Note: CDD requires that devices supporting wide color and/or HDR color also support
@@ -361,6 +371,7 @@
findExtension(disp.queryString.extensions, "EGL_KHR_image_gl_colorspace")) {
mExtensionString.append("EGL_EXT_image_gl_colorspace ");
}
+
if (findExtension(disp.queryString.extensions, ext.c_str(), len)) {
mExtensionString.append(ext + " ");
}
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index 7619a50..5f441ee 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -84,7 +84,8 @@
// Extensions implemented by the EGL wrapper.
const char* const gBuiltinExtensionString =
"EGL_ANDROID_front_buffer_auto_refresh "
- "EGL_ANDROID_get_frame_timestamps "
+ // b/269060366 Conditionally enabled during display initialization:
+ //"EGL_ANDROID_get_frame_timestamps "
"EGL_ANDROID_get_native_client_buffer "
"EGL_ANDROID_presentation_time "
"EGL_EXT_surface_CTA861_3_metadata "
@@ -2183,6 +2184,10 @@
return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
}
+ if (!dp->haveExtension("EGL_ANDROID_get_frame_timestamps")) {
+ return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
+ }
+
SurfaceRef _s(dp, surface);
if (!_s.get()) {
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
@@ -2216,6 +2221,10 @@
return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
}
+ if (!dp->haveExtension("EGL_ANDROID_get_frame_timestamps")) {
+ return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
+ }
+
SurfaceRef _s(dp, surface);
if (!_s.get()) {
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
@@ -2270,6 +2279,10 @@
return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
}
+ if (!dp->haveExtension("EGL_ANDROID_get_frame_timestamps")) {
+ return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
+ }
+
SurfaceRef _s(dp, surface);
if (!_s.get()) {
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
@@ -2300,6 +2313,10 @@
return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
}
+ if (!dp->haveExtension("EGL_ANDROID_get_frame_timestamps")) {
+ return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
+ }
+
SurfaceRef _s(dp, surface);
if (!_s.get()) {
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
@@ -2385,6 +2402,10 @@
return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
}
+ if (!dp->haveExtension("EGL_ANDROID_get_frame_timestamps")) {
+ return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
+ }
+
SurfaceRef _s(dp, surface);
if (!_s.get()) {
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
diff --git a/services/automotive/display/Android.bp b/services/automotive/display/Android.bp
index 614a78e..72bd292 100644
--- a/services/automotive/display/Android.bp
+++ b/services/automotive/display/Android.bp
@@ -53,6 +53,4 @@
vintf_fragments: [
"manifest_android.frameworks.automotive.display@1.0.xml",
],
-
- system_ext_specific: true,
}
diff --git a/services/automotive/display/android.frameworks.automotive.display@1.0-service.rc b/services/automotive/display/android.frameworks.automotive.display@1.0-service.rc
index ea1077a..5c7f344 100644
--- a/services/automotive/display/android.frameworks.automotive.display@1.0-service.rc
+++ b/services/automotive/display/android.frameworks.automotive.display@1.0-service.rc
@@ -1,4 +1,4 @@
-service automotive_display /system_ext/bin/android.frameworks.automotive.display@1.0-service
+service automotive_display /system/bin/android.frameworks.automotive.display@1.0-service
class hal
user graphics
group automotive_evs
diff --git a/services/gpuservice/tests/fuzzers/Android.bp b/services/gpuservice/tests/fuzzers/Android.bp
new file mode 100644
index 0000000..6bcc5e8
--- /dev/null
+++ b/services/gpuservice/tests/fuzzers/Android.bp
@@ -0,0 +1,26 @@
+package {
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
+cc_fuzz {
+ name: "gpu_service_fuzzer",
+ defaults: [
+ "service_fuzzer_defaults",
+ "fuzzer_disable_leaks",
+ ],
+ static_libs: [
+ "liblog",
+ ],
+ fuzz_config: {
+ cc: [
+ "paulthomson@google.com",
+ "pbaiget@google.com",
+ ],
+ triage_assignee: "waghpawan@google.com",
+ },
+ include_dirs: ["frameworks/native/services/gpuservice/"],
+ srcs: ["GpuServiceFuzzer.cpp"],
+ shared_libs: [
+ "libgpuservice",
+ ],
+}
diff --git a/services/gpuservice/tests/fuzzers/GpuServiceFuzzer.cpp b/services/gpuservice/tests/fuzzers/GpuServiceFuzzer.cpp
new file mode 100644
index 0000000..c2574a3
--- /dev/null
+++ b/services/gpuservice/tests/fuzzers/GpuServiceFuzzer.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 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 <fuzzbinder/libbinder_driver.h>
+
+#include "GpuService.h"
+
+using ::android::fuzzService;
+using ::android::GpuService;
+using ::android::sp;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ sp<GpuService> gpuService = new GpuService();
+ fuzzService(gpuService, FuzzedDataProvider(data, size));
+ return 0;
+}
diff --git a/services/gpuservice/vts/Android.bp b/services/gpuservice/vts/Android.bp
index 83a40e7..b6362e2 100644
--- a/services/gpuservice/vts/Android.bp
+++ b/services/gpuservice/vts/Android.bp
@@ -21,7 +21,6 @@
srcs: ["src/**/*.java"],
libs: [
"tradefed",
- "vts-core-tradefed-harness",
],
test_suites: [
"general-tests",
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index 20baa42..39beed3 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -461,6 +461,11 @@
}
}
+ std::vector<int32_t> usageCodes = keyMap.keyLayoutMap->findUsageCodesForKey(keycode);
+ if (usageCodes.size() > 0 && mscBitmask.test(MSC_SCAN)) {
+ return true;
+ }
+
return false;
}
diff --git a/services/sensorservice/aidl/fuzzer/Android.bp b/services/sensorservice/aidl/fuzzer/Android.bp
index 0d6e476..cb586c6 100644
--- a/services/sensorservice/aidl/fuzzer/Android.bp
+++ b/services/sensorservice/aidl/fuzzer/Android.bp
@@ -11,6 +11,7 @@
name: "libsensorserviceaidl_fuzzer",
defaults: [
"service_fuzzer_defaults",
+ "fuzzer_disable_leaks",
],
host_supported: true,
static_libs: [
diff --git a/services/sensorservice/hidl/SensorManager.cpp b/services/sensorservice/hidl/SensorManager.cpp
index 9380600..0a4e684 100644
--- a/services/sensorservice/hidl/SensorManager.cpp
+++ b/services/sensorservice/hidl/SensorManager.cpp
@@ -60,6 +60,9 @@
if (mPollThread.joinable()) {
mPollThread.join();
}
+
+ ::android::SensorManager::removeInstanceForPackage(
+ String16(ISensorManager::descriptor));
}
// Methods from ::android::frameworks::sensorservice::V1_0::ISensorManager follow.
diff --git a/services/stats/Android.bp b/services/stats/Android.bp
index 7d358e1..6b99627 100644
--- a/services/stats/Android.bp
+++ b/services/stats/Android.bp
@@ -21,6 +21,7 @@
"android.frameworks.stats@1.0",
"android.frameworks.stats-V2-ndk",
"libbinder_ndk",
+ "libexpresslog",
"libhidlbase",
"liblog",
"libstatslog",
diff --git a/services/stats/StatsAidl.cpp b/services/stats/StatsAidl.cpp
index 0f01507..b22f903 100644
--- a/services/stats/StatsAidl.cpp
+++ b/services/stats/StatsAidl.cpp
@@ -22,6 +22,7 @@
#include "StatsAidl.h"
+#include <Counter.h>
#include <log/log.h>
#include <stats_annotations.h>
#include <stats_event.h>
@@ -29,11 +30,18 @@
#include <unordered_map>
+namespace {
+ static const char* g_AtomErrorMetricName =
+ "statsd_errors.value_report_vendor_atom_errors_count";
+}
+
namespace aidl {
namespace android {
namespace frameworks {
namespace stats {
+using ::android::expresslog::Counter;
+
template <typename E>
constexpr typename std::underlying_type<E>::type to_underlying(E e) noexcept {
return static_cast<typename std::underlying_type<E>::type>(e);
@@ -86,12 +94,14 @@
ndk::ScopedAStatus StatsHal::reportVendorAtom(const VendorAtom& vendorAtom) {
if (vendorAtom.atomId < 100000 || vendorAtom.atomId >= 200000) {
ALOGE("Atom ID %ld is not a valid vendor atom ID", (long)vendorAtom.atomId);
+ Counter::logIncrement(g_AtomErrorMetricName);
return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
-1, "Not a valid vendor atom ID");
}
if (vendorAtom.reverseDomainName.length() > 50) {
ALOGE("Vendor atom reverse domain name %s is too long.",
vendorAtom.reverseDomainName.c_str());
+ Counter::logIncrement(g_AtomErrorMetricName);
return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
-1, "Vendor atom reverse domain name is too long");
}
@@ -100,8 +110,9 @@
if (vendorAtom.atomAnnotations) {
if (!write_atom_annotations(event, *vendorAtom.atomAnnotations)) {
- ALOGE("Atom ID %ld has incompatible atom level annotation", (long)vendorAtom.atomId);
AStatsEvent_release(event);
+ ALOGE("Atom ID %ld has incompatible atom level annotation", (long)vendorAtom.atomId);
+ Counter::logIncrement(g_AtomErrorMetricName);
return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
-1, "invalid atom annotation");
}
@@ -222,6 +233,7 @@
default: {
AStatsEvent_release(event);
ALOGE("Atom ID %ld has invalid atomValue.getTag", (long)vendorAtom.atomId);
+ Counter::logIncrement(g_AtomErrorMetricName);
return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
-1, "invalid atomValue.getTag");
break;
@@ -235,9 +247,10 @@
VLOG("Atom ID %ld has %ld annotations for field #%ld", (long)vendorAtom.atomId,
(long)fieldAnnotations.size(), (long)atomValueIdx + 2);
if (!write_field_annotations(event, fieldAnnotations)) {
+ AStatsEvent_release(event);
ALOGE("Atom ID %ld has incompatible field level annotation for field #%ld",
(long)vendorAtom.atomId, (long)atomValueIdx + 2);
- AStatsEvent_release(event);
+ Counter::logIncrement(g_AtomErrorMetricName);
return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
-1, "invalid atom field annotation");
}
@@ -249,6 +262,7 @@
AStatsEvent_release(event);
if (ret <= 0) {
ALOGE("Error writing Atom ID %ld. Result: %d", (long)vendorAtom.atomId, ret);
+ Counter::logIncrement(g_AtomErrorMetricName);
}
return ret <= 0 ? ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(ret,
"report atom failed")
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 3875f15..e06f3c4 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -459,6 +459,7 @@
}
bool BufferStateLayer::setSurfaceDamageRegion(const Region& surfaceDamage) {
+ if (mDrawingState.surfaceDamageRegion.hasSameRects(surfaceDamage)) return false;
mDrawingState.surfaceDamageRegion = surfaceDamage;
mDrawingState.modified = true;
setTransactionFlags(eTransactionNeeded);
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index c2b0a11..905fe40 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -72,6 +72,7 @@
#include "LayerProtoHelper.h"
#include "LayerRejecter.h"
#include "MonitoredProducer.h"
+#include "MutexUtils.h"
#include "SurfaceFlinger.h"
#include "TimeStats/TimeStats.h"
#include "TunnelModeEnabledReporter.h"
@@ -254,10 +255,12 @@
auto layersInTree = getRootLayer()->getLayersInTree(LayerVector::StateSet::Current);
std::sort(layersInTree.begin(), layersInTree.end());
- traverse(LayerVector::StateSet::Current, [&](Layer* layer) {
- layer->removeFromCurrentState();
- layer->removeRelativeZ(layersInTree);
- });
+ REQUIRE_MUTEX(mFlinger->mStateLock);
+ traverse(LayerVector::StateSet::Current,
+ [&](Layer* layer) REQUIRES(layer->mFlinger->mStateLock) {
+ layer->removeFromCurrentState();
+ layer->removeRelativeZ(layersInTree);
+ });
}
void Layer::addToCurrentState() {
@@ -936,10 +939,12 @@
mFlinger->mLayersAdded = true;
// set up SF to handle added color layer
if (isRemovedFromCurrentState()) {
+ MUTEX_ALIAS(mFlinger->mStateLock, mDrawingState.bgColorLayer->mFlinger->mStateLock);
mDrawingState.bgColorLayer->onRemovedFromCurrentState();
}
mFlinger->setTransactionFlags(eTransactionNeeded);
} else if (mDrawingState.bgColorLayer && alpha == 0) {
+ MUTEX_ALIAS(mFlinger->mStateLock, mDrawingState.bgColorLayer->mFlinger->mStateLock);
mDrawingState.bgColorLayer->reparent(nullptr);
mDrawingState.bgColorLayer = nullptr;
return true;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 200baf0..f0c8ad7 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -409,7 +409,7 @@
virtual ui::LayerStack getLayerStack() const;
virtual bool setMetadata(const LayerMetadata& data);
virtual void setChildrenDrawingParent(const sp<Layer>&);
- virtual bool reparent(const sp<IBinder>& newParentHandle);
+ virtual bool reparent(const sp<IBinder>& newParentHandle) REQUIRES(mFlinger->mStateLock);
virtual bool setColorTransform(const mat4& matrix);
virtual mat4 getColorTransform() const;
virtual bool hasColorTransform() const;
@@ -433,7 +433,8 @@
virtual bool setSidebandStream(const sp<NativeHandle>& /*sidebandStream*/) { return false; };
virtual bool setTransactionCompletedListeners(
const std::vector<sp<CallbackHandle>>& /*handles*/);
- virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace);
+ virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace)
+ REQUIRES(mFlinger->mStateLock);
virtual bool setColorSpaceAgnostic(const bool agnostic);
virtual bool setDimmingEnabled(const bool dimmingEnabled);
virtual bool setFrameRateSelectionPriority(int32_t priority);
@@ -715,13 +716,13 @@
/*
* Remove from current state and mark for removal.
*/
- void removeFromCurrentState();
+ void removeFromCurrentState() REQUIRES(mFlinger->mStateLock);
/*
* called with the state lock from a binder thread when the layer is
* removed from the current list to the pending removal list
*/
- void onRemovedFromCurrentState();
+ void onRemovedFromCurrentState() REQUIRES(mFlinger->mStateLock);
/*
* Called when the layer is added back to the current state list.
@@ -899,6 +900,9 @@
virtual bool simpleBufferUpdate(const layer_state_t&) const { return false; }
+ // Exposed so SurfaceFlinger can assert that it's held
+ const sp<SurfaceFlinger> mFlinger;
+
protected:
friend class impl::SurfaceInterceptor;
@@ -974,9 +978,6 @@
*/
virtual Rect getInputBounds() const;
- // constant
- sp<SurfaceFlinger> mFlinger;
-
bool mPremultipliedAlpha{true};
const std::string mName;
const std::string mTransactionName{"TX - " + mName};
diff --git a/services/surfaceflinger/MutexUtils.h b/services/surfaceflinger/MutexUtils.h
index f8be6f3..58f7cb4 100644
--- a/services/surfaceflinger/MutexUtils.h
+++ b/services/surfaceflinger/MutexUtils.h
@@ -50,4 +50,14 @@
const status_t status;
};
+// Require, under penalty of compilation failure, that the compiler thinks that a mutex is held.
+#define REQUIRE_MUTEX(expr) ([]() REQUIRES(expr) {})()
+
+// Tell the compiler that we know that a mutex is held.
+#define ASSERT_MUTEX(expr) ([]() ASSERT_CAPABILITY(expr) {})()
+
+// Specify that one mutex is an alias for another.
+// (e.g. SurfaceFlinger::mStateLock and Layer::mFlinger->mStateLock)
+#define MUTEX_ALIAS(held, alias) (REQUIRE_MUTEX(held), ASSERT_MUTEX(alias))
+
} // namespace android
diff --git a/services/surfaceflinger/OWNERS b/services/surfaceflinger/OWNERS
index 6011d0d..4e7da82 100644
--- a/services/surfaceflinger/OWNERS
+++ b/services/surfaceflinger/OWNERS
@@ -4,5 +4,7 @@
lpy@google.com
pdwilliams@google.com
racarr@google.com
+ramindani@google.com
+rnlee@google.com
scroggo@google.com
vishnun@google.com
diff --git a/services/surfaceflinger/Scheduler/Android.bp b/services/surfaceflinger/Scheduler/Android.bp
index 5de796d..8df9ba5 100644
--- a/services/surfaceflinger/Scheduler/Android.bp
+++ b/services/surfaceflinger/Scheduler/Android.bp
@@ -57,7 +57,4 @@
"libgtest",
"libscheduler",
],
- sanitize: {
- address: true,
- },
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 866958d..26f8010 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -4227,7 +4227,7 @@
bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelineInfo,
Vector<ComposerState>& states,
- const Vector<DisplayState>& displays, uint32_t flags,
+ Vector<DisplayState>& displays, uint32_t flags,
const InputWindowCommands& inputWindowCommands,
const int64_t desiredPresentTime, bool isAutoTimestamp,
const client_cache_t& uncacheBuffer,
@@ -4236,7 +4236,8 @@
const std::vector<ListenerCallbacks>& listenerCallbacks,
int originPid, int originUid, uint64_t transactionId) {
uint32_t transactionFlags = 0;
- for (const DisplayState& display : displays) {
+ for (DisplayState& display : displays) {
+ display.sanitize(permissions);
transactionFlags |= setDisplayStateLocked(display);
}
@@ -4415,6 +4416,7 @@
}
return 0;
}
+ MUTEX_ALIAS(mStateLock, layer->mFlinger->mStateLock);
// Only set by BLAST adapter layers
if (what & layer_state_t::eProducerDisconnect) {
@@ -7304,6 +7306,7 @@
ALOGD("Layer was destroyed soon after creation %p", state.layer.unsafe_get());
return;
}
+ MUTEX_ALIAS(mStateLock, layer->mFlinger->mStateLock);
sp<Layer> parent;
bool addToRoot = state.addToRoot;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 3e3830d..62ee1b9 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -763,7 +763,7 @@
* Transactions
*/
bool applyTransactionState(const FrameTimelineInfo& info, Vector<ComposerState>& state,
- const Vector<DisplayState>& displays, uint32_t flags,
+ Vector<DisplayState>& displays, uint32_t flags,
const InputWindowCommands& inputWindowCommands,
const int64_t desiredPresentTime, bool isAutoTimestamp,
const client_cache_t& uncacheBuffer, const int64_t postTime,
@@ -859,7 +859,7 @@
// this layer meaning it is entirely safe to destroy all
// resources associated to this layer.
void onHandleDestroyed(BBinder* handle, sp<Layer>& layer);
- void markLayerPendingRemovalLocked(const sp<Layer>& layer);
+ void markLayerPendingRemovalLocked(const sp<Layer>& layer) REQUIRES(mStateLock);
// add a layer to SurfaceFlinger
status_t addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
diff --git a/services/surfaceflinger/TEST_MAPPING b/services/surfaceflinger/TEST_MAPPING
index cab33ae..57752b7 100644
--- a/services/surfaceflinger/TEST_MAPPING
+++ b/services/surfaceflinger/TEST_MAPPING
@@ -5,6 +5,14 @@
},
{
"name": "libcompositionengine_test"
+ },
+ {
+ "name": "libscheduler_test"
+ }
+ ],
+ "hwasan-presubmit": [
+ {
+ "name": "libscheduler_test"
}
]
}
diff --git a/services/surfaceflinger/tests/DisplayConfigs_test.cpp b/services/surfaceflinger/tests/DisplayConfigs_test.cpp
index 2dc96b8..c58fe48 100644
--- a/services/surfaceflinger/tests/DisplayConfigs_test.cpp
+++ b/services/surfaceflinger/tests/DisplayConfigs_test.cpp
@@ -149,4 +149,4 @@
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wextra"
\ No newline at end of file
+#pragma clang diagnostic pop // ignored "-Wextra"
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index e9935e5..c46036a 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -508,7 +508,6 @@
case VK_FORMAT_R8_UNORM:
native_format = android::PIXEL_FORMAT_R_8;
break;
- // TODO: Do we need to query for VK_EXT_rgba10x6_formats here?
case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16:
native_format = android::PIXEL_FORMAT_RGBA_10101010;
break;
@@ -859,9 +858,23 @@
}
}
- // TODO query VK_EXT_rgba10x6_formats support
+ bool rgba10x6_formats_ext = false;
+ uint32_t exts_count;
+ const auto& driver = GetData(pdev).driver;
+ driver.EnumerateDeviceExtensionProperties(pdev, nullptr, &exts_count,
+ nullptr);
+ std::vector<VkExtensionProperties> props(exts_count);
+ driver.EnumerateDeviceExtensionProperties(pdev, nullptr, &exts_count,
+ props.data());
+ for (uint32_t i = 0; i < exts_count; i++) {
+ VkExtensionProperties prop = props[i];
+ if (strcmp(prop.extensionName,
+ VK_EXT_RGBA10X6_FORMATS_EXTENSION_NAME) == 0) {
+ rgba10x6_formats_ext = true;
+ }
+ }
desc.format = AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM;
- if (AHardwareBuffer_isSupported(&desc)) {
+ if (AHardwareBuffer_isSupported(&desc) && rgba10x6_formats_ext) {
all_formats.emplace_back(
VkSurfaceFormatKHR{VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
VK_COLOR_SPACE_SRGB_NONLINEAR_KHR});