Merge "Disable vr_hwc module."
diff --git a/Android.bp b/Android.bp
index 9829c7f..6fe0246 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,3 +1,41 @@
+package {
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+//
+// large-scale-change filtered out the below license kinds as false-positives:
+// SPDX-license-identifier-LGPL
+// SPDX-license-identifier-LGPL-2.1
+// SPDX-license-identifier-LGPL-3.0
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ "SPDX-license-identifier-BSD",
+ "SPDX-license-identifier-MIT",
+ "SPDX-license-identifier-Unicode-DFS",
+ "legacy_notice",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
ndk_headers {
name: "libandroid_headers",
from: "include/android",
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 9cab9b4..16ebf6f 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -5,10 +5,10 @@
# Only turn on clang-format check for the following subfolders.
clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
cmds/idlcli/
+ cmds/servicemanager/
include/input/
libs/binder/fuzzer/
- libs/binder/ndk/
- libs/binder/tests/fuzzers/
+ libs/binder/
libs/binderthreadstate/
libs/graphicsenv/
libs/gui/
diff --git a/cmds/atrace/Android.bp b/cmds/atrace/Android.bp
index e7d0ad0..aa0ef25 100644
--- a/cmds/atrace/Android.bp
+++ b/cmds/atrace/Android.bp
@@ -1,5 +1,22 @@
// Copyright 2012 The Android Open Source Project
+package {
+ default_applicable_licenses: ["frameworks_native_cmds_atrace_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_cmds_atrace_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_binary {
name: "atrace",
srcs: ["atrace.cpp"],
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 2519ffa..88a5872 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -62,7 +62,7 @@
using std::string;
-#define MAX_SYS_FILES 11
+#define MAX_SYS_FILES 12
const char* k_traceTagsProperty = "debug.atrace.tags.enableflags";
const char* k_userInitiatedTraceProperty = "debug.atrace.user_initiated";
@@ -175,6 +175,7 @@
{ OPT, "events/power/suspend_resume/enable" },
{ OPT, "events/cpuhp/cpuhp_enter/enable" },
{ OPT, "events/cpuhp/cpuhp_exit/enable" },
+ { OPT, "events/cpuhp/cpuhp_pause/enable" },
} },
{ "membus", "Memory Bus Utilization", 0, {
{ REQ, "events/memory_bus/enable" },
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index db3a314..37fc9a9 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -37,12 +37,18 @@
chmod 0666 /sys/kernel/tracing/events/sched/sched_process_exit/enable
chmod 0666 /sys/kernel/debug/tracing/events/sched/sched_waking/enable
chmod 0666 /sys/kernel/tracing/events/sched/sched_waking/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/sched/sched_wakeup_new/enable
+ chmod 0666 /sys/kernel/tracing/events/sched/sched_wakeup_new/enable
chmod 0666 /sys/kernel/debug/tracing/events/cgroup/enable
chmod 0666 /sys/kernel/tracing/events/cgroup/enable
chmod 0666 /sys/kernel/debug/tracing/events/power/cpu_frequency/enable
chmod 0666 /sys/kernel/tracing/events/power/cpu_frequency/enable
chmod 0666 /sys/kernel/debug/tracing/events/power/cpu_idle/enable
chmod 0666 /sys/kernel/tracing/events/power/cpu_idle/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/power/clock_enable/enable
+ chmod 0666 /sys/kernel/tracing/events/power/clock_enable/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/power/clock_disable/enable
+ chmod 0666 /sys/kernel/tracing/events/power/clock_disable/enable
chmod 0666 /sys/kernel/debug/tracing/events/power/clock_set_rate/enable
chmod 0666 /sys/kernel/tracing/events/power/clock_set_rate/enable
chmod 0666 /sys/kernel/debug/tracing/events/power/cpu_frequency_limits/enable
@@ -51,6 +57,8 @@
chmod 0666 /sys/kernel/tracing/events/cpuhp/cpuhp_enter/enable
chmod 0666 /sys/kernel/debug/tracing/events/cpuhp/cpuhp_exit/enable
chmod 0666 /sys/kernel/tracing/events/cpuhp/cpuhp_exit/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/cpuhp/cpuhp_pause/enable
+ chmod 0666 /sys/kernel/tracing/events/cpuhp/cpuhp_pause/enable
chmod 0666 /sys/kernel/debug/tracing/events/power/gpu_frequency/enable
chmod 0666 /sys/kernel/tracing/events/power/gpu_frequency/enable
chmod 0666 /sys/kernel/debug/tracing/events/power/suspend_resume/enable
@@ -79,6 +87,8 @@
chmod 0666 /sys/kernel/tracing/events/binder/binder_locked/enable
chmod 0666 /sys/kernel/debug/tracing/events/binder/binder_unlock/enable
chmod 0666 /sys/kernel/tracing/events/binder/binder_unlock/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/binder/binder_set_priority/enable
+ chmod 0666 /sys/kernel/tracing/events/binder/binder_set_priority/enable
chmod 0666 /sys/kernel/debug/tracing/events/i2c/enable
chmod 0666 /sys/kernel/tracing/events/i2c/enable
chmod 0666 /sys/kernel/debug/tracing/events/i2c/i2c_read/enable
@@ -125,12 +135,48 @@
chmod 0666 /sys/kernel/tracing/events/lowmemorykiller/lowmemory_kill/enable
chmod 0666 /sys/kernel/debug/tracing/events/oom/oom_score_adj_update/enable
chmod 0666 /sys/kernel/tracing/events/oom/oom_score_adj_update/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/oom/mark_victim/enable
+ chmod 0666 /sys/kernel/tracing/events/oom/mark_victim/enable
chmod 0666 /sys/kernel/debug/tracing/events/task/task_rename/enable
chmod 0666 /sys/kernel/tracing/events/task/task_rename/enable
chmod 0666 /sys/kernel/debug/tracing/events/task/task_newtask/enable
chmod 0666 /sys/kernel/tracing/events/task/task_newtask/enable
chmod 0666 /sys/kernel/debug/tracing/events/gpu_mem/gpu_mem_total/enable
chmod 0666 /sys/kernel/tracing/events/gpu_mem/gpu_mem_total/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/irq/enable
+ chmod 0666 /sys/kernel/tracing/events/irq/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/irq/irq_handler_entry/enable
+ chmod 0666 /sys/kernel/tracing/events/irq/irq_handler_entry/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/irq/irq_handler_exit/enable
+ chmod 0666 /sys/kernel/tracing/events/irq/irq_handler_exit/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/irq/softirq_entry/enable
+ chmod 0666 /sys/kernel/tracing/events/irq/softirq_entry/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/irq/softirq_exit/enable
+ chmod 0666 /sys/kernel/tracing/events/irq/softirq_exit/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/irq/softirq_raise/enable
+ chmod 0666 /sys/kernel/tracing/events/irq/softirq_raise/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/irq/tasklet_entry/enable
+ chmod 0666 /sys/kernel/tracing/events/irq/tasklet_entry/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/irq/tasklet_exit/enable
+ chmod 0666 /sys/kernel/tracing/events/irq/tasklet_exit/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/irq/tasklet_hi_entry/enable
+ chmod 0666 /sys/kernel/tracing/events/irq/tasklet_hi_entry/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/irq/tasklet_hi_exit/enable
+ chmod 0666 /sys/kernel/tracing/events/irq/tasklet_hi_exit/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/ipi/enable
+ chmod 0666 /sys/kernel/tracing/events/ipi/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/ipi/ipi_entry/enable
+ chmod 0666 /sys/kernel/tracing/events/ipi/ipi_entry/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/ipi/ipi_exit/enable
+ chmod 0666 /sys/kernel/tracing/events/ipi/ipi_exit/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/ipi/ipi_raise/enable
+ chmod 0666 /sys/kernel/tracing/events/ipi/ipi_raise/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/clk/clk_enable/enable
+ chmod 0666 /sys/kernel/tracing/events/clk/clk_disable/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/clk/clk_disable/enable
+ chmod 0666 /sys/kernel/tracing/events/clk/clk_enable/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/clk/clk_set_rate/enable
+ chmod 0666 /sys/kernel/tracing/events/clk/clk_set_rate/enable
# disk
chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_get_data_block/enable
diff --git a/cmds/atrace/atrace_userdebug.rc b/cmds/atrace/atrace_userdebug.rc
index 6c86c21..9186514 100644
--- a/cmds/atrace/atrace_userdebug.rc
+++ b/cmds/atrace/atrace_userdebug.rc
@@ -18,8 +18,3 @@
chmod 0666 /sys/kernel/tracing/events/filemap/enable
chmod 0666 /sys/kernel/debug/tracing/events/filemap/enable
- # irq
- chmod 0666 /sys/kernel/tracing/events/irq/enable
- chmod 0666 /sys/kernel/debug/tracing/events/irq/enable
- chmod 0666 /sys/kernel/tracing/events/ipi/enable
- chmod 0666 /sys/kernel/debug/tracing/events/ipi/enable
diff --git a/cmds/bugreport/Android.bp b/cmds/bugreport/Android.bp
index 24044a6..8262aed 100644
--- a/cmds/bugreport/Android.bp
+++ b/cmds/bugreport/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "bugreport",
srcs: ["bugreport.cpp"],
diff --git a/cmds/bugreport/OWNERS b/cmds/bugreport/OWNERS
index 1ba7cff..2a9b681 100644
--- a/cmds/bugreport/OWNERS
+++ b/cmds/bugreport/OWNERS
@@ -1,6 +1,4 @@
set noparent
-felipeal@google.com
nandana@google.com
jsharkey@android.com
-enh@google.com
diff --git a/cmds/bugreportz/Android.bp b/cmds/bugreportz/Android.bp
index 924a3a3..332f858 100644
--- a/cmds/bugreportz/Android.bp
+++ b/cmds/bugreportz/Android.bp
@@ -1,5 +1,14 @@
// bugreportz
// ==========
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "bugreportz",
diff --git a/cmds/bugreportz/OWNERS b/cmds/bugreportz/OWNERS
index 1ba7cff..2a9b681 100644
--- a/cmds/bugreportz/OWNERS
+++ b/cmds/bugreportz/OWNERS
@@ -1,6 +1,4 @@
set noparent
-felipeal@google.com
nandana@google.com
jsharkey@android.com
-enh@google.com
diff --git a/cmds/cmd/Android.bp b/cmds/cmd/Android.bp
index 8ea71cd..c900a24 100644
--- a/cmds/cmd/Android.bp
+++ b/cmds/cmd/Android.bp
@@ -1,3 +1,20 @@
+package {
+ default_applicable_licenses: ["frameworks_native_cmds_cmd_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_cmds_cmd_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_static {
name: "libcmd",
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index 80d14ac..f48f1fb 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -13,6 +13,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "dumpstate_cflag_defaults",
cflags: [
@@ -112,6 +121,7 @@
],
required: [
"atrace",
+ "dmabuf_dump",
"ip",
"iptables",
"librank",
diff --git a/cmds/dumpstate/DumpPool.cpp b/cmds/dumpstate/DumpPool.cpp
index e15ac3f..c2c8a72 100644
--- a/cmds/dumpstate/DumpPool.cpp
+++ b/cmds/dumpstate/DumpPool.cpp
@@ -64,8 +64,8 @@
if (shutdown_ || threads_.empty()) {
return;
}
- while (!tasks_.empty()) tasks_.pop();
futures_map_.clear();
+ while (!tasks_.empty()) tasks_.pop();
shutdown_ = true;
condition_variable_.notify_all();
diff --git a/cmds/dumpstate/OWNERS b/cmds/dumpstate/OWNERS
index 1ba7cff..2a9b681 100644
--- a/cmds/dumpstate/OWNERS
+++ b/cmds/dumpstate/OWNERS
@@ -1,6 +1,4 @@
set noparent
-felipeal@google.com
nandana@google.com
jsharkey@android.com
-enh@google.com
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index fbb0a18..8fd05fb 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1208,10 +1208,6 @@
static void DumpPacketStats() {
DumpFile("NETWORK DEV INFO", "/proc/net/dev");
- DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
- DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
- DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
- DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
}
static void DumpIpAddrAndRules() {
@@ -1656,8 +1652,6 @@
for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
- /* Dump Bluetooth HCI logs */
- ds.AddDir("/data/misc/bluetooth/logs", true);
/* Dump Nfc NCI logs */
ds.AddDir("/data/misc/nfc/logs", true);
@@ -1743,6 +1737,9 @@
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
+ /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
+ ds.AddDir("/data/misc/bluetooth/logs", true);
+
if (ds.dump_pool_) {
WAIT_TASK_WITH_CONSENT_CHECK(DUMP_CHECKINS_TASK, ds.dump_pool_);
} else {
@@ -1845,10 +1842,8 @@
RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
// Gather shared memory buffer info if the product implements it
- struct stat st;
- if (!stat("/product/bin/dmabuf_dump", &st)) {
- RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
- }
+ RunCommand("Dmabuf dump", {"dmabuf_dump"});
+ RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
DumpFile("PSI cpu", "/proc/pressure/cpu");
DumpFile("PSI memory", "/proc/pressure/memory");
@@ -2061,7 +2056,7 @@
}
Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
- const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
+ const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
const size_t buf_size = temp_file_pattern.length() + 1;
std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
@@ -2913,6 +2908,10 @@
// own activity pushes out interesting data from the trace ring buffer.
// The trace file is added to the zip by MaybeAddSystemTraceToZip().
MaybeSnapshotSystemTrace();
+
+ // If a winscope trace is running, snapshot it now. It will be pulled into bugreport later
+ // from WMTRACE_DATA_DIR.
+ MaybeSnapshotWinTrace();
}
onUiIntensiveBugreportDumpsFinished(calling_uid);
MaybeCheckUserConsent(calling_uid, calling_package);
@@ -3024,6 +3023,17 @@
// file in the later stages.
}
+void Dumpstate::MaybeSnapshotWinTrace() {
+ // Currently WindowManagerService and InputMethodManagerSerivice support WinScope protocol.
+ for (const auto& service : {"window", "input_method"}) {
+ RunCommand(
+ // Empty name because it's not intended to be classified as a bugreport section.
+ // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
+ "", {"cmd", service, "tracing", "save-for-bugreport"},
+ CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
+ }
+}
+
void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
if (calling_uid == AID_SHELL || !CalledByApi()) {
return;
@@ -3068,6 +3078,9 @@
android::os::UnlinkAndLogOnError(tmp_path_);
android::os::UnlinkAndLogOnError(screenshot_path_);
android::os::UnlinkAndLogOnError(path_);
+ if (dump_traces_path != nullptr) {
+ android::os::UnlinkAndLogOnError(dump_traces_path);
+ }
}
void Dumpstate::EnableParallelRunIfNeeded() {
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index f83968b..83e6787 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -549,6 +549,7 @@
void MaybeTakeEarlyScreenshot();
void MaybeSnapshotSystemTrace();
+ void MaybeSnapshotWinTrace();
void onUiIntensiveBugreportDumpsFinished(int32_t calling_uid);
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index c62d302..0712c0a 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -411,7 +411,6 @@
}
TEST_F(BugreportSectionTest, ConnectivitySectionsGenerated) {
- SectionExists("HIGH connectivity", /* bytes= */ 3000);
SectionExists("connectivity", /* bytes= */ 5000);
}
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index b2518ad..2c573e4 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -1762,6 +1762,27 @@
EXPECT_THAT(getTempFileCounts(kTestDataPath), Eq(0));
}
+TEST_F(DumpPoolTest, Shutdown_withoutCrash) {
+ bool run_1 = false;
+ auto dump_func_1 = [&]() {
+ run_1 = true;
+ };
+ auto dump_func = []() {
+ sleep(1);
+ };
+
+ dump_pool_->start(/* thread_counts = */1);
+ dump_pool_->enqueueTask(/* task_name = */"1", dump_func_1);
+ dump_pool_->enqueueTask(/* task_name = */"2", dump_func);
+ dump_pool_->enqueueTask(/* task_name = */"3", dump_func);
+ dump_pool_->enqueueTask(/* task_name = */"4", dump_func);
+ dump_pool_->waitForTask("1", "", out_fd_.get());
+ dump_pool_->shutdown();
+
+ EXPECT_TRUE(run_1);
+ EXPECT_THAT(getTempFileCounts(kTestDataPath), Eq(0));
+}
+
class TaskQueueTest : public DumpstateBaseTest {
public:
void SetUp() {
diff --git a/cmds/dumpsys/Android.bp b/cmds/dumpsys/Android.bp
index f99588f..91aa018 100644
--- a/cmds/dumpsys/Android.bp
+++ b/cmds/dumpsys/Android.bp
@@ -1,3 +1,20 @@
+package {
+ default_applicable_licenses: ["frameworks_native_cmds_dumpsys_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_cmds_dumpsys_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_defaults {
name: "dumpsys_defaults",
diff --git a/cmds/dumpsys/OWNERS b/cmds/dumpsys/OWNERS
index 1ba7cff..2a9b681 100644
--- a/cmds/dumpsys/OWNERS
+++ b/cmds/dumpsys/OWNERS
@@ -1,6 +1,4 @@
set noparent
-felipeal@google.com
nandana@google.com
jsharkey@android.com
-enh@google.com
diff --git a/cmds/dumpsys/tests/Android.bp b/cmds/dumpsys/tests/Android.bp
index e182b9d..6854c75 100644
--- a/cmds/dumpsys/tests/Android.bp
+++ b/cmds/dumpsys/tests/Android.bp
@@ -1,4 +1,13 @@
// Build the unit tests for dumpsys
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_cmds_dumpsys_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_cmds_dumpsys_license"],
+}
+
cc_test {
name: "dumpsys_test",
test_suites: ["device-tests"],
diff --git a/cmds/flatland/Android.mk b/cmds/flatland/Android.mk
index 7aa111c..754a99c 100644
--- a/cmds/flatland/Android.mk
+++ b/cmds/flatland/Android.mk
@@ -11,6 +11,9 @@
LOCAL_CFLAGS := -Wall -Werror
LOCAL_MODULE:= flatland
+LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS:= notice
+LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/../../NOTICE
LOCAL_MODULE_TAGS := tests
diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp
index 402767a..99e0f4c 100644
--- a/cmds/idlcli/Android.bp
+++ b/cmds/idlcli/Android.bp
@@ -12,10 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "idlcli-defaults",
shared_libs: [
- "android.hardware.vibrator-ndk_platform",
+ "android.hardware.vibrator-V1-ndk_platform",
"android.hardware.vibrator@1.0",
"android.hardware.vibrator@1.1",
"android.hardware.vibrator@1.2",
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index 523115f..d09d3e8 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "installd_defaults",
@@ -38,6 +47,9 @@
"libutils",
"server_configurable_flags",
],
+ export_shared_lib_headers: [
+ "libbinder",
+ ],
product_variables: {
arc: {
@@ -177,8 +189,8 @@
"liblog",
"libutils",
],
- static_libs: [
- "libapexd",
+ required: [
+ "apexd"
],
}
diff --git a/cmds/installd/QuotaUtils.cpp b/cmds/installd/QuotaUtils.cpp
index e080291..6027139 100644
--- a/cmds/installd/QuotaUtils.cpp
+++ b/cmds/installd/QuotaUtils.cpp
@@ -35,7 +35,7 @@
/* Map of all quota mounts from target to source */
std::unordered_map<std::string, std::string> mQuotaReverseMounts;
-std::string& FindQuotaDeviceForUuid(const std::string& uuid) {
+std::string FindQuotaDeviceForUuid(const std::string& uuid) {
std::lock_guard<std::recursive_mutex> lock(mMountsLock);
auto path = create_data_path(uuid.empty() ? nullptr : uuid.c_str());
return mQuotaReverseMounts[path];
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 4dfd1d0..0cf50a3 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -2112,8 +2112,9 @@
{
struct stat s;
if (stat(b_path.c_str(), &s) != 0) {
- // Silently ignore for now. The service calling this isn't smart enough to understand
- // lack of artifacts at the moment.
+ // Ignore for now. The service calling this isn't smart enough to
+ // understand lack of artifacts at the moment.
+ LOG(VERBOSE) << "A/B artifact " << b_path << " does not exist!";
return false;
}
if (!S_ISREG(s.st_mode)) {
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 443821c..ed31ad9 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -175,8 +175,10 @@
private:
bool ReadSystemProperties() {
+ // TODO This file does not have a stable format. It should be read by
+ // code shared by init and otapreopt. See b/181182967#comment80
static constexpr const char* kPropertyFiles[] = {
- "/default.prop", "/system/build.prop"
+ "/system/build.prop"
};
for (size_t i = 0; i < arraysize(kPropertyFiles); ++i) {
@@ -193,28 +195,38 @@
// export NAME VALUE
// For simplicity, don't respect string quotation. The values we are interested in can be
// encoded without them.
+ // init.environ.rc and etc/classpath have the same format for
+ // environment variable exports and can be matched by the same regex.
+ // TODO Just like with the system-properties above we really should have
+ // common code between init and otapreopt to deal with reading these
+ // things. See b/181182967
+ static constexpr const char* kEnvironmentVariableSources[] = {
+ "/init.environ.rc", "/etc/classpath"
+ };
+
std::regex export_regex("\\s*export\\s+(\\S+)\\s+(\\S+)");
- bool parse_result = ParseFile("/init.environ.rc", [&](const std::string& line) {
- std::smatch export_match;
- if (!std::regex_match(line, export_match, export_regex)) {
+ for (const char* env_vars_file : kEnvironmentVariableSources) {
+ bool parse_result = ParseFile(env_vars_file, [&](const std::string& line) {
+ std::smatch export_match;
+ if (!std::regex_match(line, export_match, export_regex)) {
+ return true;
+ }
+
+ if (export_match.size() != 3) {
+ return true;
+ }
+
+ std::string name = export_match[1].str();
+ std::string value = export_match[2].str();
+
+ system_properties_.SetProperty(name, value);
+
return true;
+ });
+ if (!parse_result) {
+ return false;
}
-
- if (export_match.size() != 3) {
- return true;
- }
-
- std::string name = export_match[1].str();
- std::string value = export_match[2].str();
-
- system_properties_.SetProperty(name, value);
-
- return true;
- });
- if (!parse_result) {
- return false;
}
-
if (system_properties_.GetProperty(kAndroidDataPathPropertyName) == nullptr) {
return false;
}
@@ -337,9 +349,6 @@
}
}
- // Clear cached artifacts.
- ClearDirectory(isa_path);
-
// Check whether we have a boot image.
// TODO: check that the files are correct wrt/ jars.
std::string preopted_boot_art_path =
@@ -383,37 +392,6 @@
return false;
}
- static void ClearDirectory(const std::string& dir) {
- DIR* c_dir = opendir(dir.c_str());
- if (c_dir == nullptr) {
- PLOG(WARNING) << "Unable to open " << dir << " to delete it's contents";
- return;
- }
-
- for (struct dirent* de = readdir(c_dir); de != nullptr; de = readdir(c_dir)) {
- const char* name = de->d_name;
- if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
- continue;
- }
- // We only want to delete regular files and symbolic links.
- std::string file = StringPrintf("%s/%s", dir.c_str(), name);
- if (de->d_type != DT_REG && de->d_type != DT_LNK) {
- LOG(WARNING) << "Unexpected file "
- << file
- << " of type "
- << std::hex
- << de->d_type
- << " encountered.";
- } else {
- // Try to unlink the file.
- if (unlink(file.c_str()) != 0) {
- PLOG(ERROR) << "Unable to unlink " << file;
- }
- }
- }
- CHECK_EQ(0, closedir(c_dir)) << "Unable to close directory.";
- }
-
static const char* ParseNull(const char* arg) {
return (strcmp(arg, "!") == 0) ? nullptr : arg;
}
@@ -473,24 +451,29 @@
// Run dexopt with the parameters of parameters_.
// TODO(calin): embed the profile name in the parameters.
int Dexopt() {
- std::string dummy;
- return dexopt(parameters_.apk_path,
- parameters_.uid,
- parameters_.pkgName,
- parameters_.instruction_set,
- parameters_.dexopt_needed,
- parameters_.oat_dir,
- parameters_.dexopt_flags,
- parameters_.compiler_filter,
- parameters_.volume_uuid,
- parameters_.shared_libraries,
- parameters_.se_info,
- parameters_.downgrade,
- parameters_.target_sdk_version,
- parameters_.profile_name,
- parameters_.dex_metadata_path,
- parameters_.compilation_reason,
- &dummy);
+ std::string error;
+ int res = dexopt(parameters_.apk_path,
+ parameters_.uid,
+ parameters_.pkgName,
+ parameters_.instruction_set,
+ parameters_.dexopt_needed,
+ parameters_.oat_dir,
+ parameters_.dexopt_flags,
+ parameters_.compiler_filter,
+ parameters_.volume_uuid,
+ parameters_.shared_libraries,
+ parameters_.se_info,
+ parameters_.downgrade,
+ parameters_.target_sdk_version,
+ parameters_.profile_name,
+ parameters_.dex_metadata_path,
+ parameters_.compilation_reason,
+ &error);
+ if (res != 0) {
+ LOG(ERROR) << "During preopt of " << parameters_.apk_path << " got result " << res
+ << " error: " << error;
+ }
+ return res;
}
int RunPreopt() {
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index 72c03bf..c04b558 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -20,16 +20,18 @@
#include <sys/stat.h>
#include <sys/wait.h>
+#include <array>
+#include <fstream>
#include <sstream>
+#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/macros.h>
#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
#include <libdm/dm.h>
#include <selinux/android.h>
-#include <apexd.h>
-
#include "installd_constants.h"
#include "otapreopt_utils.h"
@@ -59,28 +61,14 @@
}
}
-static std::vector<apex::ApexFile> ActivateApexPackages() {
- // The logic here is (partially) copied and adapted from
- // system/apex/apexd/apexd.cpp.
- //
- // Only scan the APEX directory under /system, /system_ext and /vendor (within the chroot dir).
- std::vector<const char*> apex_dirs{apex::kApexPackageSystemDir, apex::kApexPackageSystemExtDir,
- apex::kApexPackageVendorDir};
- for (const auto& dir : apex_dirs) {
- // Cast call to void to suppress warn_unused_result.
- static_cast<void>(apex::ScanPackagesDirAndActivate(dir));
- }
- return apex::GetActivePackages();
-}
+static void ActivateApexPackages() {
+ std::vector<std::string> apexd_cmd{"/system/bin/apexd", "--otachroot-bootstrap"};
+ std::string apexd_error_msg;
-static void DeactivateApexPackages(const std::vector<apex::ApexFile>& active_packages) {
- for (const apex::ApexFile& apex_file : active_packages) {
- const std::string& package_path = apex_file.GetPath();
- base::Result<void> status = apex::DeactivatePackage(package_path);
- if (!status.ok()) {
- LOG(ERROR) << "Failed to deactivate " << package_path << ": "
- << status.error();
- }
+ bool exec_result = Exec(apexd_cmd, &apexd_error_msg);
+ if (!exec_result) {
+ PLOG(ERROR) << "Running otapreopt failed: " << apexd_error_msg;
+ exit(220);
}
}
@@ -181,6 +169,13 @@
// want it for product APKs. Same notes as vendor above.
TryExtraMount("product", arg[2], "/postinstall/product");
+ constexpr const char* kPostInstallLinkerconfig = "/postinstall/linkerconfig";
+ // Try to mount /postinstall/linkerconfig. we will set it up after performing the chroot
+ if (mount("tmpfs", kPostInstallLinkerconfig, "tmpfs", 0, nullptr) != 0) {
+ PLOG(ERROR) << "Failed to mount a tmpfs for " << kPostInstallLinkerconfig;
+ exit(215);
+ }
+
// Setup APEX mount point and its security context.
static constexpr const char* kPostinstallApexDir = "/postinstall/apex";
// The following logic is similar to the one in system/core/rootdir/init.rc:
@@ -238,18 +233,48 @@
// Try to mount APEX packages in "/apex" in the chroot dir. We need at least
// the ART APEX, as it is required by otapreopt to run dex2oat.
- std::vector<apex::ApexFile> active_packages = ActivateApexPackages();
+ ActivateApexPackages();
// Check that an ART APEX has been activated; clean up and exit
// early otherwise.
- if (std::none_of(active_packages.begin(),
- active_packages.end(),
- [](const apex::ApexFile& package){
- return package.GetManifest().name() == "com.android.art";
- })) {
- LOG(FATAL_WITHOUT_ABORT) << "No activated com.android.art APEX package.";
- DeactivateApexPackages(active_packages);
- exit(217);
+ static constexpr const std::string_view kRequiredApexs[] = {
+ "com.android.art",
+ "com.android.runtime",
+ };
+ std::array<bool, arraysize(kRequiredApexs)> found_apexs{ false, false };
+ DIR* apex_dir = opendir("/apex");
+ if (apex_dir == nullptr) {
+ PLOG(ERROR) << "unable to open /apex";
+ exit(220);
+ }
+ for (dirent* entry = readdir(apex_dir); entry != nullptr; entry = readdir(apex_dir)) {
+ for (int i = 0; i < found_apexs.size(); i++) {
+ if (kRequiredApexs[i] == std::string_view(entry->d_name)) {
+ found_apexs[i] = true;
+ break;
+ }
+ }
+ }
+ closedir(apex_dir);
+ auto it = std::find(found_apexs.cbegin(), found_apexs.cend(), false);
+ if (it != found_apexs.cend()) {
+ LOG(ERROR) << "No activated " << kRequiredApexs[std::distance(found_apexs.cbegin(), it)]
+ << " package!";
+ exit(221);
+ }
+
+ // Setup /linkerconfig. Doing it after the chroot means it doesn't need its own category
+ if (selinux_android_restorecon("/linkerconfig", 0) < 0) {
+ PLOG(ERROR) << "Failed to restorecon /linkerconfig";
+ exit(219);
+ }
+ std::vector<std::string> linkerconfig_cmd{"/apex/com.android.runtime/bin/linkerconfig",
+ "--target", "/linkerconfig"};
+ std::string linkerconfig_error_msg;
+ bool linkerconfig_exec_result = Exec(linkerconfig_cmd, &linkerconfig_error_msg);
+ if (!linkerconfig_exec_result) {
+ LOG(ERROR) << "Running linkerconfig failed: " << linkerconfig_error_msg;
+ exit(218);
}
// Now go on and run otapreopt.
@@ -272,9 +297,6 @@
LOG(ERROR) << "Running otapreopt failed: " << error_msg;
}
- // Tear down the work down by the apexd logic. (i.e. deactivate packages).
- DeactivateApexPackages(active_packages);
-
if (!exec_result) {
exit(213);
}
diff --git a/cmds/installd/run_dex2oat.cpp b/cmds/installd/run_dex2oat.cpp
index 17ea903..a27fd10 100644
--- a/cmds/installd/run_dex2oat.cpp
+++ b/cmds/installd/run_dex2oat.cpp
@@ -86,7 +86,7 @@
bool generate_compact_dex,
bool use_jitzygote_image,
const char* compilation_reason) {
- PrepareBootImageAndBootClasspathFlags(use_jitzygote_image);
+ PrepareBootImageFlags(use_jitzygote_image);
PrepareInputFileFlags(output_oat, output_vdex, output_image, input_dex, input_vdex,
dex_metadata, profile, swap_fd, class_loader_context,
@@ -112,7 +112,7 @@
RunDex2Oat::~RunDex2Oat() {}
-void RunDex2Oat::PrepareBootImageAndBootClasspathFlags(bool use_jitzygote_image) {
+void RunDex2Oat::PrepareBootImageFlags(bool use_jitzygote_image) {
std::string boot_image;
if (use_jitzygote_image) {
boot_image = StringPrintf("--boot-image=%s", kJitZygoteImage);
@@ -120,23 +120,6 @@
boot_image = MapPropertyToArg("dalvik.vm.boot-image", "--boot-image=%s");
}
AddArg(boot_image);
-
- // If DEX2OATBOOTCLASSPATH is not in the environment, dex2oat is going to query
- // BOOTCLASSPATH.
- char* dex2oat_bootclasspath = getenv("DEX2OATBOOTCLASSPATH");
- if (dex2oat_bootclasspath != nullptr) {
- AddRuntimeArg(StringPrintf("-Xbootclasspath:%s", dex2oat_bootclasspath));
- }
-
- std::string updatable_bcp_packages =
- MapPropertyToArg("dalvik.vm.dex2oat-updatable-bcp-packages-file",
- "--updatable-bcp-packages-file=%s");
- if (updatable_bcp_packages.empty()) {
- // Make dex2oat fail by providing non-existent file name.
- updatable_bcp_packages =
- "--updatable-bcp-packages-file=/nonx/updatable-bcp-packages.txt";
- }
- AddArg(updatable_bcp_packages);
}
void RunDex2Oat::PrepareInputFileFlags(const UniqueFile& output_oat,
diff --git a/cmds/installd/run_dex2oat.h b/cmds/installd/run_dex2oat.h
index 325a3a2..475e124 100644
--- a/cmds/installd/run_dex2oat.h
+++ b/cmds/installd/run_dex2oat.h
@@ -56,7 +56,7 @@
void Exec(int exit_code);
protected:
- void PrepareBootImageAndBootClasspathFlags(bool use_jitzygote_image);
+ void PrepareBootImageFlags(bool use_jitzygote_image);
void PrepareInputFileFlags(const UniqueFile& output_oat,
const UniqueFile& output_vdex,
const UniqueFile& output_image,
diff --git a/cmds/installd/run_dex2oat_test.cpp b/cmds/installd/run_dex2oat_test.cpp
index 3813cf7..0a638cd 100644
--- a/cmds/installd/run_dex2oat_test.cpp
+++ b/cmds/installd/run_dex2oat_test.cpp
@@ -175,8 +175,6 @@
default_expected_flags_["--swap-fd"] = FLAG_UNUSED;
default_expected_flags_["--class-loader-context"] = FLAG_UNUSED;
default_expected_flags_["--class-loader-context-fds"] = FLAG_UNUSED;
- default_expected_flags_["--updatable-bcp-packages-file"] =
- "=/nonx/updatable-bcp-packages.txt";
// Arch
default_expected_flags_["--instruction-set"] = "=arm64";
@@ -320,28 +318,6 @@
VerifyExpectedFlags();
}
-TEST_F(RunDex2OatTest, DEX2OATBOOTCLASSPATH) {
- ASSERT_EQ(nullptr, getenv("DEX2OATBOOTCLASSPATH"));
- ASSERT_EQ(0, setenv("DEX2OATBOOTCLASSPATH", "foobar", /*override=*/ false))
- << "Failed to setenv: " << strerror(errno);
-
- CallRunDex2Oat(RunDex2OatArgs::MakeDefaultTestArgs());
-
- SetExpectedFlagUsed("-Xbootclasspath", ":foobar");
- VerifyExpectedFlags();
-
- ASSERT_EQ(0, unsetenv("DEX2OATBOOTCLASSPATH"))
- << "Failed to setenv: " << strerror(errno);
-}
-
-TEST_F(RunDex2OatTest, UpdatableBootClassPath) {
- setSystemProperty("dalvik.vm.dex2oat-updatable-bcp-packages-file", "/path/to/file");
- CallRunDex2Oat(RunDex2OatArgs::MakeDefaultTestArgs());
-
- SetExpectedFlagUsed("--updatable-bcp-packages-file", "=/path/to/file");
- VerifyExpectedFlags();
-}
-
TEST_F(RunDex2OatTest, DoNotGenerateCompactDex) {
auto args = RunDex2OatArgs::MakeDefaultTestArgs();
args->generate_compact_dex = false;
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index 7c9e3b2..f67ab81 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -1,4 +1,13 @@
// Build the unit tests for installd
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "installd_utils_test",
test_suites: ["device-tests"],
@@ -157,4 +166,3 @@
"libotapreoptparameters"
],
}
-
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index fbf1e0c..e272025 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -351,7 +351,7 @@
uid = kTestAppUid;
}
if (class_loader_context == nullptr) {
- class_loader_context = "&";
+ class_loader_context = "PCL[]";
}
int32_t dexopt_needed = 0; // does not matter;
std::optional<std::string> out_path; // does not matter
@@ -478,7 +478,7 @@
bool should_binder_call_succeed,
/*out */ binder::Status* binder_result) {
std::optional<std::string> out_path = oat_dir ? std::make_optional<std::string>(oat_dir) : std::nullopt;
- std::string class_loader_context = "&";
+ std::string class_loader_context = "PCL[]";
int32_t target_sdk_version = 0; // default
std::string profile_name = "primary.prof";
std::optional<std::string> dm_path_opt = dm_path ? std::make_optional<std::string>(dm_path) : std::nullopt;
diff --git a/cmds/ip-up-vpn/Android.mk b/cmds/ip-up-vpn/Android.mk
index e1e2204..396ae9d 100644
--- a/cmds/ip-up-vpn/Android.mk
+++ b/cmds/ip-up-vpn/Android.mk
@@ -21,6 +21,9 @@
LOCAL_CFLAGS := -Wall -Werror
LOCAL_SHARED_LIBRARIES := libcutils liblog
LOCAL_MODULE := ip-up-vpn
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/ppp
LOCAL_MODULE_TAGS := optional
diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp
index 0cbb80f..649e53a 100644
--- a/cmds/lshal/Android.bp
+++ b/cmds/lshal/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "liblshal",
shared_libs: [
diff --git a/cmds/lshal/DebugCommand.cpp b/cmds/lshal/DebugCommand.cpp
index 72958bd..ccf1ab1 100644
--- a/cmds/lshal/DebugCommand.cpp
+++ b/cmds/lshal/DebugCommand.cpp
@@ -28,7 +28,7 @@
}
std::string DebugCommand::getSimpleDescription() const {
- return "Debug a specified HAL.";
+ return "Debug a specified HIDL HAL.";
}
Status DebugCommand::parseArgs(const Arg &arg) {
@@ -78,7 +78,7 @@
"debug:\n"
" lshal debug [-E] <interface> [options [options [...]]] \n"
" Print debug information of a specified interface.\n"
- " -E: excludes debug output if HAL is actually a subclass.\n"
+ " -E: excludes debug output if HIDL HAL is actually a subclass.\n"
" <interface>: Format is `android.hardware.foo@1.0::IFoo/default`.\n"
" If instance name is missing `default` is used.\n"
" options: space separated options to IBase::debug.\n";
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index 22268ac..d5110f6 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -81,7 +81,7 @@
return "list";
}
std::string ListCommand::getSimpleDescription() const {
- return "List HALs.";
+ return "List HIDL HALs.";
}
std::string ListCommand::parseCmdline(pid_t pid) const {
@@ -295,21 +295,21 @@
}
mServicesTable.setDescription(
- "| All binderized services (registered with hwservicemanager)");
+ "| All HIDL binderized services (registered with hwservicemanager)");
mPassthroughRefTable.setDescription(
- "| All interfaces that getService() has ever returned as a passthrough interface;\n"
+ "| All HIDL interfaces getService() has ever returned as a passthrough interface;\n"
"| PIDs / processes shown below might be inaccurate because the process\n"
"| might have relinquished the interface or might have died.\n"
"| The Server / Server CMD column can be ignored.\n"
"| The Clients / Clients CMD column shows all process that have ever dlopen'ed \n"
"| the library and successfully fetched the passthrough implementation.");
mImplementationsTable.setDescription(
- "| All available passthrough implementations (all -impl.so files).\n"
+ "| All available HIDL passthrough implementations (all -impl.so files).\n"
"| These may return subclasses through their respective HIDL_FETCH_I* functions.");
mManifestHalsTable.setDescription(
- "| All HALs that are in VINTF manifest.");
+ "| All HIDL HALs that are in VINTF manifest.");
mLazyHalsTable.setDescription(
- "| All HALs that are declared in VINTF manifest:\n"
+ "| All HIDL HALs that are declared in VINTF manifest:\n"
"| - as hwbinder HALs but are not registered to hwservicemanager, and\n"
"| - as hwbinder/passthrough HALs with no implementation.");
}
@@ -903,11 +903,11 @@
thiz->mSelectedColumns.push_back(TableColumnType::VINTF);
return OK;
}, "print VINTF info. This column contains a comma-separated list of:\n"
- " - DM: if the HAL is in the device manifest\n"
- " - DC: if the HAL is in the device compatibility matrix\n"
- " - FM: if the HAL is in the framework manifest\n"
- " - FC: if the HAL is in the framework compatibility matrix\n"
- " - X: if the HAL is in none of the above lists"});
+ " - DM: if the HIDL HAL is in the device manifest\n"
+ " - DC: if the HIDL HAL is in the device compatibility matrix\n"
+ " - FM: if the HIDL HAL is in the framework manifest\n"
+ " - FC: if the HIDL HAL is in the framework compatibility matrix\n"
+ " - X: if the HIDL HAL is in none of the above lists"});
mOptions.push_back({'S', "service-status", no_argument, v++, [](ListCommand* thiz, const char*) {
thiz->mSelectedColumns.push_back(TableColumnType::SERVICE_STATUS);
return OK;
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 99cb93a..bc99f4d 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -59,7 +59,8 @@
}
void Lshal::usage() {
- err() << "lshal: List and debug HALs." << std::endl << std::endl
+ err() << "lshal: List and debug HIDL HALs." << std::endl
+ << " (for AIDL HALs, see `dumpsys`)" << std::endl << std::endl
<< "commands:" << std::endl;
size_t nameMaxLength = 0;
diff --git a/cmds/lshal/WaitCommand.cpp b/cmds/lshal/WaitCommand.cpp
index 65b41b9..437a66a 100644
--- a/cmds/lshal/WaitCommand.cpp
+++ b/cmds/lshal/WaitCommand.cpp
@@ -29,7 +29,7 @@
}
std::string WaitCommand::getSimpleDescription() const {
- return "Wait for HAL to start if it is not already started.";
+ return "Wait for HIDL HAL to start if it is not already started.";
}
Status WaitCommand::parseArgs(const Arg &arg) {
diff --git a/cmds/lshal/libprocpartition/Android.bp b/cmds/lshal/libprocpartition/Android.bp
index 9592111..cbfbdc9 100644
--- a/cmds/lshal/libprocpartition/Android.bp
+++ b/cmds/lshal/libprocpartition/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "libprocpartition",
shared_libs: [
diff --git a/cmds/rawbu/Android.bp b/cmds/rawbu/Android.bp
index 363ffc1..e34119d 100644
--- a/cmds/rawbu/Android.bp
+++ b/cmds/rawbu/Android.bp
@@ -1,5 +1,22 @@
// Copyright 2009 The Android Open Source Project
+package {
+ default_applicable_licenses: ["frameworks_native_cmds_rawbu_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_cmds_rawbu_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_binary {
name: "rawbu",
diff --git a/cmds/rss_hwm_reset/Android.bp b/cmds/rss_hwm_reset/Android.bp
index 15f10ef..cd335d4 100644
--- a/cmds/rss_hwm_reset/Android.bp
+++ b/cmds/rss_hwm_reset/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "rss_hwm_reset",
diff --git a/cmds/service/Android.bp b/cmds/service/Android.bp
index a5b1ac5..3e8e3f6 100644
--- a/cmds/service/Android.bp
+++ b/cmds/service/Android.bp
@@ -1,3 +1,20 @@
+package {
+ default_applicable_licenses: ["frameworks_native_cmds_service_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_cmds_service_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_binary {
name: "service",
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index b139251..9de344a 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "servicemanager_defaults",
diff --git a/cmds/surfacereplayer/Android.bp b/cmds/surfacereplayer/Android.bp
index d4c037a..34fc8b1 100644
--- a/cmds/surfacereplayer/Android.bp
+++ b/cmds/surfacereplayer/Android.bp
@@ -1,4 +1,13 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
subdirs = [
"proto",
"replayer",
-]
\ No newline at end of file
+]
diff --git a/cmds/surfacereplayer/proto/Android.bp b/cmds/surfacereplayer/proto/Android.bp
index 71a5e23..dae976e 100644
--- a/cmds/surfacereplayer/proto/Android.bp
+++ b/cmds/surfacereplayer/proto/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "libtrace_proto",
srcs: [
diff --git a/cmds/surfacereplayer/replayer/Android.bp b/cmds/surfacereplayer/replayer/Android.bp
index 7632311..3985230 100644
--- a/cmds/surfacereplayer/replayer/Android.bp
+++ b/cmds/surfacereplayer/replayer/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libsurfacereplayer",
srcs: [
diff --git a/data/etc/android.hardware.keystore.app_attest_key.xml b/data/etc/android.hardware.keystore.app_attest_key.xml
new file mode 100644
index 0000000..8adc439
--- /dev/null
+++ b/data/etc/android.hardware.keystore.app_attest_key.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Feature for devices that support app attestation keys (i.e. KeyMint 1.0). -->
+<permissions>
+ <feature name="android.hardware.keystore.app_attest_key" />
+</permissions>
diff --git a/data/etc/android.hardware.keystore.limited_use_key.xml b/data/etc/android.hardware.keystore.limited_use_key.xml
new file mode 100644
index 0000000..5217086
--- /dev/null
+++ b/data/etc/android.hardware.keystore.limited_use_key.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Feature for devices with KeyMint that can enforce limited use key
+ in hardware with any max usage count (including count equals to 1). -->
+<permissions>
+ <feature name="android.hardware.keystore.limited_use_key" />
+</permissions>
\ No newline at end of file
diff --git a/data/etc/android.hardware.keystore.single_use_key.xml b/data/etc/android.hardware.keystore.single_use_key.xml
new file mode 100644
index 0000000..40e80aa
--- /dev/null
+++ b/data/etc/android.hardware.keystore.single_use_key.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Feature for devices with KeyMint that only can enforce limited use key
+ in hardware with max usage count equals to 1. -->
+<permissions>
+ <feature name="android.hardware.keystore.single_use_key" />
+</permissions>
\ No newline at end of file
diff --git a/data/etc/android.hardware.telephony.ims.singlereg.xml b/data/etc/android.hardware.telephony.ims.singlereg.xml
new file mode 100644
index 0000000..9a6cec0
--- /dev/null
+++ b/data/etc/android.hardware.telephony.ims.singlereg.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Feature for devices that have an IMS service that supports all IMS
+ applications using a single IMS registration. -->
+<permissions>
+ <feature name="android.hardware.telephony.ims" />
+ <feature name="android.hardware.telephony.ims.singlereg" />
+</permissions>
diff --git a/headers/Android.bp b/headers/Android.bp
index 8f41c2b..7481a23 100644
--- a/headers/Android.bp
+++ b/headers/Android.bp
@@ -1,3 +1,13 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "media_plugin_headers",
vendor_available: true,
diff --git a/include/OWNERS b/include/OWNERS
index db52850..c98e87a 100644
--- a/include/OWNERS
+++ b/include/OWNERS
@@ -1,3 +1,4 @@
+alecmouri@google.com
alexeykuzmin@google.com
dangittik@google.com
jreck@google.com
@@ -8,7 +9,6 @@
racarr@google.com
romainguy@android.com
santoscordon@google.com
-stoza@google.com
svv@google.com
# For multinetwork.h only.
diff --git a/include/android/bitmap.h b/include/android/bitmap.h
index f195399..a70dffd 100644
--- a/include/android/bitmap.h
+++ b/include/android/bitmap.h
@@ -28,8 +28,13 @@
#include <stdbool.h>
#include <stdint.h>
+#include <stddef.h>
#include <jni.h>
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -117,8 +122,6 @@
int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
AndroidBitmapInfo* info);
-#if __ANDROID_API__ >= 30
-
/**
* Given a java bitmap object, return its {@link ADataSpace}.
*
@@ -130,8 +133,6 @@
*/
int32_t AndroidBitmap_getDataSpace(JNIEnv* env, jobject jbitmap) __INTRODUCED_IN(30);
-#endif // __ANDROID_API__ >= 30
-
/**
* Given a java bitmap object, attempt to lock the pixel address.
* Locking will ensure that the memory for the pixels will not move
@@ -152,8 +153,6 @@
*/
int AndroidBitmap_unlockPixels(JNIEnv* env, jobject jbitmap);
-#if __ANDROID_API__ >= 30
-
// Note: these values match android.graphics.Bitmap#compressFormat.
/**
@@ -254,8 +253,6 @@
int AndroidBitmap_getHardwareBuffer(JNIEnv* env, jobject bitmap,
AHardwareBuffer** outBuffer) __INTRODUCED_IN(30);
-#endif // __ANDROID_API__ >= 30
-
#ifdef __cplusplus
}
#endif
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
index e9f559c..8039bb0 100644
--- a/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -61,8 +61,6 @@
*/
typedef void (*AChoreographer_refreshRateCallback)(int64_t vsyncPeriodNanos, void* data);
-#if __ANDROID_API__ >= 24
-
/**
* Get the AChoreographer instance for the current thread. This must be called
* on an ALooper thread.
@@ -86,10 +84,6 @@
long delayMillis) __INTRODUCED_IN(24)
__DEPRECATED_IN(29);
-#endif /* __ANDROID_API__ >= 24 */
-
-#if __ANDROID_API__ >= 29
-
/**
* Power a callback to be run on the next frame. The data pointer provided will
* be passed to the callback function when it's called.
@@ -111,10 +105,6 @@
AChoreographer_frameCallback64 callback, void* data,
uint32_t delayMillis) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
-
-#if __ANDROID_API__ >= 30
-
/**
* Registers a callback to be run when the display refresh rate changes. The
* data pointer provided will be passed to the callback function when it's
@@ -160,7 +150,6 @@
void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer,
AChoreographer_refreshRateCallback, void* data)
__INTRODUCED_IN(30);
-#endif /* __ANDROID_API__ >= 30 */
__END_DECLS
diff --git a/include/android/configuration.h b/include/android/configuration.h
index ccf3e59..88019ae 100644
--- a/include/android/configuration.h
+++ b/include/android/configuration.h
@@ -645,14 +645,12 @@
*/
void AConfiguration_setScreenLong(AConfiguration* config, int32_t screenLong);
-#if __ANDROID_API__ >= 30
/**
* Return the current ACONFIGURATION_SCREENROUND_* set in the configuration.
*
* Available since API level 30.
*/
int32_t AConfiguration_getScreenRound(AConfiguration* config) __INTRODUCED_IN(30);
-#endif
/**
* Set the current screen round in the configuration.
@@ -712,7 +710,6 @@
*/
void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value);
-#if __ANDROID_API__ >= 17
/**
* Return the configuration's layout direction, or
* ACONFIGURATION_LAYOUTDIR_ANY if not set.
@@ -727,7 +724,6 @@
* Available since API level 17.
*/
void AConfiguration_setLayoutDirection(AConfiguration* config, int32_t value) __INTRODUCED_IN(17);
-#endif /* __ANDROID_API__ >= 17 */
/**
* Perform a diff between two configurations. Returns a bit mask of
diff --git a/include/android/font.h b/include/android/font.h
index 1618096..a172618 100644
--- a/include/android/font.h
+++ b/include/android/font.h
@@ -51,8 +51,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
-
enum {
/** The minimum value fot the font weight value. */
AFONT_WEIGHT_MIN = 0,
@@ -297,8 +295,6 @@
float AFont_getAxisValue(const AFont* _Nonnull font, uint32_t axisIndex)
__INTRODUCED_IN(29);
-#endif // __ANDROID_API__ >= 29
-
__END_DECLS
#endif // ANDROID_FONT_H
diff --git a/include/android/font_matcher.h b/include/android/font_matcher.h
index d4bd892..49e478c 100644
--- a/include/android/font_matcher.h
+++ b/include/android/font_matcher.h
@@ -97,8 +97,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
-
enum {
/** A family variant value for the system default variant. */
AFAMILY_VARIANT_DEFAULT = 0,
@@ -217,8 +215,6 @@
const uint32_t textLength,
uint32_t* _Nullable runLengthOut) __INTRODUCED_IN(29);
-#endif // __ANDROID_API__ >= 29
-
__END_DECLS
#endif // ANDROID_FONT_MATCHER_H
diff --git a/include/android/imagedecoder.h b/include/android/imagedecoder.h
index d7e6e41..1298c62 100644
--- a/include/android/imagedecoder.h
+++ b/include/android/imagedecoder.h
@@ -51,14 +51,16 @@
#include <android/rect.h>
#include <stdint.h>
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
struct AAsset;
-#if __ANDROID_API__ >= 30
-
/**
* {@link AImageDecoder} functions result code. Many functions will return one of these
* to indicate success ({@link ANDROID_IMAGE_DECODER_SUCCESS}) or the reason
@@ -527,8 +529,6 @@
void* pixels, size_t stride,
size_t size) __INTRODUCED_IN(30);
-#endif // __ANDROID_API__ >= 30
-
#ifdef __cplusplus
}
#endif
diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h
index c6d1c94..424299d 100644
--- a/include/android/multinetwork.h
+++ b/include/android/multinetwork.h
@@ -60,8 +60,6 @@
* on failure with an appropriate errno value set.
*/
-#if __ANDROID_API__ >= 23
-
/**
* Set the network to be used by the given socket file descriptor.
*
@@ -111,10 +109,6 @@
const char *node, const char *service,
const struct addrinfo *hints, struct addrinfo **res) __INTRODUCED_IN(23);
-#endif /* __ANDROID_API__ >= 23 */
-
-#if __ANDROID_API__ >= 29
-
/**
* Possible values of the flags argument to android_res_nsend and android_res_nquery.
* Values are ORed together.
@@ -187,8 +181,6 @@
*/
void android_res_cancel(int nsend_fd) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
-
__END_DECLS
#endif // ANDROID_MULTINETWORK_H
diff --git a/include/android/native_window_jni.h b/include/android/native_window_jni.h
index 3a77ffe..071ec79 100644
--- a/include/android/native_window_jni.h
+++ b/include/android/native_window_jni.h
@@ -44,7 +44,6 @@
*/
ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface);
-#if __ANDROID_API__ >= 26
/**
* Return a Java Surface object derived from the ANativeWindow, for interacting
* with it through Java code. The returned Java object acquires a reference on
@@ -55,7 +54,6 @@
* Available since API level 26.
*/
jobject ANativeWindow_toSurface(JNIEnv* env, ANativeWindow* window) __INTRODUCED_IN(26);
-#endif
#ifdef __cplusplus
};
diff --git a/include/android/sensor.h b/include/android/sensor.h
index eb40779..6447844 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -52,6 +52,13 @@
#include <math.h>
#include <stdint.h>
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
+#endif
+#if !defined(__DEPRECATED_IN)
+#define __DEPRECATED_IN(__api_level) __attribute__((__deprecated__))
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -553,13 +560,8 @@
* ASensorManager* sensorManager = ASensorManager_getInstance();
*
*/
-#if __ANDROID_API__ >= 26
-__attribute__ ((deprecated)) ASensorManager* ASensorManager_getInstance();
-#else
-ASensorManager* ASensorManager_getInstance();
-#endif
+ASensorManager* ASensorManager_getInstance() __DEPRECATED_IN(26);
-#if __ANDROID_API__ >= 26
/**
* Get a reference to the sensor manager. ASensorManager is a singleton
* per package as different packages may have access to different sensors.
@@ -571,7 +573,6 @@
* Available since API level 26.
*/
ASensorManager* ASensorManager_getInstanceForPackage(const char* packageName) __INTRODUCED_IN(26);
-#endif
/**
* Returns the list of available sensors.
@@ -584,7 +585,6 @@
*/
ASensor const* ASensorManager_getDefaultSensor(ASensorManager* manager, int type);
-#if __ANDROID_API__ >= 21
/**
* Returns the default sensor with the given type and wakeUp properties or NULL if no sensor
* of this type and wakeUp properties exists.
@@ -592,7 +592,6 @@
* Available since API level 21.
*/
ASensor const* ASensorManager_getDefaultSensorEx(ASensorManager* manager, int type, bool wakeUp) __INTRODUCED_IN(21);
-#endif
/**
* Creates a new sensor event queue and associate it with a looper.
@@ -609,7 +608,6 @@
*/
int ASensorManager_destroyEventQueue(ASensorManager* manager, ASensorEventQueue* queue);
-#if __ANDROID_API__ >= 26
/**
* Create direct channel based on shared memory
*
@@ -706,7 +704,6 @@
*/
int ASensorManager_configureDirectReport(ASensorManager* manager,
ASensor const* sensor, int channelId, int rate) __INTRODUCED_IN(26);
-#endif /* __ANDROID_API__ >= 26 */
/*****************************************************************************/
@@ -795,7 +792,6 @@
*/
ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue, ASensorEvent* events, size_t count);
-#if __ANDROID_API__ >= 29
/**
* Request that {@link ASENSOR_TYPE_ADDITIONAL_INFO} events to be delivered on
* the given {@link ASensorEventQueue}.
@@ -819,7 +815,6 @@
* \return 0 on success or a negative error code on failure
*/
int ASensorEventQueue_requestAdditionalInfoEvents(ASensorEventQueue* queue, bool enable) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
/*****************************************************************************/
@@ -850,7 +845,6 @@
*/
int ASensor_getMinDelay(ASensor const* sensor);
-#if __ANDROID_API__ >= 21
/**
* Returns the maximum size of batches for this sensor. Batches will often be
* smaller, as the hardware fifo might be used for other sensors.
@@ -886,9 +880,7 @@
* Available since API level 21.
*/
bool ASensor_isWakeUpSensor(ASensor const* sensor) __INTRODUCED_IN(21);
-#endif /* __ANDROID_API__ >= 21 */
-#if __ANDROID_API__ >= 26
/**
* Test if sensor supports a certain type of direct channel.
*
@@ -914,9 +906,7 @@
* does not support direct report.
*/
int ASensor_getHighestDirectReportRateLevel(ASensor const* sensor) __INTRODUCED_IN(26);
-#endif /* __ANDROID_API__ >= 26 */
-#if __ANDROID_API__ >= 29
/**
* Returns the sensor's handle.
*
@@ -934,7 +924,6 @@
* Available since API level 29.
*/
int ASensor_getHandle(ASensor const* sensor) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
#ifdef __cplusplus
};
diff --git a/include/android/sharedmem.h b/include/android/sharedmem.h
index 5f74682..7994aa9 100644
--- a/include/android/sharedmem.h
+++ b/include/android/sharedmem.h
@@ -50,8 +50,6 @@
extern "C" {
#endif
-#if __ANDROID_API__ >= 26
-
/**
* Create a shared memory region.
*
@@ -121,8 +119,6 @@
*/
int ASharedMemory_setProt(int fd, int prot) __INTRODUCED_IN(26);
-#endif // __ANDROID_API__ >= 26
-
#ifdef __cplusplus
};
#endif
diff --git a/include/android/sharedmem_jni.h b/include/android/sharedmem_jni.h
index 13e56e6..bbac785 100644
--- a/include/android/sharedmem_jni.h
+++ b/include/android/sharedmem_jni.h
@@ -52,8 +52,6 @@
extern "C" {
#endif
-#if __ANDROID_API__ >= 27
-
/**
* Returns a dup'd FD from the given Java android.os.SharedMemory object. The returned file
* descriptor has all the same properties & capabilities as the FD returned from
@@ -72,8 +70,6 @@
*/
int ASharedMemory_dupFromJava(JNIEnv* env, jobject sharedMemory) __INTRODUCED_IN(27);
-#endif // __ANDROID_API__ >= 27
-
#ifdef __cplusplus
};
#endif
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index cbcf6ec..27b880d 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -35,8 +35,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
-
struct ASurfaceControl;
/**
@@ -405,10 +403,6 @@
struct AHdrMetadata_cta861_3* metadata)
__INTRODUCED_IN(29);
-#endif // __ANDROID_API__ >= 29
-
-#if __ANDROID_API__ >= 30
-
/**
* Sets the intended frame rate for |surface_control|.
*
@@ -435,8 +429,6 @@
ASurfaceControl* surface_control, float frameRate,
int8_t compatibility) __INTRODUCED_IN(30);
-#endif // __ANDROID_API__ >= 30
-
__END_DECLS
#endif // ANDROID_SURFACE_CONTROL_H
diff --git a/include/android/surface_texture.h b/include/android/surface_texture.h
index dde7eaa..b227b32 100644
--- a/include/android/surface_texture.h
+++ b/include/android/surface_texture.h
@@ -59,8 +59,6 @@
*/
typedef struct ASurfaceTexture ASurfaceTexture;
-#if __ANDROID_API__ >= 28
-
/**
* Release the reference to the native ASurfaceTexture acquired with
* ASurfaceTexture_fromSurfaceTexture().
@@ -175,8 +173,6 @@
*/
int64_t ASurfaceTexture_getTimestamp(ASurfaceTexture* st) __INTRODUCED_IN(28);
-#endif /* __ANDROID_API__ >= 28 */
-
__END_DECLS
#endif /* ANDROID_NATIVE_SURFACE_TEXTURE_H */
diff --git a/include/android/surface_texture_jni.h b/include/android/surface_texture_jni.h
index 2266d54..e40686d 100644
--- a/include/android/surface_texture_jni.h
+++ b/include/android/surface_texture_jni.h
@@ -32,8 +32,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 28
-
/**
* Get a reference to the native ASurfaceTexture from the corresponding java object.
*
@@ -52,8 +50,6 @@
*/
ASurfaceTexture* ASurfaceTexture_fromSurfaceTexture(JNIEnv* env, jobject surfacetexture) __INTRODUCED_IN(28);
-#endif
-
__END_DECLS
#endif /* ANDROID_NATIVE_SURFACE_TEXTURE_JNI_H */
diff --git a/include/android/system_fonts.h b/include/android/system_fonts.h
index 6fd7d2c..b0bbb95 100644
--- a/include/android/system_fonts.h
+++ b/include/android/system_fonts.h
@@ -87,8 +87,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
-
/**
* ASystemFontIterator provides access to the system font configuration.
*
@@ -128,8 +126,6 @@
*/
AFont* _Nullable ASystemFontIterator_next(ASystemFontIterator* _Nonnull iterator) __INTRODUCED_IN(29);
-#endif // __ANDROID_API__ >= 29
-
__END_DECLS
#endif // ANDROID_SYSTEM_FONTS_H
diff --git a/include/android/thermal.h b/include/android/thermal.h
index 83582d6..6ec68d9 100644
--- a/include/android/thermal.h
+++ b/include/android/thermal.h
@@ -53,7 +53,7 @@
#include <sys/types.h>
#if !defined(__INTRODUCED_IN)
-#define __INTRODUCED_IN(30) /* Introduced in API level 30 */
+#define __INTRODUCED_IN(__api_level) /* nothing */
#endif
#ifdef __cplusplus
@@ -109,8 +109,6 @@
*/
typedef void (*AThermal_StatusCallback)(void *data, AThermalStatus status);
-#if __ANDROID_API__ >= 30
-
/**
* Acquire an instance of the thermal manager. This must be freed using
* {@link AThermal_releaseManager}.
@@ -179,8 +177,6 @@
int AThermal_unregisterThermalStatusListener(AThermalManager *manager,
AThermal_StatusCallback callback, void *data) __INTRODUCED_IN(30);
-#endif // __ANDROID_API__ >= 30
-
#ifdef __cplusplus
}
#endif
diff --git a/include/android/trace.h b/include/android/trace.h
index dbad6f6..dcefffb 100644
--- a/include/android/trace.h
+++ b/include/android/trace.h
@@ -40,8 +40,6 @@
extern "C" {
#endif
-#if __ANDROID_API__ >= 23
-
/**
* Returns true if tracing is enabled. Use this to avoid expensive computation only necessary
* when tracing is enabled.
@@ -72,10 +70,6 @@
*/
void ATrace_endSection() __INTRODUCED_IN(23);
-#endif /* __ANDROID_API__ >= 23 */
-
-#if __ANDROID_API__ >= 29
-
/**
* Writes a trace message to indicate that a given section of code has
* begun. Must be followed by a call to {@link ATrace_endAsyncSection} with the same
@@ -112,8 +106,6 @@
*/
void ATrace_setCounter(const char* counterName, int64_t counterValue) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
-
#ifdef __cplusplus
}
#endif
diff --git a/libs/adbd_auth/Android.bp b/libs/adbd_auth/Android.bp
index 8883c04..16cded8 100644
--- a/libs/adbd_auth/Android.bp
+++ b/libs/adbd_auth/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library {
name: "libadbd_auth",
cflags: [
diff --git a/libs/adbd_auth/include/adbd_auth.h b/libs/adbd_auth/include/adbd_auth.h
index 8f834df..1dcf540 100644
--- a/libs/adbd_auth/include/adbd_auth.h
+++ b/libs/adbd_auth/include/adbd_auth.h
@@ -26,7 +26,6 @@
#endif
__BEGIN_DECLS
-#if !defined(__ANDROID__) || __ANDROID_API__ >= 30
// The transport type of the device connection.
enum AdbTransportType : int32_t {
@@ -186,5 +185,4 @@
*/
bool adbd_auth_supports_feature(AdbdAuthFeature feature);
-#endif //!__ANDROID__ || __ANDROID_API__ >= 30
__END_DECLS
diff --git a/libs/android_runtime_lazy/Android.bp b/libs/android_runtime_lazy/Android.bp
index cdd7764..b74923c 100644
--- a/libs/android_runtime_lazy/Android.bp
+++ b/libs/android_runtime_lazy/Android.bp
@@ -30,6 +30,15 @@
// instead of libandroid_runtime. When they are used by a vendor process,
// depending on libandroid_runtime is meaningless. In this case,
// they can depend on libandroid_runtime_lazy.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library {
name: "libandroid_runtime_lazy",
vendor_available: true,
diff --git a/libs/arect/Android.bp b/libs/arect/Android.bp
index 80aa891..bb40f51 100644
--- a/libs/arect/Android.bp
+++ b/libs/arect/Android.bp
@@ -12,6 +12,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_applicable_licenses: ["frameworks_native_libs_arect_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_libs_arect_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
ndk_headers {
name: "libarect_headers_for_ndk",
from: "include/android",
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index ed079db..cdc90fb 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "libbinder_headers",
export_include_dirs: ["include"],
@@ -22,14 +31,21 @@
header_libs: [
"libbase_headers",
+ "libbinder_headers_platform_shared",
"libcutils_headers",
"libutils_headers",
],
export_header_lib_headers: [
"libbase_headers",
+ "libbinder_headers_platform_shared",
"libcutils_headers",
"libutils_headers",
],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media",
+ "com.android.media.swcodec",
+ ],
min_sdk_version: "29",
target: {
darwin: {
@@ -42,14 +58,13 @@
// transport itself and should be moved to AIDL or in domain-specific libs.
//
// Currently, these are only on system android (not vendor, not host)
+// TODO(b/183654927) - move these into separate libraries
libbinder_device_interface_sources = [
"ActivityManager.cpp",
"AppOpsManager.cpp",
"IActivityManager.cpp",
"IAppOpsCallback.cpp",
"IAppOpsService.cpp",
- "IBatteryStats.cpp",
- "IMediaResourceMonitor.cpp",
"IPermissionController.cpp",
"IProcessInfoService.cpp",
"IUidObserver.cpp",
@@ -57,6 +72,7 @@
"PermissionController.cpp",
"ProcessInfoService.cpp",
"IpPrefix.cpp",
+ ":activity_manager_procstate_aidl",
]
cc_library {
@@ -108,11 +124,16 @@
"ParcelFileDescriptor.cpp",
"PersistableBundle.cpp",
"ProcessState.cpp",
+ "RpcAddress.cpp",
+ "RpcConnection.cpp",
+ "RpcServer.cpp",
+ "RpcState.cpp",
"Static.cpp",
"Stability.cpp",
"Status.cpp",
"TextOutput.cpp",
"Utils.cpp",
+ ":packagemanager_aidl",
":libbinder_aidl",
],
@@ -200,17 +221,20 @@
"-misc-redundant-expression",
"-misc-unused-using-decls",
"performance*",
+ "-performance-no-int-to-ptr",
"portability*",
],
+
+ pgo: {
+ sampling: true,
+ profile_file: "libbinder/libbinder.profdata",
+ },
}
// AIDL interface between libbinder and framework.jar
filegroup {
name: "libbinder_aidl",
srcs: [
- "aidl/android/content/pm/IPackageChangeObserver.aidl",
- "aidl/android/content/pm/IPackageManagerNative.aidl",
- "aidl/android/content/pm/PackageChangeEvent.aidl",
"aidl/android/os/IClientCallback.aidl",
"aidl/android/os/IServiceCallback.aidl",
"aidl/android/os/IServiceManager.aidl",
@@ -219,6 +243,16 @@
path: "aidl",
}
+filegroup {
+ name: "packagemanager_aidl",
+ srcs: [
+ "aidl/android/content/pm/IPackageChangeObserver.aidl",
+ "aidl/android/content/pm/IPackageManagerNative.aidl",
+ "aidl/android/content/pm/PackageChangeEvent.aidl",
+ ],
+ path: "aidl",
+}
+
aidl_interface {
name: "libbinder_aidl_test_stub",
unstable: true,
@@ -231,3 +265,23 @@
},
},
}
+
+// libbinder historically contained additional interfaces that provided specific
+// functionality in the platform but have nothing to do with binder itself. These
+// are moved out of libbinder in order to avoid the overhead of their vtables.
+// If you are working on or own one of these interfaces, the responsible things
+// to would be:
+// - give them a new home
+// - convert them to AIDL instead of having manually written parceling code
+
+cc_library {
+ name: "libbatterystats_aidl",
+ srcs: [
+ "IBatteryStats.cpp",
+ ],
+ export_include_dirs: ["include_batterystats"],
+ shared_libs: [
+ "libbinder",
+ "libutils",
+ ],
+}
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index bf4387a..53b36ff 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -21,6 +21,7 @@
#include <binder/IPCThreadState.h>
#include <binder/IResultReceiver.h>
+#include <binder/RpcConnection.h>
#include <binder/Stability.h>
#include <cutils/compiler.h>
#include <utils/Log.h>
@@ -133,25 +134,56 @@
}
sTrackingMap[trackedUid]++;
}
- return new BpBinder(handle, trackedUid);
+ return new BpBinder(BinderHandle{handle}, trackedUid);
}
-BpBinder::BpBinder(int32_t handle, int32_t trackedUid)
- : mStability(0)
- , mHandle(handle)
- , mAlive(1)
- , mObitsSent(0)
- , mObituaries(nullptr)
- , mTrackedUid(trackedUid)
-{
- ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);
+BpBinder* BpBinder::create(const sp<RpcConnection>& connection, const RpcAddress& address) {
+ LOG_ALWAYS_FATAL_IF(connection == nullptr, "BpBinder::create null connection");
+ // These are not currently tracked, since there is no UID or other
+ // identifier to track them with. However, if similar functionality is
+ // needed, connection objects keep track of all BpBinder objects on a
+ // per-connection basis.
+
+ return new BpBinder(SocketHandle{connection, address});
+}
+
+BpBinder::BpBinder(Handle&& handle)
+ : mStability(0),
+ mHandle(handle),
+ mAlive(true),
+ mObitsSent(false),
+ mObituaries(nullptr),
+ mTrackedUid(-1) {
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
- IPCThreadState::self()->incWeakHandle(handle, this);
}
-int32_t BpBinder::handle() const {
- return mHandle;
+BpBinder::BpBinder(BinderHandle&& handle, int32_t trackedUid) : BpBinder(Handle(handle)) {
+ mTrackedUid = trackedUid;
+
+ ALOGV("Creating BpBinder %p handle %d\n", this, this->binderHandle());
+
+ IPCThreadState::self()->incWeakHandle(this->binderHandle(), this);
+}
+
+BpBinder::BpBinder(SocketHandle&& handle) : BpBinder(Handle(handle)) {
+ LOG_ALWAYS_FATAL_IF(rpcConnection() == nullptr, "BpBinder created w/o connection object");
+}
+
+bool BpBinder::isRpcBinder() const {
+ return std::holds_alternative<SocketHandle>(mHandle);
+}
+
+const RpcAddress& BpBinder::rpcAddress() const {
+ return std::get<SocketHandle>(mHandle).address;
+}
+
+const sp<RpcConnection>& BpBinder::rpcConnection() const {
+ return std::get<SocketHandle>(mHandle).connection;
+}
+
+int32_t BpBinder::binderHandle() const {
+ return std::get<BinderHandle>(mHandle).handle;
}
bool BpBinder::isDescriptorCached() const {
@@ -162,10 +194,13 @@
const String16& BpBinder::getInterfaceDescriptor() const
{
if (isDescriptorCached() == false) {
- Parcel send, reply;
+ sp<BpBinder> thiz = const_cast<BpBinder*>(this);
+
+ Parcel data;
+ data.markForBinder(thiz);
+ Parcel reply;
// do the IPC without a lock held.
- status_t err = const_cast<BpBinder*>(this)->transact(
- INTERFACE_TRANSACTION, send, &reply);
+ status_t err = thiz->transact(INTERFACE_TRANSACTION, data, &reply);
if (err == NO_ERROR) {
String16 res(reply.readString16());
Mutex::Autolock _l(mLock);
@@ -190,9 +225,10 @@
status_t BpBinder::pingBinder()
{
- Parcel send;
+ Parcel data;
+ data.markForBinder(this);
Parcel reply;
- return transact(PING_TRANSACTION, send, &reply);
+ return transact(PING_TRANSACTION, data, &reply);
}
status_t BpBinder::dump(int fd, const Vector<String16>& args)
@@ -228,15 +264,21 @@
: Stability::getLocalLevel();
if (CC_UNLIKELY(!Stability::check(category, required))) {
- ALOGE("Cannot do a user transaction on a %s binder in a %s context.",
+ ALOGE("Cannot do a user transaction on a %s binder (%s) in a %s context.",
category.debugString().c_str(),
+ String8(getInterfaceDescriptor()).c_str(),
Stability::levelString(required).c_str());
return BAD_TYPE;
}
}
- status_t status = IPCThreadState::self()->transact(
- mHandle, code, data, reply, flags);
+ status_t status;
+ if (CC_UNLIKELY(isRpcBinder())) {
+ status = rpcConnection()->transact(rpcAddress(), code, data, reply, flags);
+ } else {
+ status = IPCThreadState::self()->transact(binderHandle(), code, data, reply, flags);
+ }
+
if (status == DEAD_OBJECT) mAlive = 0;
return status;
@@ -249,6 +291,8 @@
status_t BpBinder::linkToDeath(
const sp<DeathRecipient>& recipient, void* cookie, uint32_t flags)
{
+ if (isRpcBinder()) return UNKNOWN_TRANSACTION;
+
Obituary ob;
ob.recipient = recipient;
ob.cookie = cookie;
@@ -266,10 +310,10 @@
if (!mObituaries) {
return NO_MEMORY;
}
- ALOGV("Requesting death notification: %p handle %d\n", this, mHandle);
+ ALOGV("Requesting death notification: %p handle %d\n", this, binderHandle());
getWeakRefs()->incWeak(this);
IPCThreadState* self = IPCThreadState::self();
- self->requestDeathNotification(mHandle, this);
+ self->requestDeathNotification(binderHandle(), this);
self->flushCommands();
}
ssize_t res = mObituaries->add(ob);
@@ -285,6 +329,8 @@
const wp<DeathRecipient>& recipient, void* cookie, uint32_t flags,
wp<DeathRecipient>* outRecipient)
{
+ if (isRpcBinder()) return UNKNOWN_TRANSACTION;
+
AutoMutex _l(mLock);
if (mObitsSent) {
@@ -302,9 +348,9 @@
}
mObituaries->removeAt(i);
if (mObituaries->size() == 0) {
- ALOGV("Clearing death notification: %p handle %d\n", this, mHandle);
+ ALOGV("Clearing death notification: %p handle %d\n", this, binderHandle());
IPCThreadState* self = IPCThreadState::self();
- self->clearDeathNotification(mHandle, this);
+ self->clearDeathNotification(binderHandle(), this);
self->flushCommands();
delete mObituaries;
mObituaries = nullptr;
@@ -318,8 +364,10 @@
void BpBinder::sendObituary()
{
- ALOGV("Sending obituary for proxy %p handle %d, mObitsSent=%s\n",
- this, mHandle, mObitsSent ? "true" : "false");
+ LOG_ALWAYS_FATAL_IF(isRpcBinder(), "Cannot send obituary for remote binder.");
+
+ ALOGV("Sending obituary for proxy %p handle %d, mObitsSent=%s\n", this, binderHandle(),
+ mObitsSent ? "true" : "false");
mAlive = 0;
if (mObitsSent) return;
@@ -327,9 +375,9 @@
mLock.lock();
Vector<Obituary>* obits = mObituaries;
if(obits != nullptr) {
- ALOGV("Clearing sent death notification: %p handle %d\n", this, mHandle);
+ ALOGV("Clearing sent death notification: %p handle %d\n", this, binderHandle());
IPCThreadState* self = IPCThreadState::self();
- self->clearDeathNotification(mHandle, this);
+ self->clearDeathNotification(binderHandle(), this);
self->flushCommands();
mObituaries = nullptr;
}
@@ -387,7 +435,9 @@
BpBinder::~BpBinder()
{
- ALOGV("Destroying BpBinder %p handle %d\n", this, mHandle);
+ ALOGV("Destroying BpBinder %p handle %d\n", this, binderHandle());
+
+ if (CC_UNLIKELY(isRpcBinder())) return;
IPCThreadState* ipc = IPCThreadState::self();
@@ -395,7 +445,8 @@
AutoMutex _l(sTrackingLock);
uint32_t trackedValue = sTrackingMap[mTrackedUid];
if (CC_UNLIKELY((trackedValue & COUNTING_VALUE_MASK) == 0)) {
- ALOGE("Unexpected Binder Proxy tracking decrement in %p handle %d\n", this, mHandle);
+ ALOGE("Unexpected Binder Proxy tracking decrement in %p handle %d\n", this,
+ binderHandle());
} else {
if (CC_UNLIKELY(
(trackedValue & LIMIT_REACHED_MASK) &&
@@ -412,26 +463,31 @@
}
if (ipc) {
- ipc->expungeHandle(mHandle, this);
- ipc->decWeakHandle(mHandle);
+ ipc->expungeHandle(binderHandle(), this);
+ ipc->decWeakHandle(binderHandle());
}
}
void BpBinder::onFirstRef()
{
- ALOGV("onFirstRef BpBinder %p handle %d\n", this, mHandle);
+ ALOGV("onFirstRef BpBinder %p handle %d\n", this, binderHandle());
+ if (CC_UNLIKELY(isRpcBinder())) return;
IPCThreadState* ipc = IPCThreadState::self();
- if (ipc) ipc->incStrongHandle(mHandle, this);
+ if (ipc) ipc->incStrongHandle(binderHandle(), this);
}
void BpBinder::onLastStrongRef(const void* /*id*/)
{
- ALOGV("onLastStrongRef BpBinder %p handle %d\n", this, mHandle);
+ ALOGV("onLastStrongRef BpBinder %p handle %d\n", this, binderHandle());
+ if (CC_UNLIKELY(isRpcBinder())) {
+ (void)rpcConnection()->sendDecStrong(rpcAddress());
+ return;
+ }
IF_ALOGV() {
printRefs();
}
IPCThreadState* ipc = IPCThreadState::self();
- if (ipc) ipc->decStrongHandle(mHandle);
+ if (ipc) ipc->decStrongHandle(binderHandle());
mLock.lock();
Vector<Obituary>* obits = mObituaries;
@@ -441,7 +497,7 @@
mDescriptorCache.size() ? String8(mDescriptorCache).c_str() : "<uncached descriptor>");
}
- if (ipc) ipc->clearDeathNotification(mHandle, this);
+ if (ipc) ipc->clearDeathNotification(binderHandle(), this);
mObituaries = nullptr;
}
mLock.unlock();
@@ -456,9 +512,12 @@
bool BpBinder::onIncStrongAttempted(uint32_t /*flags*/, const void* /*id*/)
{
- ALOGV("onIncStrongAttempted BpBinder %p handle %d\n", this, mHandle);
+ // RPC binder doesn't currently support inc from weak binders
+ if (CC_UNLIKELY(isRpcBinder())) return false;
+
+ ALOGV("onIncStrongAttempted BpBinder %p handle %d\n", this, binderHandle());
IPCThreadState* ipc = IPCThreadState::self();
- return ipc ? ipc->attemptIncStrongHandle(mHandle) == NO_ERROR : false;
+ return ipc ? ipc->attemptIncStrongHandle(binderHandle()) == NO_ERROR : false;
}
uint32_t BpBinder::getBinderProxyCount(uint32_t uid)
diff --git a/libs/binder/BufferedTextOutput.cpp b/libs/binder/BufferedTextOutput.cpp
index 88c85bf..349658e 100644
--- a/libs/binder/BufferedTextOutput.cpp
+++ b/libs/binder/BufferedTextOutput.cpp
@@ -15,7 +15,6 @@
*/
#include "BufferedTextOutput.h"
-#include <binder/Debug.h>
#include <cutils/atomic.h>
#include <utils/Log.h>
@@ -26,6 +25,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include "Debug.h"
#include "Static.h"
// ---------------------------------------------------------------------------
diff --git a/libs/binder/Debug.cpp b/libs/binder/Debug.cpp
index 3a62059..8676955 100644
--- a/libs/binder/Debug.cpp
+++ b/libs/binder/Debug.cpp
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#include <binder/Debug.h>
+#include "Debug.h"
+
#include <binder/ProcessState.h>
#include <utils/misc.h>
@@ -25,6 +26,22 @@
namespace android {
+std::string hexString(const void* bytes, size_t len) {
+ if (bytes == nullptr) return "<null>";
+
+ const uint8_t* bytes8 = static_cast<const uint8_t*>(bytes);
+ const char chars[] = "0123456789abcdef";
+ std::string result;
+ result.resize(len * 2);
+
+ for (size_t i = 0; i < len; i++) {
+ result[2 * i] = chars[bytes8[i] >> 4];
+ result[2 * i + 1] = chars[bytes8[i] & 0xf];
+ }
+
+ return result;
+}
+
// ---------------------------------------------------------------------
static const char indentStr[] =
diff --git a/libs/binder/include/binder/Debug.h b/libs/binder/Debug.h
similarity index 89%
rename from libs/binder/include/binder/Debug.h
rename to libs/binder/Debug.h
index ac71e00..7ca087e 100644
--- a/libs/binder/include/binder/Debug.h
+++ b/libs/binder/Debug.h
@@ -17,13 +17,13 @@
#pragma once
#include <stdint.h>
-#include <sys/cdefs.h>
#include <sys/types.h>
+#include <string>
namespace android {
// ---------------------------------------------------------------------------
-__BEGIN_DECLS
+std::string hexString(const void* data, size_t size);
const char* stringForIndent(int32_t indentLevel);
@@ -37,10 +37,7 @@
size_t alignment=0, bool cArrayStyle=false,
debugPrintFunc func = nullptr, void* cookie = nullptr);
-
-ssize_t getBinderKernelReferences(size_t count, uintptr_t* buf);
-
-__END_DECLS
+extern "C" ssize_t getBinderKernelReferences(size_t count, uintptr_t* buf);
// ---------------------------------------------------------------------------
} // namespace android
diff --git a/libs/binder/IBatteryStats.cpp b/libs/binder/IBatteryStats.cpp
index d0085df..0de804c 100644
--- a/libs/binder/IBatteryStats.cpp
+++ b/libs/binder/IBatteryStats.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <binder/IBatteryStats.h>
+#include <batterystats/IBatteryStats.h>
#include <utils/Log.h>
#include <binder/Parcel.h>
diff --git a/libs/binder/IMediaResourceMonitor.cpp b/libs/binder/IMediaResourceMonitor.cpp
deleted file mode 100644
index f5fa817..0000000
--- a/libs/binder/IMediaResourceMonitor.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2016 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 <binder/IMediaResourceMonitor.h>
-#include <binder/Parcel.h>
-#include <utils/Errors.h>
-#include <sys/types.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------
-
-class BpMediaResourceMonitor : public BpInterface<IMediaResourceMonitor> {
-public:
- explicit BpMediaResourceMonitor(const sp<IBinder>& impl)
- : BpInterface<IMediaResourceMonitor>(impl) {}
-
- virtual void notifyResourceGranted(/*in*/ int32_t pid, /*in*/ const int32_t type)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IMediaResourceMonitor::getInterfaceDescriptor());
- data.writeInt32(pid);
- data.writeInt32(type);
- remote()->transact(NOTIFY_RESOURCE_GRANTED, data, &reply, IBinder::FLAG_ONEWAY);
- }
-};
-
-IMPLEMENT_META_INTERFACE(MediaResourceMonitor, "android.media.IMediaResourceMonitor")
-
-// ----------------------------------------------------------------------
-
-// NOLINTNEXTLINE(google-default-arguments)
-status_t BnMediaResourceMonitor::onTransact( uint32_t code, const Parcel& data, Parcel* reply,
- uint32_t flags) {
- switch(code) {
- case NOTIFY_RESOURCE_GRANTED: {
- CHECK_INTERFACE(IMediaResourceMonitor, data, reply);
- int32_t pid = data.readInt32();
- const int32_t type = data.readInt32();
- notifyResourceGranted(/*in*/ pid, /*in*/ type);
- return NO_ERROR;
- } break;
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-// ----------------------------------------------------------------------
-
-} // namespace android
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 5c34069..406bd54 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -611,6 +611,12 @@
mPostWriteStrongDerefs.clear();
}
+void IPCThreadState::createTransactionReference(RefBase* ref)
+{
+ ref->incStrong(mProcess.get());
+ mPostWriteStrongDerefs.push(ref);
+}
+
void IPCThreadState::joinThreadPool(bool isMain)
{
LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
@@ -683,6 +689,8 @@
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
+ LOG_ALWAYS_FATAL_IF(data.isForRpc(), "Parcel constructed for RPC, but being used with binder.");
+
status_t err;
flags |= TF_ACCEPT_FDS;
diff --git a/libs/binder/IpPrefix.cpp b/libs/binder/IpPrefix.cpp
index 8d62266..4edc493 100644
--- a/libs/binder/IpPrefix.cpp
+++ b/libs/binder/IpPrefix.cpp
@@ -24,12 +24,10 @@
#include <log/log.h>
#include <utils/Errors.h>
-using android::BAD_TYPE;
using android::BAD_VALUE;
using android::NO_ERROR;
using android::Parcel;
using android::status_t;
-using android::UNEXPECTED_NULL;
namespace android {
diff --git a/libs/binder/LazyServiceRegistrar.cpp b/libs/binder/LazyServiceRegistrar.cpp
index 21a9251..f96b6bb 100644
--- a/libs/binder/LazyServiceRegistrar.cpp
+++ b/libs/binder/LazyServiceRegistrar.cpp
@@ -30,16 +30,12 @@
using AidlServiceManager = android::os::IServiceManager;
-class ClientCounterCallback : public ::android::os::BnClientCallback {
+class ClientCounterCallbackImpl : public ::android::os::BnClientCallback {
public:
- ClientCounterCallback() : mNumConnectedServices(0), mForcePersist(false) {}
+ ClientCounterCallbackImpl() : mNumConnectedServices(0), mForcePersist(false) {}
bool registerService(const sp<IBinder>& service, const std::string& name,
bool allowIsolated, int dumpFlags);
-
- /**
- * Set a flag to prevent services from automatically shutting down
- */
void forcePersist(bool persist);
void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback);
@@ -97,7 +93,29 @@
std::function<bool(bool)> mActiveServicesCallback;
};
-bool ClientCounterCallback::registerService(const sp<IBinder>& service, const std::string& name,
+class ClientCounterCallback {
+public:
+ ClientCounterCallback();
+
+ bool registerService(const sp<IBinder>& service, const std::string& name,
+ bool allowIsolated, int dumpFlags);
+
+ /**
+ * Set a flag to prevent services from automatically shutting down
+ */
+ void forcePersist(bool persist);
+
+ void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback);
+
+ bool tryUnregister();
+
+ void reRegister();
+
+private:
+ sp<ClientCounterCallbackImpl> mImpl;
+};
+
+bool ClientCounterCallbackImpl::registerService(const sp<IBinder>& service, const std::string& name,
bool allowIsolated, int dumpFlags) {
auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
@@ -111,7 +129,7 @@
}
if (!reRegister) {
- if (!manager->registerClientCallback(name, service, this).isOk()) {
+ if(!manager->registerClientCallback(name, service, this).isOk()) {
ALOGE("Failed to add client callback for service %s", name.c_str());
return false;
}
@@ -127,7 +145,7 @@
return true;
}
-std::map<std::string, ClientCounterCallback::Service>::iterator ClientCounterCallback::assertRegisteredService(const sp<IBinder>& service) {
+std::map<std::string, ClientCounterCallbackImpl::Service>::iterator ClientCounterCallbackImpl::assertRegisteredService(const sp<IBinder>& service) {
LOG_ALWAYS_FATAL_IF(service == nullptr, "Got onClients callback for null service");
for (auto it = mRegisteredServices.begin(); it != mRegisteredServices.end(); ++it) {
auto const& [name, registered] = *it;
@@ -139,7 +157,7 @@
__builtin_unreachable();
}
-void ClientCounterCallback::forcePersist(bool persist) {
+void ClientCounterCallbackImpl::forcePersist(bool persist) {
mForcePersist = persist;
if (!mForcePersist) {
// Attempt a shutdown in case the number of clients hit 0 while the flag was on
@@ -147,7 +165,7 @@
}
}
-bool ClientCounterCallback::tryUnregister() {
+bool ClientCounterCallbackImpl::tryUnregister() {
auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
for (auto& [name, entry] : mRegisteredServices) {
@@ -163,7 +181,7 @@
return true;
}
-void ClientCounterCallback::reRegister() {
+void ClientCounterCallbackImpl::reRegister() {
for (auto& [name, entry] : mRegisteredServices) {
// re-register entry if not already registered
if (entry.registered) {
@@ -180,7 +198,7 @@
}
}
-void ClientCounterCallback::maybeTryShutdown() {
+void ClientCounterCallbackImpl::maybeTryShutdown() {
if (mForcePersist) {
ALOGI("Shutdown prevented by forcePersist override flag.");
return;
@@ -207,7 +225,7 @@
* onClients is oneway, so no need to worry about multi-threading. Note that this means multiple
* invocations could occur on different threads however.
*/
-Status ClientCounterCallback::onClients(const sp<IBinder>& service, bool clients) {
+Status ClientCounterCallbackImpl::onClients(const sp<IBinder>& service, bool clients) {
auto & [name, registered] = *assertRegisteredService(service);
if (registered.clients == clients) {
LOG_ALWAYS_FATAL("Process already thought %s had clients: %d but servicemanager has "
@@ -229,24 +247,49 @@
mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients);
maybeTryShutdown();
-
return Status::ok();
}
-void ClientCounterCallback::tryShutdown() {
- ALOGI("Trying to shut down the service. No clients in use for any service in process.");
+ void ClientCounterCallbackImpl::tryShutdown() {
+ ALOGI("Trying to shut down the service. No clients in use for any service in process.");
if (tryUnregister()) {
- ALOGI("Unregistered all clients and exiting");
- exit(EXIT_SUCCESS);
- }
+ ALOGI("Unregistered all clients and exiting");
+ exit(EXIT_SUCCESS);
+ }
reRegister();
}
+void ClientCounterCallbackImpl::setActiveServicesCallback(const std::function<bool(bool)>&
+ activeServicesCallback) {
+ mActiveServicesCallback = activeServicesCallback;
+}
+
+ClientCounterCallback::ClientCounterCallback() {
+ mImpl = sp<ClientCounterCallbackImpl>::make();
+}
+
+bool ClientCounterCallback::registerService(const sp<IBinder>& service, const std::string& name,
+ bool allowIsolated, int dumpFlags) {
+ return mImpl->registerService(service, name, allowIsolated, dumpFlags);
+}
+
+void ClientCounterCallback::forcePersist(bool persist) {
+ mImpl->forcePersist(persist);
+}
+
void ClientCounterCallback::setActiveServicesCallback(const std::function<bool(bool)>&
activeServicesCallback) {
- mActiveServicesCallback = activeServicesCallback;
+ mImpl->setActiveServicesCallback(activeServicesCallback);
+}
+
+bool ClientCounterCallback::tryUnregister() {
+ return mImpl->tryUnregister();
+}
+
+void ClientCounterCallback::reRegister() {
+ mImpl->reRegister();
}
} // namespace internal
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 8087443..34a474b 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -41,13 +41,15 @@
#include <binder/TextOutput.h>
#include <cutils/ashmem.h>
+#include <cutils/compiler.h>
#include <utils/Flattenable.h>
#include <utils/Log.h>
-#include <utils/misc.h>
-#include <utils/String8.h>
#include <utils/String16.h>
+#include <utils/String8.h>
+#include <utils/misc.h>
#include <private/binder/binder_module.h>
+#include "RpcState.h"
#include "Static.h"
#include "Utils.h"
@@ -191,6 +193,22 @@
status_t Parcel::flattenBinder(const sp<IBinder>& binder)
{
+ if (isForRpc()) {
+ if (binder) {
+ status_t status = writeInt32(1); // non-null
+ if (status != OK) return status;
+ RpcAddress address = RpcAddress::zero();
+ status = mConnection->state()->onBinderLeaving(mConnection, binder, &address);
+ if (status != OK) return status;
+ status = address.writeToParcel(this);
+ if (status != OK) return status;
+ } else {
+ status_t status = writeInt32(0); // null
+ if (status != OK) return status;
+ }
+ return finishFlattenBinder(binder);
+ }
+
flat_binder_object obj;
obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
@@ -205,8 +223,13 @@
BpBinder *proxy = binder->remoteBinder();
if (proxy == nullptr) {
ALOGE("null proxy");
+ } else {
+ if (proxy->isRpcBinder()) {
+ ALOGE("Sending a socket binder over RPC is prohibited");
+ return INVALID_OPERATION;
+ }
}
- const int32_t handle = proxy ? proxy->getPrivateAccessorForHandle().handle() : 0;
+ const int32_t handle = proxy ? proxy->getPrivateAccessorForId().binderHandle() : 0;
obj.hdr.type = BINDER_TYPE_HANDLE;
obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
obj.handle = handle;
@@ -245,6 +268,26 @@
status_t Parcel::unflattenBinder(sp<IBinder>* out) const
{
+ if (isForRpc()) {
+ LOG_ALWAYS_FATAL_IF(mConnection == nullptr,
+ "RpcConnection required to read from remote parcel");
+
+ int32_t isNull;
+ status_t status = readInt32(&isNull);
+ if (status != OK) return status;
+
+ sp<IBinder> binder;
+
+ if (isNull & 1) {
+ auto addr = RpcAddress::zero();
+ status_t status = addr.readFromParcel(*this);
+ if (status != OK) return status;
+ binder = mConnection->state()->onBinderEntering(mConnection, addr);
+ }
+
+ return finishUnflattenBinder(binder, out);
+ }
+
const flat_binder_object* flat = readObject(false);
if (flat) {
@@ -511,6 +554,21 @@
mDeallocZero = true;
}
+void Parcel::markForBinder(const sp<IBinder>& binder) {
+ if (binder && binder->remoteBinder() && binder->remoteBinder()->isRpcBinder()) {
+ markForRpc(binder->remoteBinder()->getPrivateAccessorForId().rpcConnection());
+ }
+}
+
+void Parcel::markForRpc(const sp<RpcConnection>& connection) {
+ LOG_ALWAYS_FATAL_IF(connection == nullptr, "markForRpc requires connection");
+ mConnection = connection;
+}
+
+bool Parcel::isForRpc() const {
+ return mConnection != nullptr;
+}
+
void Parcel::updateWorkSourceRequestHeaderPosition() const {
// Only update the request headers once. We only want to point
// to the first headers read/written.
@@ -533,12 +591,14 @@
}
status_t Parcel::writeInterfaceToken(const char16_t* str, size_t len) {
- const IPCThreadState* threadState = IPCThreadState::self();
- writeInt32(threadState->getStrictModePolicy() | STRICT_MODE_PENALTY_GATHER);
- updateWorkSourceRequestHeaderPosition();
- writeInt32(threadState->shouldPropagateWorkSource() ?
- threadState->getCallingWorkSourceUid() : IPCThreadState::kUnsetWorkSource);
- writeInt32(kHeader);
+ if (CC_LIKELY(!isForRpc())) {
+ const IPCThreadState* threadState = IPCThreadState::self();
+ writeInt32(threadState->getStrictModePolicy() | STRICT_MODE_PENALTY_GATHER);
+ updateWorkSourceRequestHeaderPosition();
+ writeInt32(threadState->shouldPropagateWorkSource() ? threadState->getCallingWorkSourceUid()
+ : IPCThreadState::kUnsetWorkSource);
+ writeInt32(kHeader);
+ }
// currently the interface identification token is just its name as a string
return writeString16(str, len);
@@ -585,31 +645,34 @@
size_t len,
IPCThreadState* threadState) const
{
- // StrictModePolicy.
- int32_t strictPolicy = readInt32();
- if (threadState == nullptr) {
- threadState = IPCThreadState::self();
+ if (CC_LIKELY(!isForRpc())) {
+ // StrictModePolicy.
+ int32_t strictPolicy = readInt32();
+ if (threadState == nullptr) {
+ threadState = IPCThreadState::self();
+ }
+ if ((threadState->getLastTransactionBinderFlags() & IBinder::FLAG_ONEWAY) != 0) {
+ // For one-way calls, the callee is running entirely
+ // disconnected from the caller, so disable StrictMode entirely.
+ // Not only does disk/network usage not impact the caller, but
+ // there's no way to communicate back violations anyway.
+ threadState->setStrictModePolicy(0);
+ } else {
+ threadState->setStrictModePolicy(strictPolicy);
+ }
+ // WorkSource.
+ updateWorkSourceRequestHeaderPosition();
+ int32_t workSource = readInt32();
+ threadState->setCallingWorkSourceUidWithoutPropagation(workSource);
+ // vendor header
+ int32_t header = readInt32();
+ if (header != kHeader) {
+ ALOGE("Expecting header 0x%x but found 0x%x. Mixing copies of libbinder?", kHeader,
+ header);
+ return false;
+ }
}
- if ((threadState->getLastTransactionBinderFlags() &
- IBinder::FLAG_ONEWAY) != 0) {
- // For one-way calls, the callee is running entirely
- // disconnected from the caller, so disable StrictMode entirely.
- // Not only does disk/network usage not impact the caller, but
- // there's no way to commuicate back any violations anyway.
- threadState->setStrictModePolicy(0);
- } else {
- threadState->setStrictModePolicy(strictPolicy);
- }
- // WorkSource.
- updateWorkSourceRequestHeaderPosition();
- int32_t workSource = readInt32();
- threadState->setCallingWorkSourceUidWithoutPropagation(workSource);
- // vendor header
- int32_t header = readInt32();
- if (header != kHeader) {
- ALOGE("Expecting header 0x%x but found 0x%x. Mixing copies of libbinder?", kHeader, header);
- return false;
- }
+
// Interface descriptor.
size_t parcel_interface_len;
const char16_t* parcel_interface = readString16Inplace(&parcel_interface_len);
@@ -769,200 +832,116 @@
return NO_ERROR;
}
-status_t Parcel::writeUtf8AsUtf16(const std::optional<std::string>& str) {
- if (!str) {
- return writeInt32(-1);
- }
- return writeUtf8AsUtf16(*str);
-}
-status_t Parcel::writeUtf8AsUtf16(const std::unique_ptr<std::string>& str) {
- if (!str) {
- return writeInt32(-1);
- }
- return writeUtf8AsUtf16(*str);
-}
+status_t Parcel::writeUtf8AsUtf16(const std::optional<std::string>& str) { return writeData(str); }
+status_t Parcel::writeUtf8AsUtf16(const std::unique_ptr<std::string>& str) { return writeData(str); }
-status_t Parcel::writeByteVectorInternal(const int8_t* data, size_t size) {
- if (size > std::numeric_limits<int32_t>::max()) {
- return BAD_VALUE;
- }
+status_t Parcel::writeString16(const std::optional<String16>& str) { return writeData(str); }
+status_t Parcel::writeString16(const std::unique_ptr<String16>& str) { return writeData(str); }
- status_t status = writeInt32(size);
- if (status != OK) {
- return status;
- }
+status_t Parcel::writeByteVector(const std::vector<int8_t>& val) { return writeData(val); }
+status_t Parcel::writeByteVector(const std::optional<std::vector<int8_t>>& val) { return writeData(val); }
+status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val) { return writeData(val); }
+status_t Parcel::writeByteVector(const std::vector<uint8_t>& val) { return writeData(val); }
+status_t Parcel::writeByteVector(const std::optional<std::vector<uint8_t>>& val) { return writeData(val); }
+status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val){ return writeData(val); }
+status_t Parcel::writeInt32Vector(const std::vector<int32_t>& val) { return writeData(val); }
+status_t Parcel::writeInt32Vector(const std::optional<std::vector<int32_t>>& val) { return writeData(val); }
+status_t Parcel::writeInt32Vector(const std::unique_ptr<std::vector<int32_t>>& val) { return writeData(val); }
+status_t Parcel::writeInt64Vector(const std::vector<int64_t>& val) { return writeData(val); }
+status_t Parcel::writeInt64Vector(const std::optional<std::vector<int64_t>>& val) { return writeData(val); }
+status_t Parcel::writeInt64Vector(const std::unique_ptr<std::vector<int64_t>>& val) { return writeData(val); }
+status_t Parcel::writeUint64Vector(const std::vector<uint64_t>& val) { return writeData(val); }
+status_t Parcel::writeUint64Vector(const std::optional<std::vector<uint64_t>>& val) { return writeData(val); }
+status_t Parcel::writeUint64Vector(const std::unique_ptr<std::vector<uint64_t>>& val) { return writeData(val); }
+status_t Parcel::writeFloatVector(const std::vector<float>& val) { return writeData(val); }
+status_t Parcel::writeFloatVector(const std::optional<std::vector<float>>& val) { return writeData(val); }
+status_t Parcel::writeFloatVector(const std::unique_ptr<std::vector<float>>& val) { return writeData(val); }
+status_t Parcel::writeDoubleVector(const std::vector<double>& val) { return writeData(val); }
+status_t Parcel::writeDoubleVector(const std::optional<std::vector<double>>& val) { return writeData(val); }
+status_t Parcel::writeDoubleVector(const std::unique_ptr<std::vector<double>>& val) { return writeData(val); }
+status_t Parcel::writeBoolVector(const std::vector<bool>& val) { return writeData(val); }
+status_t Parcel::writeBoolVector(const std::optional<std::vector<bool>>& val) { return writeData(val); }
+status_t Parcel::writeBoolVector(const std::unique_ptr<std::vector<bool>>& val) { return writeData(val); }
+status_t Parcel::writeCharVector(const std::vector<char16_t>& val) { return writeData(val); }
+status_t Parcel::writeCharVector(const std::optional<std::vector<char16_t>>& val) { return writeData(val); }
+status_t Parcel::writeCharVector(const std::unique_ptr<std::vector<char16_t>>& val) { return writeData(val); }
- return write(data, size);
-}
-
-status_t Parcel::writeByteVector(const std::vector<int8_t>& val) {
- return writeByteVectorInternal(val.data(), val.size());
-}
-
-status_t Parcel::writeByteVector(const std::optional<std::vector<int8_t>>& val)
-{
- if (!val) return writeInt32(-1);
- return writeByteVectorInternal(val->data(), val->size());
-}
-
-status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val)
-{
- if (!val) return writeInt32(-1);
- return writeByteVectorInternal(val->data(), val->size());
-}
-
-status_t Parcel::writeByteVector(const std::vector<uint8_t>& val) {
- return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val.data()), val.size());
-}
-
-status_t Parcel::writeByteVector(const std::optional<std::vector<uint8_t>>& val)
-{
- if (!val) return writeInt32(-1);
- return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size());
-}
-
-status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val)
-{
- if (!val) return writeInt32(-1);
- return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size());
-}
-
-status_t Parcel::writeInt32Vector(const std::vector<int32_t>& val)
-{
- return writeTypedVector(val, &Parcel::writeInt32);
-}
-
-status_t Parcel::writeInt32Vector(const std::optional<std::vector<int32_t>>& val)
-{
- return writeNullableTypedVector(val, &Parcel::writeInt32);
-}
-
-status_t Parcel::writeInt32Vector(const std::unique_ptr<std::vector<int32_t>>& val)
-{
- return writeNullableTypedVector(val, &Parcel::writeInt32);
-}
-
-status_t Parcel::writeInt64Vector(const std::vector<int64_t>& val)
-{
- return writeTypedVector(val, &Parcel::writeInt64);
-}
-
-status_t Parcel::writeInt64Vector(const std::optional<std::vector<int64_t>>& val)
-{
- return writeNullableTypedVector(val, &Parcel::writeInt64);
-}
-
-status_t Parcel::writeInt64Vector(const std::unique_ptr<std::vector<int64_t>>& val)
-{
- return writeNullableTypedVector(val, &Parcel::writeInt64);
-}
-
-status_t Parcel::writeUint64Vector(const std::vector<uint64_t>& val)
-{
- return writeTypedVector(val, &Parcel::writeUint64);
-}
-
-status_t Parcel::writeUint64Vector(const std::optional<std::vector<uint64_t>>& val)
-{
- return writeNullableTypedVector(val, &Parcel::writeUint64);
-}
-
-status_t Parcel::writeUint64Vector(const std::unique_ptr<std::vector<uint64_t>>& val)
-{
- return writeNullableTypedVector(val, &Parcel::writeUint64);
-}
-
-status_t Parcel::writeFloatVector(const std::vector<float>& val)
-{
- return writeTypedVector(val, &Parcel::writeFloat);
-}
-
-status_t Parcel::writeFloatVector(const std::optional<std::vector<float>>& val)
-{
- return writeNullableTypedVector(val, &Parcel::writeFloat);
-}
-
-status_t Parcel::writeFloatVector(const std::unique_ptr<std::vector<float>>& val)
-{
- return writeNullableTypedVector(val, &Parcel::writeFloat);
-}
-
-status_t Parcel::writeDoubleVector(const std::vector<double>& val)
-{
- return writeTypedVector(val, &Parcel::writeDouble);
-}
-
-status_t Parcel::writeDoubleVector(const std::optional<std::vector<double>>& val)
-{
- return writeNullableTypedVector(val, &Parcel::writeDouble);
-}
-
-status_t Parcel::writeDoubleVector(const std::unique_ptr<std::vector<double>>& val)
-{
- return writeNullableTypedVector(val, &Parcel::writeDouble);
-}
-
-status_t Parcel::writeBoolVector(const std::vector<bool>& val)
-{
- return writeTypedVector(val, &Parcel::writeBool);
-}
-
-status_t Parcel::writeBoolVector(const std::optional<std::vector<bool>>& val)
-{
- return writeNullableTypedVector(val, &Parcel::writeBool);
-}
-
-status_t Parcel::writeBoolVector(const std::unique_ptr<std::vector<bool>>& val)
-{
- return writeNullableTypedVector(val, &Parcel::writeBool);
-}
-
-status_t Parcel::writeCharVector(const std::vector<char16_t>& val)
-{
- return writeTypedVector(val, &Parcel::writeChar);
-}
-
-status_t Parcel::writeCharVector(const std::optional<std::vector<char16_t>>& val)
-{
- return writeNullableTypedVector(val, &Parcel::writeChar);
-}
-
-status_t Parcel::writeCharVector(const std::unique_ptr<std::vector<char16_t>>& val)
-{
- return writeNullableTypedVector(val, &Parcel::writeChar);
-}
-
-status_t Parcel::writeString16Vector(const std::vector<String16>& val)
-{
- return writeTypedVector(val, &Parcel::writeString16);
-}
-
+status_t Parcel::writeString16Vector(const std::vector<String16>& val) { return writeData(val); }
status_t Parcel::writeString16Vector(
- const std::optional<std::vector<std::optional<String16>>>& val)
-{
- return writeNullableTypedVector(val, &Parcel::writeString16);
-}
-
+ const std::optional<std::vector<std::optional<String16>>>& val) { return writeData(val); }
status_t Parcel::writeString16Vector(
- const std::unique_ptr<std::vector<std::unique_ptr<String16>>>& val)
-{
- return writeNullableTypedVector(val, &Parcel::writeString16);
-}
-
+ const std::unique_ptr<std::vector<std::unique_ptr<String16>>>& val) { return writeData(val); }
status_t Parcel::writeUtf8VectorAsUtf16Vector(
- const std::optional<std::vector<std::optional<std::string>>>& val) {
- return writeNullableTypedVector(val, &Parcel::writeUtf8AsUtf16);
-}
-
+ const std::optional<std::vector<std::optional<std::string>>>& val) { return writeData(val); }
status_t Parcel::writeUtf8VectorAsUtf16Vector(
- const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& val) {
- return writeNullableTypedVector(val, &Parcel::writeUtf8AsUtf16);
-}
+ const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& val) { return writeData(val); }
+status_t Parcel::writeUtf8VectorAsUtf16Vector(const std::vector<std::string>& val) { return writeData(val); }
-status_t Parcel::writeUtf8VectorAsUtf16Vector(const std::vector<std::string>& val) {
- return writeTypedVector(val, &Parcel::writeUtf8AsUtf16);
-}
+status_t Parcel::writeUniqueFileDescriptorVector(const std::vector<base::unique_fd>& val) { return writeData(val); }
+status_t Parcel::writeUniqueFileDescriptorVector(const std::optional<std::vector<base::unique_fd>>& val) { return writeData(val); }
+status_t Parcel::writeUniqueFileDescriptorVector(const std::unique_ptr<std::vector<base::unique_fd>>& val) { return writeData(val); }
+
+status_t Parcel::writeStrongBinderVector(const std::vector<sp<IBinder>>& val) { return writeData(val); }
+status_t Parcel::writeStrongBinderVector(const std::optional<std::vector<sp<IBinder>>>& val) { return writeData(val); }
+status_t Parcel::writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val) { return writeData(val); }
+
+status_t Parcel::writeParcelable(const Parcelable& parcelable) { return writeData(parcelable); }
+
+status_t Parcel::readUtf8FromUtf16(std::optional<std::string>* str) const { return readData(str); }
+status_t Parcel::readUtf8FromUtf16(std::unique_ptr<std::string>* str) const { return readData(str); }
+
+status_t Parcel::readString16(std::optional<String16>* pArg) const { return readData(pArg); }
+status_t Parcel::readString16(std::unique_ptr<String16>* pArg) const { return readData(pArg); }
+
+status_t Parcel::readByteVector(std::vector<int8_t>* val) const { return readData(val); }
+status_t Parcel::readByteVector(std::vector<uint8_t>* val) const { return readData(val); }
+status_t Parcel::readByteVector(std::optional<std::vector<int8_t>>* val) const { return readData(val); }
+status_t Parcel::readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const { return readData(val); }
+status_t Parcel::readByteVector(std::optional<std::vector<uint8_t>>* val) const { return readData(val); }
+status_t Parcel::readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const { return readData(val); }
+status_t Parcel::readInt32Vector(std::optional<std::vector<int32_t>>* val) const { return readData(val); }
+status_t Parcel::readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const { return readData(val); }
+status_t Parcel::readInt32Vector(std::vector<int32_t>* val) const { return readData(val); }
+status_t Parcel::readInt64Vector(std::optional<std::vector<int64_t>>* val) const { return readData(val); }
+status_t Parcel::readInt64Vector(std::unique_ptr<std::vector<int64_t>>* val) const { return readData(val); }
+status_t Parcel::readInt64Vector(std::vector<int64_t>* val) const { return readData(val); }
+status_t Parcel::readUint64Vector(std::optional<std::vector<uint64_t>>* val) const { return readData(val); }
+status_t Parcel::readUint64Vector(std::unique_ptr<std::vector<uint64_t>>* val) const { return readData(val); }
+status_t Parcel::readUint64Vector(std::vector<uint64_t>* val) const { return readData(val); }
+status_t Parcel::readFloatVector(std::optional<std::vector<float>>* val) const { return readData(val); }
+status_t Parcel::readFloatVector(std::unique_ptr<std::vector<float>>* val) const { return readData(val); }
+status_t Parcel::readFloatVector(std::vector<float>* val) const { return readData(val); }
+status_t Parcel::readDoubleVector(std::optional<std::vector<double>>* val) const { return readData(val); }
+status_t Parcel::readDoubleVector(std::unique_ptr<std::vector<double>>* val) const { return readData(val); }
+status_t Parcel::readDoubleVector(std::vector<double>* val) const { return readData(val); }
+status_t Parcel::readBoolVector(std::optional<std::vector<bool>>* val) const { return readData(val); }
+status_t Parcel::readBoolVector(std::unique_ptr<std::vector<bool>>* val) const { return readData(val); }
+status_t Parcel::readBoolVector(std::vector<bool>* val) const { return readData(val); }
+status_t Parcel::readCharVector(std::optional<std::vector<char16_t>>* val) const { return readData(val); }
+status_t Parcel::readCharVector(std::unique_ptr<std::vector<char16_t>>* val) const { return readData(val); }
+status_t Parcel::readCharVector(std::vector<char16_t>* val) const { return readData(val); }
+
+status_t Parcel::readString16Vector(
+ std::optional<std::vector<std::optional<String16>>>* val) const { return readData(val); }
+status_t Parcel::readString16Vector(
+ std::unique_ptr<std::vector<std::unique_ptr<String16>>>* val) const { return readData(val); }
+status_t Parcel::readString16Vector(std::vector<String16>* val) const { return readData(val); }
+status_t Parcel::readUtf8VectorFromUtf16Vector(
+ std::optional<std::vector<std::optional<std::string>>>* val) const { return readData(val); }
+status_t Parcel::readUtf8VectorFromUtf16Vector(
+ std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const { return readData(val); }
+status_t Parcel::readUtf8VectorFromUtf16Vector(std::vector<std::string>* val) const { return readData(val); }
+
+status_t Parcel::readUniqueFileDescriptorVector(std::optional<std::vector<base::unique_fd>>* val) const { return readData(val); }
+status_t Parcel::readUniqueFileDescriptorVector(std::unique_ptr<std::vector<base::unique_fd>>* val) const { return readData(val); }
+status_t Parcel::readUniqueFileDescriptorVector(std::vector<base::unique_fd>* val) const { return readData(val); }
+
+status_t Parcel::readStrongBinderVector(std::optional<std::vector<sp<IBinder>>>* val) const { return readData(val); }
+status_t Parcel::readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const { return readData(val); }
+status_t Parcel::readStrongBinderVector(std::vector<sp<IBinder>>* val) const { return readData(val); }
+
+status_t Parcel::readParcelable(Parcelable* parcelable) const { return readData(parcelable); }
status_t Parcel::writeInt32(int32_t val)
{
@@ -1091,24 +1070,6 @@
return err;
}
-status_t Parcel::writeString16(const std::optional<String16>& str)
-{
- if (!str) {
- return writeInt32(-1);
- }
-
- return writeString16(*str);
-}
-
-status_t Parcel::writeString16(const std::unique_ptr<String16>& str)
-{
- if (!str) {
- return writeInt32(-1);
- }
-
- return writeString16(*str);
-}
-
status_t Parcel::writeString16(const String16& str)
{
return writeString16(str.string(), str.size());
@@ -1138,32 +1099,6 @@
return flattenBinder(val);
}
-status_t Parcel::writeStrongBinderVector(const std::vector<sp<IBinder>>& val)
-{
- return writeTypedVector(val, &Parcel::writeStrongBinder);
-}
-
-status_t Parcel::writeStrongBinderVector(const std::optional<std::vector<sp<IBinder>>>& val)
-{
- return writeNullableTypedVector(val, &Parcel::writeStrongBinder);
-}
-
-status_t Parcel::writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val)
-{
- return writeNullableTypedVector(val, &Parcel::writeStrongBinder);
-}
-
-status_t Parcel::readStrongBinderVector(std::optional<std::vector<sp<IBinder>>>* val) const {
- return readNullableTypedVector(val, &Parcel::readNullableStrongBinder);
-}
-
-status_t Parcel::readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const {
- return readNullableTypedVector(val, &Parcel::readNullableStrongBinder);
-}
-
-status_t Parcel::readStrongBinderVector(std::vector<sp<IBinder>>* val) const {
- return readTypedVector(val, &Parcel::readStrongBinder);
-}
status_t Parcel::writeRawNullableParcelable(const Parcelable* parcelable) {
if (!parcelable) {
@@ -1173,14 +1108,6 @@
return writeParcelable(*parcelable);
}
-status_t Parcel::writeParcelable(const Parcelable& parcelable) {
- status_t status = writeInt32(1); // parcelable is not null.
- if (status != OK) {
- return status;
- }
- return parcelable.writeToParcel(this);
-}
-
status_t Parcel::writeNativeHandle(const native_handle* handle)
{
if (!handle || handle->version != sizeof(native_handle))
@@ -1206,6 +1133,11 @@
status_t Parcel::writeFileDescriptor(int fd, bool takeOwnership)
{
+ if (isForRpc()) {
+ ALOGE("Cannot write file descriptor to remote binder.");
+ return BAD_TYPE;
+ }
+
flat_binder_object obj;
obj.hdr.type = BINDER_TYPE_FD;
obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
@@ -1251,18 +1183,6 @@
return writeDupFileDescriptor(fd.get());
}
-status_t Parcel::writeUniqueFileDescriptorVector(const std::vector<base::unique_fd>& val) {
- return writeTypedVector(val, &Parcel::writeUniqueFileDescriptor);
-}
-
-status_t Parcel::writeUniqueFileDescriptorVector(const std::optional<std::vector<base::unique_fd>>& val) {
- return writeNullableTypedVector(val, &Parcel::writeUniqueFileDescriptor);
-}
-
-status_t Parcel::writeUniqueFileDescriptorVector(const std::unique_ptr<std::vector<base::unique_fd>>& val) {
- return writeNullableTypedVector(val, &Parcel::writeUniqueFileDescriptor);
-}
-
status_t Parcel::writeBlob(size_t len, bool mutableCopy, WritableBlob* outBlob)
{
if (len > INT32_MAX) {
@@ -1477,31 +1397,6 @@
goto data_sorted;
}
-status_t Parcel::readVectorSizeWithCoarseBoundCheck(int32_t *size) const {
- int32_t requestedSize;
- const status_t status = readInt32(&requestedSize);
- if (status != NO_ERROR) return status;
-
- // We permit negative sizes, which indicate presence of a nullable vector,
- // i.e. a vector embedded in std::optional, std::unique_ptr, or std::shared_ptr.
- if (requestedSize > 0) {
- // Check if there are fewer bytes than vector elements.
- // A lower bound is 1 byte per element, satisfied by some enum and int8_t and uint8_t.
- const size_t availableBytes = dataAvail();
- if (static_cast<size_t>(requestedSize) > availableBytes) {
- // We have a size that is greater than the number of bytes available.
- // On bounds failure we do not 'rewind' position by 4 bytes of the size already read.
- ALOGW("%s: rejecting out of bounds vector size (requestedSize):%d "
- "Parcel{dataAvail:%zu mDataSize:%zu mDataPos:%zu mDataCapacity:%zu}",
- __func__, requestedSize, availableBytes, mDataSize, mDataPos, mDataCapacity);
- return BAD_VALUE;
- }
- }
-
- *size = requestedSize;
- return NO_ERROR;
-}
-
status_t Parcel::read(void* outData, size_t len) const
{
if (len > INT32_MAX) {
@@ -1605,236 +1500,6 @@
return err;
}
-status_t Parcel::readByteVector(std::vector<int8_t>* val) const {
- size_t size;
- if (status_t status = reserveOutVector(val, &size); status != OK) return status;
- return readByteVectorInternal(val, size);
-}
-
-status_t Parcel::readByteVector(std::vector<uint8_t>* val) const {
- size_t size;
- if (status_t status = reserveOutVector(val, &size); status != OK) return status;
- return readByteVectorInternal(val, size);
-}
-
-status_t Parcel::readByteVector(std::optional<std::vector<int8_t>>* val) const {
- size_t size;
- if (status_t status = reserveOutVector(val, &size); status != OK) return status;
- if (!*val) {
- // reserveOutVector does not create the out vector if size is < 0.
- // This occurs when writing a null byte vector.
- return OK;
- }
- return readByteVectorInternal(&**val, size);
-}
-
-status_t Parcel::readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const {
- size_t size;
- if (status_t status = reserveOutVector(val, &size); status != OK) return status;
- if (val->get() == nullptr) {
- // reserveOutVector does not create the out vector if size is < 0.
- // This occurs when writing a null byte vector.
- return OK;
- }
- return readByteVectorInternal(val->get(), size);
-}
-
-status_t Parcel::readByteVector(std::optional<std::vector<uint8_t>>* val) const {
- size_t size;
- if (status_t status = reserveOutVector(val, &size); status != OK) return status;
- if (!*val) {
- // reserveOutVector does not create the out vector if size is < 0.
- // This occurs when writing a null byte vector.
- return OK;
- }
- return readByteVectorInternal(&**val, size);
-}
-
-status_t Parcel::readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const {
- size_t size;
- if (status_t status = reserveOutVector(val, &size); status != OK) return status;
- if (val->get() == nullptr) {
- // reserveOutVector does not create the out vector if size is < 0.
- // This occurs when writing a null byte vector.
- return OK;
- }
- return readByteVectorInternal(val->get(), size);
-}
-
-status_t Parcel::readInt32Vector(std::optional<std::vector<int32_t>>* val) const {
- return readNullableTypedVector(val, &Parcel::readInt32);
-}
-
-status_t Parcel::readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const {
- return readNullableTypedVector(val, &Parcel::readInt32);
-}
-
-status_t Parcel::readInt32Vector(std::vector<int32_t>* val) const {
- return readTypedVector(val, &Parcel::readInt32);
-}
-
-status_t Parcel::readInt64Vector(std::optional<std::vector<int64_t>>* val) const {
- return readNullableTypedVector(val, &Parcel::readInt64);
-}
-
-status_t Parcel::readInt64Vector(std::unique_ptr<std::vector<int64_t>>* val) const {
- return readNullableTypedVector(val, &Parcel::readInt64);
-}
-
-status_t Parcel::readInt64Vector(std::vector<int64_t>* val) const {
- return readTypedVector(val, &Parcel::readInt64);
-}
-
-status_t Parcel::readUint64Vector(std::optional<std::vector<uint64_t>>* val) const {
- return readNullableTypedVector(val, &Parcel::readUint64);
-}
-
-status_t Parcel::readUint64Vector(std::unique_ptr<std::vector<uint64_t>>* val) const {
- return readNullableTypedVector(val, &Parcel::readUint64);
-}
-
-status_t Parcel::readUint64Vector(std::vector<uint64_t>* val) const {
- return readTypedVector(val, &Parcel::readUint64);
-}
-
-status_t Parcel::readFloatVector(std::optional<std::vector<float>>* val) const {
- return readNullableTypedVector(val, &Parcel::readFloat);
-}
-
-status_t Parcel::readFloatVector(std::unique_ptr<std::vector<float>>* val) const {
- return readNullableTypedVector(val, &Parcel::readFloat);
-}
-
-status_t Parcel::readFloatVector(std::vector<float>* val) const {
- return readTypedVector(val, &Parcel::readFloat);
-}
-
-status_t Parcel::readDoubleVector(std::optional<std::vector<double>>* val) const {
- return readNullableTypedVector(val, &Parcel::readDouble);
-}
-
-status_t Parcel::readDoubleVector(std::unique_ptr<std::vector<double>>* val) const {
- return readNullableTypedVector(val, &Parcel::readDouble);
-}
-
-status_t Parcel::readDoubleVector(std::vector<double>* val) const {
- return readTypedVector(val, &Parcel::readDouble);
-}
-
-status_t Parcel::readBoolVector(std::optional<std::vector<bool>>* val) const {
- const int32_t start = dataPosition();
- int32_t size;
- status_t status = readVectorSizeWithCoarseBoundCheck(&size);
- val->reset();
-
- if (status != OK || size < 0) {
- return status;
- }
-
- setDataPosition(start);
- val->emplace();
-
- status = readBoolVector(&**val);
-
- if (status != OK) {
- val->reset();
- }
-
- return status;
-}
-
-status_t Parcel::readBoolVector(std::unique_ptr<std::vector<bool>>* val) const {
- const int32_t start = dataPosition();
- int32_t size;
- status_t status = readVectorSizeWithCoarseBoundCheck(&size);
- val->reset();
-
- if (status != OK || size < 0) {
- return status;
- }
-
- setDataPosition(start);
- val->reset(new (std::nothrow) std::vector<bool>());
-
- status = readBoolVector(val->get());
-
- if (status != OK) {
- val->reset();
- }
-
- return status;
-}
-
-status_t Parcel::readBoolVector(std::vector<bool>* val) const {
- int32_t size;
- status_t status = readVectorSizeWithCoarseBoundCheck(&size);
-
- if (status != OK) {
- return status;
- }
-
- if (size < 0) {
- return UNEXPECTED_NULL;
- }
-
- val->resize(size);
-
- /* C++ bool handling means a vector of bools isn't necessarily addressable
- * (we might use individual bits)
- */
- bool data;
- for (int32_t i = 0; i < size; ++i) {
- status = readBool(&data);
- (*val)[i] = data;
-
- if (status != OK) {
- return status;
- }
- }
-
- return OK;
-}
-
-status_t Parcel::readCharVector(std::optional<std::vector<char16_t>>* val) const {
- return readNullableTypedVector(val, &Parcel::readChar);
-}
-
-status_t Parcel::readCharVector(std::unique_ptr<std::vector<char16_t>>* val) const {
- return readNullableTypedVector(val, &Parcel::readChar);
-}
-
-status_t Parcel::readCharVector(std::vector<char16_t>* val) const {
- return readTypedVector(val, &Parcel::readChar);
-}
-
-status_t Parcel::readString16Vector(
- std::optional<std::vector<std::optional<String16>>>* val) const {
- return readNullableTypedVector(val, &Parcel::readString16);
-}
-
-status_t Parcel::readString16Vector(
- std::unique_ptr<std::vector<std::unique_ptr<String16>>>* val) const {
- return readNullableTypedVector(val, &Parcel::readString16);
-}
-
-status_t Parcel::readString16Vector(std::vector<String16>* val) const {
- return readTypedVector(val, &Parcel::readString16);
-}
-
-status_t Parcel::readUtf8VectorFromUtf16Vector(
- std::optional<std::vector<std::optional<std::string>>>* val) const {
- return readNullableTypedVector(val, &Parcel::readUtf8FromUtf16);
-}
-
-status_t Parcel::readUtf8VectorFromUtf16Vector(
- std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const {
- return readNullableTypedVector(val, &Parcel::readUtf8FromUtf16);
-}
-
-status_t Parcel::readUtf8VectorFromUtf16Vector(std::vector<std::string>* val) const {
- return readTypedVector(val, &Parcel::readUtf8FromUtf16);
-}
-
status_t Parcel::readInt32(int32_t *pArg) const
{
return readAligned(pArg);
@@ -2007,36 +1672,6 @@
return NO_ERROR;
}
-status_t Parcel::readUtf8FromUtf16(std::optional<std::string>* str) const {
- const int32_t start = dataPosition();
- int32_t size;
- status_t status = readInt32(&size);
- str->reset();
-
- if (status != OK || size < 0) {
- return status;
- }
-
- setDataPosition(start);
- str->emplace();
- return readUtf8FromUtf16(&**str);
-}
-
-status_t Parcel::readUtf8FromUtf16(std::unique_ptr<std::string>* str) const {
- const int32_t start = dataPosition();
- int32_t size;
- status_t status = readInt32(&size);
- str->reset();
-
- if (status != OK || size < 0) {
- return status;
- }
-
- setDataPosition(start);
- str->reset(new (std::nothrow) std::string());
- return readUtf8FromUtf16(str->get());
-}
-
const char* Parcel::readCString() const
{
if (mDataPos < mDataSize) {
@@ -2084,7 +1719,10 @@
*outLen = size;
const char* str = (const char*)readInplace(size+1);
if (str != nullptr) {
- return str;
+ if (str[size] == '\0') {
+ return str;
+ }
+ android_errorWriteLog(0x534e4554, "172655291");
}
}
*outLen = 0;
@@ -2100,51 +1738,6 @@
return String16();
}
-status_t Parcel::readString16(std::optional<String16>* pArg) const
-{
- const int32_t start = dataPosition();
- int32_t size;
- status_t status = readInt32(&size);
- pArg->reset();
-
- if (status != OK || size < 0) {
- return status;
- }
-
- setDataPosition(start);
- pArg->emplace();
-
- status = readString16(&**pArg);
-
- if (status != OK) {
- pArg->reset();
- }
-
- return status;
-}
-
-status_t Parcel::readString16(std::unique_ptr<String16>* pArg) const
-{
- const int32_t start = dataPosition();
- int32_t size;
- status_t status = readInt32(&size);
- pArg->reset();
-
- if (status != OK || size < 0) {
- return status;
- }
-
- setDataPosition(start);
- pArg->reset(new (std::nothrow) String16());
-
- status = readString16(pArg->get());
-
- if (status != OK) {
- pArg->reset();
- }
-
- return status;
-}
status_t Parcel::readString16(String16* pArg) const
{
@@ -2167,7 +1760,10 @@
*outLen = size;
const char16_t* str = (const char16_t*)readInplace((size+1)*sizeof(char16_t));
if (str != nullptr) {
- return str;
+ if (str[size] == u'\0') {
+ return str;
+ }
+ android_errorWriteLog(0x534e4554, "172655291");
}
}
*outLen = 0;
@@ -2198,18 +1794,6 @@
return val;
}
-status_t Parcel::readParcelable(Parcelable* parcelable) const {
- int32_t have_parcelable = 0;
- status_t status = readInt32(&have_parcelable);
- if (status != OK) {
- return status;
- }
- if (!have_parcelable) {
- return UNEXPECTED_NULL;
- }
- return parcelable->readFromParcel(this);
-}
-
int32_t Parcel::readExceptionCode() const
{
binder::Status status;
@@ -2285,7 +1869,7 @@
ssize_t written = TEMP_FAILURE_RETRY(
::write(comm, &message, sizeof(message)));
- if (written == -1 || written != sizeof(message)) {
+ if (written != sizeof(message)) {
ALOGW("Failed to detach ParcelFileDescriptor written: %zd err: %s",
written, strerror(errno));
return BAD_TYPE;
@@ -2328,18 +1912,6 @@
return OK;
}
-status_t Parcel::readUniqueFileDescriptorVector(std::optional<std::vector<base::unique_fd>>* val) const {
- return readNullableTypedVector(val, &Parcel::readUniqueFileDescriptor);
-}
-
-status_t Parcel::readUniqueFileDescriptorVector(std::unique_ptr<std::vector<base::unique_fd>>* val) const {
- return readNullableTypedVector(val, &Parcel::readUniqueFileDescriptor);
-}
-
-status_t Parcel::readUniqueFileDescriptorVector(std::vector<base::unique_fd>* val) const {
- return readTypedVector(val, &Parcel::readUniqueFileDescriptor);
-}
-
status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const
{
int32_t blobType;
@@ -2909,6 +2481,7 @@
mDataPos = 0;
ALOGV("initState Setting data size of %p to %zu", this, mDataSize);
ALOGV("initState Setting data pos of %p to %zu", this, mDataPos);
+ mConnection = nullptr;
mObjects = nullptr;
mObjectsSize = 0;
mObjectsCapacity = 0;
diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp
index c807cfe..406fee0 100644
--- a/libs/binder/PersistableBundle.cpp
+++ b/libs/binder/PersistableBundle.cpp
@@ -31,7 +31,6 @@
using android::BAD_VALUE;
using android::NO_ERROR;
using android::Parcel;
-using android::sp;
using android::status_t;
using android::UNEXPECTED_NULL;
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index c38249e..82f6faf 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -205,10 +205,12 @@
//
// Returns -1 in case of failure, otherwise the strong reference count.
ssize_t ProcessState::getStrongRefCountForNode(const sp<BpBinder>& binder) {
+ if (binder->isRpcBinder()) return -1;
+
binder_node_info_for_ref info;
memset(&info, 0, sizeof(binder_node_info_for_ref));
- info.handle = binder->getPrivateAccessorForHandle().handle();
+ info.handle = binder->getPrivateAccessorForId().binderHandle();
status_t result = ioctl(mDriverFD, BINDER_GET_NODE_INFO_FOR_REF, &info);
diff --git a/libs/binder/RpcAddress.cpp b/libs/binder/RpcAddress.cpp
new file mode 100644
index 0000000..5c32320
--- /dev/null
+++ b/libs/binder/RpcAddress.cpp
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+#include <binder/RpcAddress.h>
+
+#include <binder/Parcel.h>
+
+#include "Debug.h"
+#include "RpcState.h"
+#include "RpcWireFormat.h"
+
+namespace android {
+
+RpcAddress RpcAddress::zero() {
+ return RpcAddress();
+}
+
+bool RpcAddress::isZero() const {
+ RpcWireAddress ZERO{0};
+ return memcmp(mRawAddr.get(), &ZERO, sizeof(RpcWireAddress)) == 0;
+}
+
+static void ReadRandomBytes(uint8_t* buf, size_t len) {
+ int fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
+ if (fd == -1) {
+ ALOGE("%s: cannot read /dev/urandom", __func__);
+ return;
+ }
+
+ size_t n;
+ while ((n = TEMP_FAILURE_RETRY(read(fd, buf, len))) > 0) {
+ len -= n;
+ buf += n;
+ }
+ if (len > 0) {
+ ALOGW("%s: there are %d bytes skipped", __func__, (int)len);
+ }
+ close(fd);
+}
+
+RpcAddress RpcAddress::unique() {
+ RpcAddress ret;
+ ReadRandomBytes((uint8_t*)ret.mRawAddr.get(), sizeof(RpcWireAddress));
+ LOG_RPC_DETAIL("Creating new address: %s", ret.toString().c_str());
+ return ret;
+}
+
+RpcAddress RpcAddress::fromRawEmbedded(const RpcWireAddress* raw) {
+ RpcAddress addr;
+ memcpy(addr.mRawAddr.get(), raw, sizeof(RpcWireAddress));
+ return addr;
+}
+
+const RpcWireAddress& RpcAddress::viewRawEmbedded() const {
+ return *mRawAddr.get();
+}
+
+bool RpcAddress::operator<(const RpcAddress& rhs) const {
+ return std::memcmp(mRawAddr.get(), rhs.mRawAddr.get(), sizeof(RpcWireAddress)) < 0;
+}
+
+std::string RpcAddress::toString() const {
+ return hexString(mRawAddr.get(), sizeof(RpcWireAddress));
+}
+
+status_t RpcAddress::writeToParcel(Parcel* parcel) const {
+ return parcel->write(mRawAddr.get(), sizeof(RpcWireAddress));
+}
+
+status_t RpcAddress::readFromParcel(const Parcel& parcel) {
+ return parcel.read(mRawAddr.get(), sizeof(RpcWireAddress));
+}
+
+RpcAddress::~RpcAddress() {}
+RpcAddress::RpcAddress() : mRawAddr(std::make_shared<RpcWireAddress>()) {}
+
+} // namespace android
diff --git a/libs/binder/RpcConnection.cpp b/libs/binder/RpcConnection.cpp
new file mode 100644
index 0000000..dab3246
--- /dev/null
+++ b/libs/binder/RpcConnection.cpp
@@ -0,0 +1,349 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "RpcConnection"
+
+#include <binder/RpcConnection.h>
+
+#include <binder/Parcel.h>
+#include <binder/Stability.h>
+#include <utils/String8.h>
+
+#include "RpcState.h"
+#include "RpcWireFormat.h"
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#ifdef __GLIBC__
+extern "C" pid_t gettid();
+#endif
+
+#ifdef __BIONIC__
+#include <linux/vm_sockets.h>
+#endif
+
+namespace android {
+
+using base::unique_fd;
+
+RpcConnection::SocketAddress::~SocketAddress() {}
+
+RpcConnection::RpcConnection() {
+ LOG_RPC_DETAIL("RpcConnection created %p", this);
+
+ mState = std::make_unique<RpcState>();
+}
+RpcConnection::~RpcConnection() {
+ LOG_RPC_DETAIL("RpcConnection destroyed %p", this);
+}
+
+sp<RpcConnection> RpcConnection::make() {
+ return new RpcConnection;
+}
+
+class UnixSocketAddress : public RpcConnection::SocketAddress {
+public:
+ explicit UnixSocketAddress(const char* path) : mAddr({.sun_family = AF_UNIX}) {
+ unsigned int pathLen = strlen(path) + 1;
+ LOG_ALWAYS_FATAL_IF(pathLen > sizeof(mAddr.sun_path), "%u %s", pathLen, path);
+ memcpy(mAddr.sun_path, path, pathLen);
+ }
+ virtual ~UnixSocketAddress() {}
+ std::string toString() const override {
+ return String8::format("path '%.*s'", static_cast<int>(sizeof(mAddr.sun_path)),
+ mAddr.sun_path)
+ .c_str();
+ }
+ const sockaddr* addr() const override { return reinterpret_cast<const sockaddr*>(&mAddr); }
+ size_t addrSize() const override { return sizeof(mAddr); }
+
+private:
+ sockaddr_un mAddr;
+};
+
+bool RpcConnection::setupUnixDomainServer(const char* path) {
+ return addServer(UnixSocketAddress(path));
+}
+
+bool RpcConnection::addUnixDomainClient(const char* path) {
+ return addClient(UnixSocketAddress(path));
+}
+
+#ifdef __BIONIC__
+
+class VsockSocketAddress : public RpcConnection::SocketAddress {
+public:
+ VsockSocketAddress(unsigned int cid, unsigned int port)
+ : mAddr({
+ .svm_family = AF_VSOCK,
+ .svm_port = port,
+ .svm_cid = cid,
+ }) {}
+ virtual ~VsockSocketAddress() {}
+ std::string toString() const override {
+ return String8::format("cid %du port %du", mAddr.svm_cid, mAddr.svm_port).c_str();
+ }
+ const sockaddr* addr() const override { return reinterpret_cast<const sockaddr*>(&mAddr); }
+ size_t addrSize() const override { return sizeof(mAddr); }
+
+private:
+ sockaddr_vm mAddr;
+};
+
+bool RpcConnection::setupVsockServer(unsigned int port) {
+ // realizing value w/ this type at compile time to avoid ubsan abort
+ constexpr unsigned int kAnyCid = VMADDR_CID_ANY;
+
+ return addServer(VsockSocketAddress(kAnyCid, port));
+}
+
+bool RpcConnection::addVsockClient(unsigned int cid, unsigned int port) {
+ return addClient(VsockSocketAddress(cid, port));
+}
+
+#endif // __BIONIC__
+
+sp<IBinder> RpcConnection::getRootObject() {
+ ExclusiveSocket socket(this, SocketUse::CLIENT);
+ return state()->getRootObject(socket.fd(), this);
+}
+
+status_t RpcConnection::transact(const RpcAddress& address, uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags) {
+ ExclusiveSocket socket(this,
+ (flags & IBinder::FLAG_ONEWAY) ? SocketUse::CLIENT_ASYNC
+ : SocketUse::CLIENT);
+ return state()->transact(socket.fd(), address, code, data, this, reply, flags);
+}
+
+status_t RpcConnection::sendDecStrong(const RpcAddress& address) {
+ ExclusiveSocket socket(this, SocketUse::CLIENT_REFCOUNT);
+ return state()->sendDecStrong(socket.fd(), address);
+}
+
+void RpcConnection::join() {
+ // establish a connection
+ {
+ unique_fd clientFd(
+ TEMP_FAILURE_RETRY(accept4(mServer.get(), nullptr, 0 /*length*/, SOCK_CLOEXEC)));
+ if (clientFd < 0) {
+ // If this log becomes confusing, should save more state from setupUnixDomainServer
+ // in order to output here.
+ ALOGE("Could not accept4 socket: %s", strerror(errno));
+ return;
+ }
+
+ LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get());
+
+ assignServerToThisThread(std::move(clientFd));
+ }
+
+ // We may not use the connection we just established (two threads might
+ // establish connections for each other), but for now, just use one
+ // server/socket connection.
+ ExclusiveSocket socket(this, SocketUse::SERVER);
+
+ while (true) {
+ status_t error = state()->getAndExecuteCommand(socket.fd(), this);
+
+ if (error != OK) {
+ ALOGI("Binder socket thread closing w/ status %s", statusToString(error).c_str());
+ return;
+ }
+ }
+}
+
+void RpcConnection::setForServer(const wp<RpcServer>& server) {
+ mForServer = server;
+}
+
+wp<RpcServer> RpcConnection::server() {
+ return mForServer;
+}
+
+bool RpcConnection::addServer(const SocketAddress& addr) {
+ LOG_ALWAYS_FATAL_IF(mServer.get() != -1, "Each RpcConnection can only have one server.");
+
+ unique_fd serverFd(
+ TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)));
+ if (serverFd == -1) {
+ ALOGE("Could not create socket: %s", strerror(errno));
+ return false;
+ }
+
+ if (0 != TEMP_FAILURE_RETRY(bind(serverFd.get(), addr.addr(), addr.addrSize()))) {
+ int savedErrno = errno;
+ ALOGE("Could not bind socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
+ return false;
+ }
+
+ if (0 != TEMP_FAILURE_RETRY(listen(serverFd.get(), 1 /*backlog*/))) {
+ int savedErrno = errno;
+ ALOGE("Could not listen socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
+ return false;
+ }
+
+ mServer = std::move(serverFd);
+ return true;
+}
+
+bool RpcConnection::addClient(const SocketAddress& addr) {
+ unique_fd serverFd(
+ TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)));
+ if (serverFd == -1) {
+ int savedErrno = errno;
+ ALOGE("Could not create socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
+ return false;
+ }
+
+ if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), addr.addr(), addr.addrSize()))) {
+ int savedErrno = errno;
+ ALOGE("Could not connect socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
+ return false;
+ }
+
+ LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get());
+
+ std::lock_guard<std::mutex> _l(mSocketMutex);
+ sp<ConnectionSocket> connection = new ConnectionSocket();
+ connection->fd = std::move(serverFd);
+ mClients.push_back(connection);
+ return true;
+}
+
+void RpcConnection::assignServerToThisThread(base::unique_fd&& fd) {
+ std::lock_guard<std::mutex> _l(mSocketMutex);
+ sp<ConnectionSocket> connection = new ConnectionSocket();
+ connection->fd = std::move(fd);
+ mServers.push_back(connection);
+}
+
+RpcConnection::ExclusiveSocket::ExclusiveSocket(const sp<RpcConnection>& connection, SocketUse use)
+ : mConnection(connection) {
+ pid_t tid = gettid();
+ std::unique_lock<std::mutex> _l(mConnection->mSocketMutex);
+
+ mConnection->mWaitingThreads++;
+ while (true) {
+ sp<ConnectionSocket> exclusive;
+ sp<ConnectionSocket> available;
+
+ // CHECK FOR DEDICATED CLIENT SOCKET
+ //
+ // A server/looper should always use a dedicated connection.
+ if (use != SocketUse::SERVER) {
+ findSocket(tid, &exclusive, &available, mConnection->mClients,
+ mConnection->mClientsOffset);
+
+ // WARNING: this assumes a server cannot request its client to send
+ // a transaction, as mServers is excluded below.
+ //
+ // Imagine we have more than one thread in play, and a single thread
+ // sends a synchronous, then an asynchronous command. Imagine the
+ // asynchronous command is sent on the first client socket. Then, if
+ // we naively send a synchronous command to that same socket, the
+ // thread on the far side might be busy processing the asynchronous
+ // command. So, we move to considering the second available thread
+ // for subsequent calls.
+ if (use == SocketUse::CLIENT_ASYNC && (exclusive != nullptr || available != nullptr)) {
+ mConnection->mClientsOffset =
+ (mConnection->mClientsOffset + 1) % mConnection->mClients.size();
+ }
+ }
+
+ // USE SERVING SOCKET (to start serving or for nested transaction)
+ //
+ // asynchronous calls cannot be nested
+ if (use != SocketUse::CLIENT_ASYNC) {
+ // servers should start serving on an available thread only
+ // otherwise, this should only be a nested call
+ bool useAvailable = use == SocketUse::SERVER;
+
+ findSocket(tid, &exclusive, (useAvailable ? &available : nullptr),
+ mConnection->mServers, 0 /* index hint */);
+ }
+
+ // if our thread is already using a connection, prioritize using that
+ if (exclusive != nullptr) {
+ mSocket = exclusive;
+ mReentrant = true;
+ break;
+ } else if (available != nullptr) {
+ mSocket = available;
+ mSocket->exclusiveTid = tid;
+ break;
+ }
+
+ LOG_ALWAYS_FATAL_IF(use == SocketUse::SERVER, "Must create connection to join one.");
+
+ // in regular binder, this would usually be a deadlock :)
+ LOG_ALWAYS_FATAL_IF(mConnection->mClients.size() == 0,
+ "Not a client of any connection. You must create a connection to an "
+ "RPC server to make any non-nested (e.g. oneway or on another thread) "
+ "calls.");
+
+ LOG_RPC_DETAIL("No available connection (have %zu clients and %zu servers). Waiting...",
+ mConnection->mClients.size(), mConnection->mServers.size());
+ mConnection->mSocketCv.wait(_l);
+ }
+ mConnection->mWaitingThreads--;
+}
+
+void RpcConnection::ExclusiveSocket::findSocket(pid_t tid, sp<ConnectionSocket>* exclusive,
+ sp<ConnectionSocket>* available,
+ std::vector<sp<ConnectionSocket>>& sockets,
+ size_t socketsIndexHint) {
+ LOG_ALWAYS_FATAL_IF(sockets.size() > 0 && socketsIndexHint >= sockets.size(),
+ "Bad index %zu >= %zu", socketsIndexHint, sockets.size());
+
+ if (*exclusive != nullptr) return; // consistent with break below
+
+ for (size_t i = 0; i < sockets.size(); i++) {
+ sp<ConnectionSocket>& socket = sockets[(i + socketsIndexHint) % sockets.size()];
+
+ // take first available connection (intuition = caching)
+ if (available && *available == nullptr && socket->exclusiveTid == std::nullopt) {
+ *available = socket;
+ continue;
+ }
+
+ // though, prefer to take connection which is already inuse by this thread
+ // (nested transactions)
+ if (exclusive && socket->exclusiveTid == tid) {
+ *exclusive = socket;
+ break; // consistent with return above
+ }
+ }
+}
+
+RpcConnection::ExclusiveSocket::~ExclusiveSocket() {
+ // reentrant use of a connection means something less deep in the call stack
+ // is using this fd, and it retains the right to it. So, we don't give up
+ // exclusive ownership, and no thread is freed.
+ if (!mReentrant) {
+ std::unique_lock<std::mutex> _l(mConnection->mSocketMutex);
+ mSocket->exclusiveTid = std::nullopt;
+ if (mConnection->mWaitingThreads > 0) {
+ _l.unlock();
+ mConnection->mSocketCv.notify_one();
+ }
+ }
+}
+
+} // namespace android
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
new file mode 100644
index 0000000..df07916
--- /dev/null
+++ b/libs/binder/RpcServer.cpp
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "RpcServer"
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <vector>
+
+#include <binder/Parcel.h>
+#include <binder/RpcServer.h>
+#include <log/log.h>
+#include "RpcState.h"
+
+#include "RpcWireFormat.h"
+
+namespace android {
+
+using base::unique_fd;
+
+RpcServer::RpcServer() {}
+RpcServer::~RpcServer() {}
+
+sp<RpcServer> RpcServer::make() {
+ return new RpcServer;
+}
+
+void RpcServer::iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction() {
+ mAgreedExperimental = true;
+}
+
+sp<RpcConnection> RpcServer::addClientConnection() {
+ LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
+
+ auto connection = RpcConnection::make();
+ connection->setForServer(this);
+ mConnections.push_back(connection);
+ return connection;
+}
+
+void RpcServer::setRootObject(const sp<IBinder>& binder) {
+ LOG_ALWAYS_FATAL_IF(mRootObject != nullptr, "There can only be one root object");
+ mRootObject = binder;
+}
+
+sp<IBinder> RpcServer::getRootObject() {
+ return mRootObject;
+}
+
+} // namespace android
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
new file mode 100644
index 0000000..64e842e
--- /dev/null
+++ b/libs/binder/RpcState.cpp
@@ -0,0 +1,663 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "RpcState"
+
+#include "RpcState.h"
+
+#include <binder/BpBinder.h>
+#include <binder/RpcServer.h>
+
+#include "Debug.h"
+#include "RpcWireFormat.h"
+
+#include <inttypes.h>
+
+namespace android {
+
+RpcState::RpcState() {}
+RpcState::~RpcState() {}
+
+status_t RpcState::onBinderLeaving(const sp<RpcConnection>& connection, const sp<IBinder>& binder,
+ RpcAddress* outAddress) {
+ bool isRemote = binder->remoteBinder();
+ bool isRpc = isRemote && binder->remoteBinder()->isRpcBinder();
+
+ if (isRpc && binder->remoteBinder()->getPrivateAccessorForId().rpcConnection() != connection) {
+ // We need to be able to send instructions over the socket for how to
+ // connect to a different server, and we also need to let the host
+ // process know that this is happening.
+ ALOGE("Canot send binder from unrelated binder RPC connection.");
+ return INVALID_OPERATION;
+ }
+
+ if (isRemote && !isRpc) {
+ // Without additional work, this would have the effect of using this
+ // process to proxy calls from the socket over to the other process, and
+ // it would make those calls look like they come from us (not over the
+ // sockets). In order to make this work transparently like binder, we
+ // would instead need to send instructions over the socket for how to
+ // connect to the host process, and we also need to let the host process
+ // know this was happening.
+ ALOGE("Cannot send binder proxy %p over sockets", binder.get());
+ return INVALID_OPERATION;
+ }
+
+ std::lock_guard<std::mutex> _l(mNodeMutex);
+
+ // TODO(b/182939933): maybe move address out of BpBinder, and keep binder->address map
+ // in RpcState
+ for (auto& [addr, node] : mNodeForAddress) {
+ if (binder == node.binder) {
+ if (isRpc) {
+ const RpcAddress& actualAddr =
+ binder->remoteBinder()->getPrivateAccessorForId().rpcAddress();
+ // TODO(b/182939933): this is only checking integrity of data structure
+ // a different data structure doesn't need this
+ LOG_ALWAYS_FATAL_IF(addr < actualAddr, "Address mismatch");
+ LOG_ALWAYS_FATAL_IF(actualAddr < addr, "Address mismatch");
+ }
+ node.timesSent++;
+ node.sentRef = binder; // might already be set
+ *outAddress = addr;
+ return OK;
+ }
+ }
+ LOG_ALWAYS_FATAL_IF(isRpc, "RPC binder must have known address at this point");
+
+ auto&& [it, inserted] = mNodeForAddress.insert({RpcAddress::unique(),
+ BinderNode{
+ .binder = binder,
+ .timesSent = 1,
+ .sentRef = binder,
+ }});
+ // TODO(b/182939933): better organization could avoid needing this log
+ LOG_ALWAYS_FATAL_IF(!inserted);
+
+ *outAddress = it->first;
+ return OK;
+}
+
+sp<IBinder> RpcState::onBinderEntering(const sp<RpcConnection>& connection,
+ const RpcAddress& address) {
+ std::unique_lock<std::mutex> _l(mNodeMutex);
+
+ if (auto it = mNodeForAddress.find(address); it != mNodeForAddress.end()) {
+ sp<IBinder> binder = it->second.binder.promote();
+
+ // implicitly have strong RPC refcount, since we received this binder
+ it->second.timesRecd++;
+
+ _l.unlock();
+
+ // We have timesRecd RPC refcounts, but we only need to hold on to one
+ // when we keep the object. All additional dec strongs are sent
+ // immediately, we wait to send the last one in BpBinder::onLastDecStrong.
+ (void)connection->sendDecStrong(address);
+
+ return binder;
+ }
+
+ auto&& [it, inserted] = mNodeForAddress.insert({address, BinderNode{}});
+ LOG_ALWAYS_FATAL_IF(!inserted, "Failed to insert binder when creating proxy");
+
+ // Currently, all binders are assumed to be part of the same connection (no
+ // device global binders in the RPC world).
+ sp<IBinder> binder = BpBinder::create(connection, it->first);
+ it->second.binder = binder;
+ it->second.timesRecd = 1;
+ return binder;
+}
+
+size_t RpcState::countBinders() {
+ std::lock_guard<std::mutex> _l(mNodeMutex);
+ return mNodeForAddress.size();
+}
+
+void RpcState::dump() {
+ std::lock_guard<std::mutex> _l(mNodeMutex);
+ ALOGE("DUMP OF RpcState %p", this);
+ ALOGE("DUMP OF RpcState (%zu nodes)", mNodeForAddress.size());
+ for (const auto& [address, node] : mNodeForAddress) {
+ sp<IBinder> binder = node.binder.promote();
+
+ const char* desc;
+ if (binder) {
+ if (binder->remoteBinder()) {
+ if (binder->remoteBinder()->isRpcBinder()) {
+ desc = "(rpc binder proxy)";
+ } else {
+ desc = "(binder proxy)";
+ }
+ } else {
+ desc = "(local binder)";
+ }
+ } else {
+ desc = "(null)";
+ }
+
+ ALOGE("- BINDER NODE: %p times sent:%zu times recd: %zu a:%s type:%s",
+ node.binder.unsafe_get(), node.timesSent, node.timesRecd, address.toString().c_str(),
+ desc);
+ }
+ ALOGE("END DUMP OF RpcState");
+}
+
+void RpcState::terminate() {
+ if (SHOULD_LOG_RPC_DETAIL) {
+ ALOGE("RpcState::terminate()");
+ dump();
+ }
+
+ // if the destructor of a binder object makes another RPC call, then calling
+ // decStrong could deadlock. So, we must hold onto these binders until
+ // mNodeMutex is no longer taken.
+ std::vector<sp<IBinder>> tempHoldBinder;
+
+ {
+ std::lock_guard<std::mutex> _l(mNodeMutex);
+ mTerminated = true;
+ for (auto& [address, node] : mNodeForAddress) {
+ sp<IBinder> binder = node.binder.promote();
+ LOG_ALWAYS_FATAL_IF(binder == nullptr, "Binder %p expected to be owned.", binder.get());
+
+ if (node.sentRef != nullptr) {
+ tempHoldBinder.push_back(node.sentRef);
+ }
+ }
+
+ mNodeForAddress.clear();
+ }
+}
+
+bool RpcState::rpcSend(const base::unique_fd& fd, const char* what, const void* data, size_t size) {
+ LOG_RPC_DETAIL("Sending %s on fd %d: %s", what, fd.get(), hexString(data, size).c_str());
+
+ if (size > std::numeric_limits<ssize_t>::max()) {
+ ALOGE("Cannot send %s at size %zu (too big)", what, size);
+ terminate();
+ return false;
+ }
+
+ ssize_t sent = TEMP_FAILURE_RETRY(send(fd.get(), data, size, 0));
+
+ if (sent < 0 || sent != static_cast<ssize_t>(size)) {
+ ALOGE("Failed to send %s (sent %zd of %zu bytes) on fd %d, error: %s", what, sent, size,
+ fd.get(), strerror(errno));
+
+ terminate();
+ return false;
+ }
+
+ return true;
+}
+
+bool RpcState::rpcRec(const base::unique_fd& fd, const char* what, void* data, size_t size) {
+ if (size > std::numeric_limits<ssize_t>::max()) {
+ ALOGE("Cannot rec %s at size %zu (too big)", what, size);
+ terminate();
+ return false;
+ }
+
+ ssize_t recd = TEMP_FAILURE_RETRY(recv(fd.get(), data, size, MSG_WAITALL));
+
+ if (recd < 0 || recd != static_cast<ssize_t>(size)) {
+ terminate();
+
+ if (recd == 0 && errno == 0) {
+ LOG_RPC_DETAIL("No more data when trying to read %s on fd %d", what, fd.get());
+ return false;
+ }
+
+ ALOGE("Failed to read %s (received %zd of %zu bytes) on fd %d, error: %s", what, recd, size,
+ fd.get(), strerror(errno));
+ return false;
+ } else {
+ LOG_RPC_DETAIL("Received %s on fd %d: %s", what, fd.get(), hexString(data, size).c_str());
+ }
+
+ return true;
+}
+
+sp<IBinder> RpcState::getRootObject(const base::unique_fd& fd,
+ const sp<RpcConnection>& connection) {
+ Parcel data;
+ data.markForRpc(connection);
+ Parcel reply;
+
+ status_t status = transact(fd, RpcAddress::zero(), RPC_SPECIAL_TRANSACT_GET_ROOT, data,
+ connection, &reply, 0);
+ if (status != OK) {
+ ALOGE("Error getting root object: %s", statusToString(status).c_str());
+ return nullptr;
+ }
+
+ return reply.readStrongBinder();
+}
+
+status_t RpcState::transact(const base::unique_fd& fd, const RpcAddress& address, uint32_t code,
+ const Parcel& data, const sp<RpcConnection>& connection, Parcel* reply,
+ uint32_t flags) {
+ uint64_t asyncNumber = 0;
+
+ if (!address.isZero()) {
+ std::lock_guard<std::mutex> _l(mNodeMutex);
+ if (mTerminated) return DEAD_OBJECT; // avoid fatal only, otherwise races
+ auto it = mNodeForAddress.find(address);
+ LOG_ALWAYS_FATAL_IF(it == mNodeForAddress.end(), "Sending transact on unknown address %s",
+ address.toString().c_str());
+
+ if (flags & IBinder::FLAG_ONEWAY) {
+ asyncNumber = it->second.asyncNumber++;
+ }
+ }
+
+ if (!data.isForRpc()) {
+ ALOGE("Refusing to send RPC with parcel not crafted for RPC");
+ return BAD_TYPE;
+ }
+
+ if (data.objectsCount() != 0) {
+ ALOGE("Parcel at %p has attached objects but is being used in an RPC call", &data);
+ return BAD_TYPE;
+ }
+
+ RpcWireTransaction transaction{
+ .address = address.viewRawEmbedded(),
+ .code = code,
+ .flags = flags,
+ .asyncNumber = asyncNumber,
+ };
+
+ std::vector<uint8_t> transactionData(sizeof(RpcWireTransaction) + data.dataSize());
+ memcpy(transactionData.data() + 0, &transaction, sizeof(RpcWireTransaction));
+ memcpy(transactionData.data() + sizeof(RpcWireTransaction), data.data(), data.dataSize());
+
+ if (transactionData.size() > std::numeric_limits<uint32_t>::max()) {
+ ALOGE("Transaction size too big %zu", transactionData.size());
+ return BAD_VALUE;
+ }
+
+ RpcWireHeader command{
+ .command = RPC_COMMAND_TRANSACT,
+ .bodySize = static_cast<uint32_t>(transactionData.size()),
+ };
+
+ if (!rpcSend(fd, "transact header", &command, sizeof(command))) {
+ return DEAD_OBJECT;
+ }
+ if (!rpcSend(fd, "command body", transactionData.data(), transactionData.size())) {
+ return DEAD_OBJECT;
+ }
+
+ if (flags & IBinder::FLAG_ONEWAY) {
+ return OK; // do not wait for result
+ }
+
+ LOG_ALWAYS_FATAL_IF(reply == nullptr, "Reply parcel must be used for synchronous transaction.");
+
+ return waitForReply(fd, connection, reply);
+}
+
+static void cleanup_data(Parcel* p, const uint8_t* data, size_t dataSize,
+ const binder_size_t* objects, size_t objectsCount) {
+ (void)p;
+ delete[] const_cast<uint8_t*>(data - offsetof(RpcWireReply, data));
+ (void)dataSize;
+ LOG_ALWAYS_FATAL_IF(objects != nullptr);
+ LOG_ALWAYS_FATAL_IF(objectsCount, 0);
+}
+
+status_t RpcState::waitForReply(const base::unique_fd& fd, const sp<RpcConnection>& connection,
+ Parcel* reply) {
+ RpcWireHeader command;
+ while (true) {
+ if (!rpcRec(fd, "command header", &command, sizeof(command))) {
+ return DEAD_OBJECT;
+ }
+
+ if (command.command == RPC_COMMAND_REPLY) break;
+
+ status_t status = processServerCommand(fd, connection, command);
+ if (status != OK) return status;
+ }
+
+ uint8_t* data = new uint8_t[command.bodySize];
+
+ if (!rpcRec(fd, "reply body", data, command.bodySize)) {
+ return DEAD_OBJECT;
+ }
+
+ if (command.bodySize < sizeof(RpcWireReply)) {
+ ALOGE("Expecting %zu but got %" PRId32 " bytes for RpcWireReply. Terminating!",
+ sizeof(RpcWireReply), command.bodySize);
+ terminate();
+ return BAD_VALUE;
+ }
+ RpcWireReply* rpcReply = reinterpret_cast<RpcWireReply*>(data);
+ if (rpcReply->status != OK) return rpcReply->status;
+
+ reply->ipcSetDataReference(rpcReply->data, command.bodySize - offsetof(RpcWireReply, data),
+ nullptr, 0, cleanup_data);
+
+ reply->markForRpc(connection);
+
+ return OK;
+}
+
+status_t RpcState::sendDecStrong(const base::unique_fd& fd, const RpcAddress& addr) {
+ {
+ std::lock_guard<std::mutex> _l(mNodeMutex);
+ if (mTerminated) return DEAD_OBJECT; // avoid fatal only, otherwise races
+ auto it = mNodeForAddress.find(addr);
+ LOG_ALWAYS_FATAL_IF(it == mNodeForAddress.end(), "Sending dec strong on unknown address %s",
+ addr.toString().c_str());
+ LOG_ALWAYS_FATAL_IF(it->second.timesRecd <= 0, "Bad dec strong %s",
+ addr.toString().c_str());
+
+ it->second.timesRecd--;
+ if (it->second.timesRecd == 0 && it->second.timesSent == 0) {
+ mNodeForAddress.erase(it);
+ }
+ }
+
+ RpcWireHeader cmd = {
+ .command = RPC_COMMAND_DEC_STRONG,
+ .bodySize = sizeof(RpcWireAddress),
+ };
+ if (!rpcSend(fd, "dec ref header", &cmd, sizeof(cmd))) return DEAD_OBJECT;
+ if (!rpcSend(fd, "dec ref body", &addr.viewRawEmbedded(), sizeof(RpcWireAddress)))
+ return DEAD_OBJECT;
+ return OK;
+}
+
+status_t RpcState::getAndExecuteCommand(const base::unique_fd& fd,
+ const sp<RpcConnection>& connection) {
+ LOG_RPC_DETAIL("getAndExecuteCommand on fd %d", fd.get());
+
+ RpcWireHeader command;
+ if (!rpcRec(fd, "command header", &command, sizeof(command))) {
+ return DEAD_OBJECT;
+ }
+
+ return processServerCommand(fd, connection, command);
+}
+
+status_t RpcState::processServerCommand(const base::unique_fd& fd,
+ const sp<RpcConnection>& connection,
+ const RpcWireHeader& command) {
+ switch (command.command) {
+ case RPC_COMMAND_TRANSACT:
+ return processTransact(fd, connection, command);
+ case RPC_COMMAND_DEC_STRONG:
+ return processDecStrong(fd, command);
+ }
+
+ // We should always know the version of the opposing side, and since the
+ // RPC-binder-level wire protocol is not self synchronizing, we have no way
+ // to understand where the current command ends and the next one begins. We
+ // also can't consider it a fatal error because this would allow any client
+ // to kill us, so ending the connection for misbehaving client.
+ ALOGE("Unknown RPC command %d - terminating connection", command.command);
+ terminate();
+ return DEAD_OBJECT;
+}
+status_t RpcState::processTransact(const base::unique_fd& fd, const sp<RpcConnection>& connection,
+ const RpcWireHeader& command) {
+ LOG_ALWAYS_FATAL_IF(command.command != RPC_COMMAND_TRANSACT, "command: %d", command.command);
+
+ std::vector<uint8_t> transactionData(command.bodySize);
+ if (!rpcRec(fd, "transaction body", transactionData.data(), transactionData.size())) {
+ return DEAD_OBJECT;
+ }
+
+ return processTransactInternal(fd, connection, std::move(transactionData));
+}
+
+status_t RpcState::processTransactInternal(const base::unique_fd& fd,
+ const sp<RpcConnection>& connection,
+ std::vector<uint8_t>&& transactionData) {
+ if (transactionData.size() < sizeof(RpcWireTransaction)) {
+ ALOGE("Expecting %zu but got %zu bytes for RpcWireTransaction. Terminating!",
+ sizeof(RpcWireTransaction), transactionData.size());
+ terminate();
+ return BAD_VALUE;
+ }
+ RpcWireTransaction* transaction = reinterpret_cast<RpcWireTransaction*>(transactionData.data());
+
+ // TODO(b/182939933): heap allocation just for lookup in mNodeForAddress,
+ // maybe add an RpcAddress 'view' if the type remains 'heavy'
+ auto addr = RpcAddress::fromRawEmbedded(&transaction->address);
+
+ status_t replyStatus = OK;
+ sp<IBinder> target;
+ if (!addr.isZero()) {
+ std::lock_guard<std::mutex> _l(mNodeMutex);
+
+ auto it = mNodeForAddress.find(addr);
+ if (it == mNodeForAddress.end()) {
+ ALOGE("Unknown binder address %s.", addr.toString().c_str());
+ dump();
+ replyStatus = BAD_VALUE;
+ } else {
+ target = it->second.binder.promote();
+ if (target == nullptr) {
+ // This can happen if the binder is remote in this process, and
+ // another thread has called the last decStrong on this binder.
+ // However, for local binders, it indicates a misbehaving client
+ // (any binder which is being transacted on should be holding a
+ // strong ref count), so in either case, terminating the
+ // connection.
+ ALOGE("While transacting, binder has been deleted at address %s. Terminating!",
+ addr.toString().c_str());
+ terminate();
+ replyStatus = BAD_VALUE;
+ } else if (target->localBinder() == nullptr) {
+ ALOGE("Transactions can only go to local binders, not address %s. Terminating!",
+ addr.toString().c_str());
+ terminate();
+ replyStatus = BAD_VALUE;
+ } else if (transaction->flags & IBinder::FLAG_ONEWAY) {
+ if (transaction->asyncNumber != it->second.asyncNumber) {
+ // we need to process some other asynchronous transaction
+ // first
+ // TODO(b/183140903): limit enqueues/detect overfill for bad client
+ // TODO(b/183140903): detect when an object is deleted when it still has
+ // pending async transactions
+ it->second.asyncTodo.push(BinderNode::AsyncTodo{
+ .data = std::move(transactionData),
+ .asyncNumber = transaction->asyncNumber,
+ });
+ LOG_RPC_DETAIL("Enqueuing %" PRId64 " on %s", transaction->asyncNumber,
+ addr.toString().c_str());
+ return OK;
+ }
+ }
+ }
+ }
+
+ Parcel data;
+ data.setData(transaction->data, transactionData.size() - offsetof(RpcWireTransaction, data));
+ data.markForRpc(connection);
+
+ Parcel reply;
+ reply.markForRpc(connection);
+
+ if (replyStatus == OK) {
+ if (target) {
+ replyStatus = target->transact(transaction->code, data, &reply, transaction->flags);
+ } else {
+ LOG_RPC_DETAIL("Got special transaction %u", transaction->code);
+ // special case for 'zero' address (special server commands)
+ switch (transaction->code) {
+ case RPC_SPECIAL_TRANSACT_GET_ROOT: {
+ sp<IBinder> root;
+ sp<RpcServer> server = connection->server().promote();
+ if (server) {
+ root = server->getRootObject();
+ } else {
+ ALOGE("Root object requested, but no server attached.");
+ }
+
+ replyStatus = reply.writeStrongBinder(root);
+ break;
+ }
+ default: {
+ replyStatus = UNKNOWN_TRANSACTION;
+ }
+ }
+ }
+ }
+
+ if (transaction->flags & IBinder::FLAG_ONEWAY) {
+ if (replyStatus != OK) {
+ ALOGW("Oneway call failed with error: %d", replyStatus);
+ }
+
+ LOG_RPC_DETAIL("Processed async transaction %" PRId64 " on %s", transaction->asyncNumber,
+ addr.toString().c_str());
+
+ // Check to see if there is another asynchronous transaction to process.
+ // This behavior differs from binder behavior, since in the binder
+ // driver, asynchronous transactions will be processed after existing
+ // pending binder transactions on the queue. The downside of this is
+ // that asynchronous transactions can be drowned out by synchronous
+ // transactions. However, we have no easy way to queue these
+ // transactions after the synchronous transactions we may want to read
+ // from the wire. So, in socket binder here, we have the opposite
+ // downside: asynchronous transactions may drown out synchronous
+ // transactions.
+ {
+ std::unique_lock<std::mutex> _l(mNodeMutex);
+ auto it = mNodeForAddress.find(addr);
+ // last refcount dropped after this transaction happened
+ if (it == mNodeForAddress.end()) return OK;
+
+ // note - only updated now, instead of later, so that other threads
+ // will queue any later transactions
+
+ // TODO(b/183140903): support > 2**64 async transactions
+ // (we can do this by allowing asyncNumber to wrap, since we
+ // don't expect more than 2**64 simultaneous transactions)
+ it->second.asyncNumber++;
+
+ if (it->second.asyncTodo.size() == 0) return OK;
+ if (it->second.asyncTodo.top().asyncNumber == it->second.asyncNumber) {
+ LOG_RPC_DETAIL("Found next async transaction %" PRId64 " on %s",
+ it->second.asyncNumber, addr.toString().c_str());
+
+ // justification for const_cast (consider avoiding priority_queue):
+ // - AsyncTodo operator< doesn't depend on 'data' object
+ // - gotta go fast
+ std::vector<uint8_t> data = std::move(
+ const_cast<BinderNode::AsyncTodo&>(it->second.asyncTodo.top()).data);
+ it->second.asyncTodo.pop();
+ _l.unlock();
+ return processTransactInternal(fd, connection, std::move(data));
+ }
+ }
+ return OK;
+ }
+
+ RpcWireReply rpcReply{
+ .status = replyStatus,
+ };
+
+ std::vector<uint8_t> replyData(sizeof(RpcWireReply) + reply.dataSize());
+ memcpy(replyData.data() + 0, &rpcReply, sizeof(RpcWireReply));
+ memcpy(replyData.data() + sizeof(RpcWireReply), reply.data(), reply.dataSize());
+
+ if (replyData.size() > std::numeric_limits<uint32_t>::max()) {
+ ALOGE("Reply size too big %zu", transactionData.size());
+ terminate();
+ return BAD_VALUE;
+ }
+
+ RpcWireHeader cmdReply{
+ .command = RPC_COMMAND_REPLY,
+ .bodySize = static_cast<uint32_t>(replyData.size()),
+ };
+
+ if (!rpcSend(fd, "reply header", &cmdReply, sizeof(RpcWireHeader))) {
+ return DEAD_OBJECT;
+ }
+ if (!rpcSend(fd, "reply body", replyData.data(), replyData.size())) {
+ return DEAD_OBJECT;
+ }
+ return OK;
+}
+
+status_t RpcState::processDecStrong(const base::unique_fd& fd, const RpcWireHeader& command) {
+ LOG_ALWAYS_FATAL_IF(command.command != RPC_COMMAND_DEC_STRONG, "command: %d", command.command);
+
+ std::vector<uint8_t> commandData(command.bodySize);
+ if (!rpcRec(fd, "dec ref body", commandData.data(), commandData.size())) {
+ return DEAD_OBJECT;
+ }
+
+ if (command.bodySize < sizeof(RpcWireAddress)) {
+ ALOGE("Expecting %zu but got %" PRId32 " bytes for RpcWireAddress. Terminating!",
+ sizeof(RpcWireAddress), command.bodySize);
+ terminate();
+ return BAD_VALUE;
+ }
+ RpcWireAddress* address = reinterpret_cast<RpcWireAddress*>(commandData.data());
+
+ // TODO(b/182939933): heap allocation just for lookup
+ auto addr = RpcAddress::fromRawEmbedded(address);
+ std::unique_lock<std::mutex> _l(mNodeMutex);
+ auto it = mNodeForAddress.find(addr);
+ if (it == mNodeForAddress.end()) {
+ ALOGE("Unknown binder address %s for dec strong.", addr.toString().c_str());
+ dump();
+ return OK;
+ }
+
+ sp<IBinder> target = it->second.binder.promote();
+ if (target == nullptr) {
+ ALOGE("While requesting dec strong, binder has been deleted at address %s. Terminating!",
+ addr.toString().c_str());
+ terminate();
+ return BAD_VALUE;
+ }
+
+ if (it->second.timesSent == 0) {
+ ALOGE("No record of sending binder, but requested decStrong: %s", addr.toString().c_str());
+ return OK;
+ }
+
+ LOG_ALWAYS_FATAL_IF(it->second.sentRef == nullptr, "Inconsistent state, lost ref for %s",
+ addr.toString().c_str());
+
+ sp<IBinder> tempHold;
+
+ it->second.timesSent--;
+ if (it->second.timesSent == 0) {
+ tempHold = it->second.sentRef;
+ it->second.sentRef = nullptr;
+
+ if (it->second.timesRecd == 0) {
+ mNodeForAddress.erase(it);
+ }
+ }
+
+ _l.unlock();
+ tempHold = nullptr; // destructor may make binder calls on this connection
+
+ return OK;
+}
+
+} // namespace android
diff --git a/libs/binder/RpcState.h b/libs/binder/RpcState.h
new file mode 100644
index 0000000..f4f5151
--- /dev/null
+++ b/libs/binder/RpcState.h
@@ -0,0 +1,170 @@
+/*
+ * 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 <android-base/unique_fd.h>
+#include <binder/IBinder.h>
+#include <binder/Parcel.h>
+#include <binder/RpcConnection.h>
+
+#include <map>
+#include <queue>
+
+namespace android {
+
+struct RpcWireHeader;
+
+/**
+ * Log a lot more information about RPC calls, when debugging issues. Usually,
+ * you would want to enable this in only one process. If repeated issues require
+ * a specific subset of logs to debug, this could be broken up like
+ * IPCThreadState's.
+ */
+#define SHOULD_LOG_RPC_DETAIL false
+
+#if SHOULD_LOG_RPC_DETAIL
+#define LOG_RPC_DETAIL(...) ALOGI(__VA_ARGS__)
+#else
+#define LOG_RPC_DETAIL(...) ALOGV(__VA_ARGS__) // for type checking
+#endif
+
+/**
+ * Abstracts away management of ref counts and the wire format from
+ * RpcConnection
+ */
+class RpcState {
+public:
+ RpcState();
+ ~RpcState();
+
+ sp<IBinder> getRootObject(const base::unique_fd& fd, const sp<RpcConnection>& connection);
+
+ [[nodiscard]] status_t transact(const base::unique_fd& fd, const RpcAddress& address,
+ uint32_t code, const Parcel& data,
+ const sp<RpcConnection>& connection, Parcel* reply,
+ uint32_t flags);
+ [[nodiscard]] status_t sendDecStrong(const base::unique_fd& fd, const RpcAddress& address);
+ [[nodiscard]] status_t getAndExecuteCommand(const base::unique_fd& fd,
+ const sp<RpcConnection>& connection);
+
+ /**
+ * Called by Parcel for outgoing binders. This implies one refcount of
+ * ownership to the outgoing binder.
+ */
+ [[nodiscard]] status_t onBinderLeaving(const sp<RpcConnection>& connection,
+ const sp<IBinder>& binder, RpcAddress* outAddress);
+
+ /**
+ * Called by Parcel for incoming binders. This either returns the refcount
+ * to the process, if this process already has one, or it takes ownership of
+ * that refcount
+ */
+ sp<IBinder> onBinderEntering(const sp<RpcConnection>& connection, const RpcAddress& address);
+
+ size_t countBinders();
+ void dump();
+
+private:
+ /**
+ * Called when reading or writing data to a connection fails to clean up
+ * data associated with the connection in order to cleanup binders.
+ * Specifically, we have a strong dependency cycle, since BpBinder is
+ * OBJECT_LIFETIME_WEAK (so that onAttemptIncStrong may return true).
+ *
+ * BpBinder -> RpcConnection -> RpcState
+ * ^-----------------------------/
+ *
+ * In the success case, eventually all refcounts should be propagated over
+ * the connection, though this could also be called to eagerly cleanup
+ * the connection.
+ *
+ * WARNING: RpcState is responsible for calling this when the connection is
+ * no longer recoverable.
+ */
+ void terminate();
+
+ [[nodiscard]] bool rpcSend(const base::unique_fd& fd, const char* what, const void* data,
+ size_t size);
+ [[nodiscard]] bool rpcRec(const base::unique_fd& fd, const char* what, void* data, size_t size);
+
+ [[nodiscard]] status_t waitForReply(const base::unique_fd& fd,
+ const sp<RpcConnection>& connection, Parcel* reply);
+ [[nodiscard]] status_t processServerCommand(const base::unique_fd& fd,
+ const sp<RpcConnection>& connection,
+ const RpcWireHeader& command);
+ [[nodiscard]] status_t processTransact(const base::unique_fd& fd,
+ const sp<RpcConnection>& connection,
+ const RpcWireHeader& command);
+ [[nodiscard]] status_t processTransactInternal(const base::unique_fd& fd,
+ const sp<RpcConnection>& connection,
+ std::vector<uint8_t>&& transactionData);
+ [[nodiscard]] status_t processDecStrong(const base::unique_fd& fd,
+ const RpcWireHeader& command);
+
+ struct BinderNode {
+ // Two cases:
+ // A - local binder we are serving
+ // B - remote binder, we are sending transactions to
+ wp<IBinder> binder;
+
+ // if timesSent > 0, this will be equal to binder.promote()
+ sp<IBinder> sentRef;
+
+ // Number of times we've sent this binder out of process, which
+ // translates to an implicit strong count. A client must send RPC binder
+ // socket's dec ref for each time it is sent out of process in order to
+ // deallocate it. Note, a proxy binder we are holding onto might be
+ // sent (this is important when the only remaining refcount of this
+ // binder is the one associated with a transaction sending it back to
+ // its server)
+ size_t timesSent = 0;
+
+ // Number of times we've received this binder, each time corresponds to
+ // a reference we hold over the wire (not a local incStrong/decStrong)
+ size_t timesRecd = 0;
+
+ // transaction ID, for async transactions
+ uint64_t asyncNumber = 0;
+
+ //
+ // CASE A - local binder we are serving
+ //
+
+ // async transaction queue, _only_ for local binder
+ struct AsyncTodo {
+ std::vector<uint8_t> data; // most convenient format, to move it here
+ uint64_t asyncNumber = 0;
+
+ bool operator<(const AsyncTodo& o) const {
+ return asyncNumber > /* !!! */ o.asyncNumber;
+ }
+ };
+ std::priority_queue<AsyncTodo> asyncTodo;
+
+ //
+ // CASE B - remote binder, we are sending transactions to
+ //
+
+ // (no additional data specific to remote binders)
+ };
+
+ std::mutex mNodeMutex;
+ bool mTerminated = false;
+ // binders known by both sides of a connection
+ std::map<RpcAddress, BinderNode> mNodeForAddress;
+};
+
+} // namespace android
diff --git a/libs/binder/RpcWireFormat.h b/libs/binder/RpcWireFormat.h
new file mode 100644
index 0000000..60ec6c9
--- /dev/null
+++ b/libs/binder/RpcWireFormat.h
@@ -0,0 +1,85 @@
+/*
+ * 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
+
+namespace android {
+
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wpadded"
+
+enum : uint32_t {
+ /**
+ * follows is RpcWireTransaction, if flags != oneway, reply w/ RPC_COMMAND_REPLY expected
+ */
+ RPC_COMMAND_TRANSACT = 0,
+ /**
+ * follows is RpcWireReply
+ */
+ RPC_COMMAND_REPLY,
+ /**
+ * follows is RpcWireAddress
+ *
+ * note - this in the protocol directly instead of as a 'special
+ * transaction' in order to keep it as lightweight as possible (we don't
+ * want to create a 'Parcel' object for every decref)
+ */
+ RPC_COMMAND_DEC_STRONG,
+};
+
+/**
+ * These commands are used when the address in an RpcWireTransaction is zero'd
+ * out (no address). This allows the transact/reply flow to be used for
+ * additional server commands, without making the protocol for
+ * transactions/replies more complicated.
+ */
+enum : uint32_t {
+ RPC_SPECIAL_TRANSACT_GET_ROOT = 0,
+};
+
+// serialization is like:
+// |RpcWireHeader|struct desginated by 'command'| (over and over again)
+
+struct RpcWireHeader {
+ uint32_t command; // RPC_COMMAND_*
+ uint32_t bodySize;
+
+ uint32_t reserved[2];
+};
+
+struct RpcWireAddress {
+ uint8_t address[32];
+};
+
+struct RpcWireTransaction {
+ RpcWireAddress address;
+ uint32_t code;
+ uint32_t flags;
+
+ uint64_t asyncNumber;
+
+ uint32_t reserved[4];
+
+ uint8_t data[0];
+};
+
+struct RpcWireReply {
+ int32_t status; // transact return
+ uint8_t data[0];
+};
+
+#pragma clang diagnostic pop
+
+} // namespace android
diff --git a/libs/binder/Stability.cpp b/libs/binder/Stability.cpp
index 339c538..06830c0 100644
--- a/libs/binder/Stability.cpp
+++ b/libs/binder/Stability.cpp
@@ -38,6 +38,18 @@
};
}
+void Stability::forceDowngradeCompilationUnit(const sp<IBinder>& binder) {
+ // Downgrading a remote binder would require also copying the version from
+ // the binder sent here. In practice though, we don't need to downgrade the
+ // stability of a remote binder, since this would as an effect only restrict
+ // what we can do to it.
+ LOG_ALWAYS_FATAL_IF(!binder || !binder->localBinder(), "Can only downgrade local binder");
+
+ auto stability = Category::currentFromLevel(getLocalLevel());
+ status_t result = setRepr(binder.get(), stability.repr(), REPR_LOG | REPR_ALLOW_DOWNGRADE);
+ LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
+}
+
std::string Stability::Category::debugString() {
return levelString(level) + " wire protocol version "
+ std::to_string(version);
@@ -45,13 +57,13 @@
void Stability::markCompilationUnit(IBinder* binder) {
auto stability = Category::currentFromLevel(getLocalLevel());
- status_t result = setRepr(binder, stability.repr(), true /*log*/);
+ status_t result = setRepr(binder, stability.repr(), REPR_LOG);
LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
}
void Stability::markVintf(IBinder* binder) {
auto stability = Category::currentFromLevel(Level::VINTF);
- status_t result = setRepr(binder, stability.repr(), true /*log*/);
+ status_t result = setRepr(binder, stability.repr(), REPR_LOG);
LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
}
@@ -62,7 +74,7 @@
void Stability::markVndk(IBinder* binder) {
auto stability = Category::currentFromLevel(Level::VENDOR);
- status_t result = setRepr(binder, stability.repr(), true /*log*/);
+ status_t result = setRepr(binder, stability.repr(), REPR_LOG);
LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
}
@@ -72,7 +84,7 @@
void Stability::tryMarkCompilationUnit(IBinder* binder) {
auto stability = Category::currentFromLevel(getLocalLevel());
- (void) setRepr(binder, stability.repr(), false /*log*/);
+ (void) setRepr(binder, stability.repr(), REPR_NONE);
}
Stability::Level Stability::getLocalLevel() {
@@ -94,7 +106,10 @@
#endif
}
-status_t Stability::setRepr(IBinder* binder, int32_t representation, bool log) {
+status_t Stability::setRepr(IBinder* binder, int32_t representation, uint32_t flags) {
+ bool log = flags & REPR_LOG;
+ bool allowDowngrade = flags & REPR_ALLOW_DOWNGRADE;
+
auto current = getCategory(binder);
auto setting = Category::fromRepr(representation);
@@ -129,7 +144,11 @@
return BAD_TYPE;
}
- if (current.repr() != 0 && current != setting) {
+ if (current == setting) return OK;
+
+ bool hasAlreadyBeenSet = current.repr() != 0;
+ bool isAllowedDowngrade = allowDowngrade && check(current, setting.level);
+ if (hasAlreadyBeenSet && !isAllowedDowngrade) {
if (log) {
ALOGE("Interface being set with %s but it is already marked as %s",
setting.debugString().c_str(),
@@ -138,7 +157,11 @@
return BAD_TYPE;
}
- if (current == setting) return OK;
+ if (isAllowedDowngrade) {
+ ALOGI("Interface set with %s downgraded to %s stability",
+ current.debugString().c_str(),
+ setting.debugString().c_str());
+ }
BBinder* local = binder->localBinder();
if (local != nullptr) {
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index 2e90142..b58d919 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -22,11 +22,10 @@
"name": "binderParcelTest"
},
{
- "name": "binderParcelTest",
- "host": true
+ "name": "binderLibTest"
},
{
- "name": "binderLibTest"
+ "name": "binderRpcTest"
},
{
"name": "binderStabilityTest"
@@ -44,6 +43,9 @@
"name": "aidl_integration_test"
},
{
+ "name": "memunreachable_binder_test"
+ },
+ {
"name": "libbinderthreadstateutils_test"
},
{
diff --git a/libs/binder/TextOutput.cpp b/libs/binder/TextOutput.cpp
index 684a7dc..a0ade50 100644
--- a/libs/binder/TextOutput.cpp
+++ b/libs/binder/TextOutput.cpp
@@ -16,7 +16,7 @@
#include <binder/TextOutput.h>
-#include <binder/Debug.h>
+#include "Debug.h"
#include <utils/String8.h>
#include <utils/String16.h>
diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl
index ce30050..2fabf94 100644
--- a/libs/binder/aidl/android/os/IServiceManager.aidl
+++ b/libs/binder/aidl/android/os/IServiceManager.aidl
@@ -43,9 +43,9 @@
*/
const int DUMP_FLAG_PRIORITY_DEFAULT = 1 << 3;
- const int DUMP_FLAG_PRIORITY_ALL = 15;
- // DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH
- // | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PRIORITY_DEFAULT;
+ const int DUMP_FLAG_PRIORITY_ALL =
+ DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH
+ | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PRIORITY_DEFAULT;
/* Allows services to dump sections in protobuf format. */
const int DUMP_FLAG_PROTO = 1 << 4;
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 22300ac..8ab7893 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -17,15 +17,19 @@
#pragma once
#include <binder/IBinder.h>
+#include <binder/RpcAddress.h>
#include <utils/KeyedVector.h>
#include <utils/Mutex.h>
#include <utils/threads.h>
#include <unordered_map>
+#include <variant>
// ---------------------------------------------------------------------------
namespace android {
+class RpcConnection;
+class RpcState;
namespace internal {
class Stability;
}
@@ -37,6 +41,14 @@
{
public:
static BpBinder* create(int32_t handle);
+ static BpBinder* create(const sp<RpcConnection>& connection, const RpcAddress& address);
+
+ /**
+ * Return value:
+ * true - this is associated with a socket RpcConnection
+ * false - (usual) binder over e.g. /dev/binder
+ */
+ bool isRpcBinder() const;
virtual const String16& getInterfaceDescriptor() const;
virtual bool isBinderAlive() const;
@@ -108,33 +120,56 @@
KeyedVector<const void*, entry_t> mObjects;
};
- class PrivateAccessorForHandle {
+ class PrivateAccessorForId {
private:
- friend BpBinder;
- friend ::android::Parcel;
- friend ::android::ProcessState;
- explicit PrivateAccessorForHandle(const BpBinder* binder) : mBinder(binder) {}
- int32_t handle() const { return mBinder->handle(); }
+ friend class BpBinder;
+ friend class ::android::Parcel;
+ friend class ::android::ProcessState;
+ friend class ::android::RpcState;
+ explicit PrivateAccessorForId(const BpBinder* binder) : mBinder(binder) {}
+
+ // valid if !isRpcBinder
+ int32_t binderHandle() const { return mBinder->binderHandle(); }
+
+ // valid if isRpcBinder
+ const RpcAddress& rpcAddress() const { return mBinder->rpcAddress(); }
+ const sp<RpcConnection>& rpcConnection() const { return mBinder->rpcConnection(); }
+
const BpBinder* mBinder;
};
- const PrivateAccessorForHandle getPrivateAccessorForHandle() const {
- return PrivateAccessorForHandle(this);
+ const PrivateAccessorForId getPrivateAccessorForId() const {
+ return PrivateAccessorForId(this);
}
private:
- friend PrivateAccessorForHandle;
+ friend PrivateAccessorForId;
- int32_t handle() const;
- BpBinder(int32_t handle,int32_t trackedUid);
+ struct BinderHandle {
+ int32_t handle;
+ };
+ struct SocketHandle {
+ sp<RpcConnection> connection;
+ RpcAddress address;
+ };
+ using Handle = std::variant<BinderHandle, SocketHandle>;
+
+ int32_t binderHandle() const;
+ const RpcAddress& rpcAddress() const;
+ const sp<RpcConnection>& rpcConnection() const;
+
+ explicit BpBinder(Handle&& handle);
+ BpBinder(BinderHandle&& handle, int32_t trackedUid);
+ explicit BpBinder(SocketHandle&& handle);
+
virtual ~BpBinder();
virtual void onFirstRef();
virtual void onLastStrongRef(const void* id);
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
friend ::android::internal::Stability;
- int32_t mStability;
- const int32_t mHandle;
+ int32_t mStability;
+ Handle mHandle;
struct Obituary {
wp<DeathRecipient> recipient;
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index c8fb448..31f63c8 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -60,6 +60,15 @@
EXTENSION_TRANSACTION = B_PACK_CHARS('_', 'E', 'X', 'T'),
DEBUG_PID_TRANSACTION = B_PACK_CHARS('_', 'P', 'I', 'D'),
+ // See android.os.IBinder.TWEET_TRANSACTION
+ // Most importantly, messages can be anything not exceeding 130 UTF-8
+ // characters, and callees should exclaim "jolly good message old boy!"
+ TWEET_TRANSACTION = B_PACK_CHARS('_', 'T', 'W', 'T'),
+
+ // See android.os.IBinder.LIKE_TRANSACTION
+ // Improve binder self-esteem.
+ LIKE_TRANSACTION = B_PACK_CHARS('_', 'L', 'I', 'K'),
+
// Corresponds to TF_ONE_WAY -- an asynchronous call.
FLAG_ONEWAY = 0x00000001,
diff --git a/libs/binder/include/binder/IMediaResourceMonitor.h b/libs/binder/include/binder/IMediaResourceMonitor.h
deleted file mode 100644
index f92d557..0000000
--- a/libs/binder/include/binder/IMediaResourceMonitor.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2016 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
-
-#ifndef __ANDROID_VNDK__
-
-#include <binder/IInterface.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------
-
-class IMediaResourceMonitor : public IInterface {
-public:
- DECLARE_META_INTERFACE(MediaResourceMonitor)
-
- // Values should be in sync with Intent.EXTRA_MEDIA_RESOURCE_TYPE_XXX.
- enum {
- TYPE_VIDEO_CODEC = 0,
- TYPE_AUDIO_CODEC = 1,
- };
-
- virtual void notifyResourceGranted(/*in*/ int32_t pid, /*in*/ const int32_t type) = 0;
-
- enum {
- NOTIFY_RESOURCE_GRANTED = IBinder::FIRST_CALL_TRANSACTION,
- };
-};
-
-// ----------------------------------------------------------------------
-
-class BnMediaResourceMonitor : public BnInterface<IMediaResourceMonitor> {
-public:
- // NOLINTNEXTLINE(google-default-arguments)
- virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
- uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------
-
-} // namespace android
-
-#else // __ANDROID_VNDK__
-#error "This header is not visible to vendors"
-#endif // __ANDROID_VNDK__
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 0183324..23a0cb0 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -162,6 +162,12 @@
// This constant needs to be kept in sync with Binder.UNSET_WORKSOURCE from the Java
// side.
static const int32_t kUnsetWorkSource = -1;
+
+ // Create a temp reference until commands in queue flushed to driver
+ // Internal only.
+ // @internal
+ void createTransactionReference(RefBase* ref);
+
private:
IPCThreadState();
~IPCThreadState();
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 54c49e4..9578372 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -50,11 +50,14 @@
class IBinder;
class IPCThreadState;
class ProcessState;
+class RpcConnection;
class String8;
class TextOutput;
class Parcel {
friend class IPCThreadState;
+ friend class RpcState;
+
public:
class ReadableBlob;
class WritableBlob;
@@ -92,7 +95,21 @@
// In order to verify this, heap dumps should be used.
void markSensitive() const;
- // Writes the RPC header.
+ // For a 'data' Parcel, this should mark the Parcel as being prepared for a
+ // transaction on this specific binder object. Based on this, the format of
+ // the wire binder protocol may change (data is written differently when it
+ // is for an RPC transaction).
+ void markForBinder(const sp<IBinder>& binder);
+
+ // Whenever possible, markForBinder should be preferred. This method is
+ // called automatically on reply Parcels for RPC transactions.
+ void markForRpc(const sp<RpcConnection>& connection);
+
+ // Whether this Parcel is written for RPC transactions (after calls to
+ // markForBinder or markForRpc).
+ bool isForRpc() const;
+
+ // Writes the IPC/RPC header.
status_t writeInterfaceToken(const String16& interface);
status_t writeInterfaceToken(const char16_t* str, size_t len);
@@ -190,34 +207,47 @@
// Write an Enum vector with underlying type int8_t.
// Does not use padding; each byte is contiguous.
template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t writeEnumVector(const std::vector<T>& val);
+ status_t writeEnumVector(const std::vector<T>& val)
+ { return writeData(val); }
template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t writeEnumVector(const std::optional<std::vector<T>>& val);
+ status_t writeEnumVector(const std::optional<std::vector<T>>& val)
+ { return writeData(val); }
template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead")));
+ status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead")))
+ { return writeData(val); }
// Write an Enum vector with underlying type != int8_t.
template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t writeEnumVector(const std::vector<T>& val);
+ status_t writeEnumVector(const std::vector<T>& val)
+ { return writeData(val); }
template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t writeEnumVector(const std::optional<std::vector<T>>& val);
+ status_t writeEnumVector(const std::optional<std::vector<T>>& val)
+ { return writeData(val); }
template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead")));
+ status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead")))
+ { return writeData(val); }
template<typename T>
- status_t writeParcelableVector(const std::optional<std::vector<std::optional<T>>>& val);
+ status_t writeParcelableVector(const std::optional<std::vector<std::optional<T>>>& val)
+ { return writeData(val); }
template<typename T>
- status_t writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val) __attribute__((deprecated("use std::optional version instead")));
+ status_t writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val) __attribute__((deprecated("use std::optional version instead")))
+ { return writeData(val); }
template<typename T>
- status_t writeParcelableVector(const std::shared_ptr<std::vector<std::unique_ptr<T>>>& val) __attribute__((deprecated("use std::optional version instead")));
+ status_t writeParcelableVector(const std::shared_ptr<std::vector<std::unique_ptr<T>>>& val) __attribute__((deprecated("use std::optional version instead")))
+ { return writeData(val); }
template<typename T>
- status_t writeParcelableVector(const std::shared_ptr<std::vector<std::optional<T>>>& val);
+ status_t writeParcelableVector(const std::shared_ptr<std::vector<std::optional<T>>>& val)
+ { return writeData(val); }
template<typename T>
- status_t writeParcelableVector(const std::vector<T>& val);
+ status_t writeParcelableVector(const std::vector<T>& val)
+ { return writeData(val); }
template<typename T>
- status_t writeNullableParcelable(const std::optional<T>& parcelable);
+ status_t writeNullableParcelable(const std::optional<T>& parcelable)
+ { return writeData(parcelable); }
template<typename T>
- status_t writeNullableParcelable(const std::unique_ptr<T>& parcelable) __attribute__((deprecated("use std::optional version instead")));
+ status_t writeNullableParcelable(const std::unique_ptr<T>& parcelable) __attribute__((deprecated("use std::optional version instead")))
+ { return writeData(parcelable); }
status_t writeParcelable(const Parcelable& parcelable);
@@ -335,35 +365,48 @@
// Read an Enum vector with underlying type int8_t.
// Does not use padding; each byte is contiguous.
template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t readEnumVector(std::vector<T>* val) const;
+ status_t readEnumVector(std::vector<T>* val) const
+ { return readData(val); }
template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead")));
+ status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead")))
+ { return readData(val); }
template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t readEnumVector(std::optional<std::vector<T>>* val) const;
+ status_t readEnumVector(std::optional<std::vector<T>>* val) const
+ { return readData(val); }
// Read an Enum vector with underlying type != int8_t.
template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t readEnumVector(std::vector<T>* val) const;
+ status_t readEnumVector(std::vector<T>* val) const
+ { return readData(val); }
template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead")));
+ status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead")))
+ { return readData(val); }
template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t readEnumVector(std::optional<std::vector<T>>* val) const;
+ status_t readEnumVector(std::optional<std::vector<T>>* val) const
+ { return readData(val); }
template<typename T>
status_t readParcelableVector(
- std::optional<std::vector<std::optional<T>>>* val) const;
+ std::optional<std::vector<std::optional<T>>>* val) const
+ { return readData(val); }
template<typename T>
status_t readParcelableVector(
- std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const __attribute__((deprecated("use std::optional version instead")));
+ std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const __attribute__((deprecated("use std::optional version instead")))
+ { return readData(val); }
template<typename T>
- status_t readParcelableVector(std::vector<T>* val) const;
+ status_t readParcelableVector(std::vector<T>* val) const
+ { return readData(val); }
status_t readParcelable(Parcelable* parcelable) const;
template<typename T>
- status_t readParcelable(std::optional<T>* parcelable) const;
+ status_t readParcelable(std::optional<T>* parcelable) const
+ { return readData(parcelable); }
template<typename T>
- status_t readParcelable(std::unique_ptr<T>* parcelable) const __attribute__((deprecated("use std::optional version instead")));
+ status_t readParcelable(std::unique_ptr<T>* parcelable) const __attribute__((deprecated("use std::optional version instead")))
+ { return readData(parcelable); }
+ // If strong binder would be nullptr, readStrongBinder() returns an error.
+ // TODO: T must be derived from IInterface, fix for clarity.
template<typename T>
status_t readStrongBinder(sp<T>* val) const;
@@ -418,20 +461,13 @@
template<typename T>
status_t read(LightFlattenable<T>& val) const;
+ // resizeOutVector is used to resize AIDL out vector parameters.
template<typename T>
status_t resizeOutVector(std::vector<T>* val) const;
template<typename T>
status_t resizeOutVector(std::optional<std::vector<T>>* val) const;
template<typename T>
status_t resizeOutVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead")));
- template<typename T>
- status_t reserveOutVector(std::vector<T>* val, size_t* size) const;
- template<typename T>
- status_t reserveOutVector(std::optional<std::vector<T>>* val,
- size_t* size) const;
- template<typename T>
- status_t reserveOutVector(std::unique_ptr<std::vector<T>>* val,
- size_t* size) const __attribute__((deprecated("use std::optional version instead")));
// Like Parcel.java's readExceptionCode(). Reads the first int32
// off of a Parcel's header, returning 0 or the negative error
@@ -518,10 +554,6 @@
void scanForFds() const;
status_t validateReadData(size_t len) const;
- // Reads an int32 size and does a coarse bounds check against the number
- // of available bytes in the Parcel.
- status_t readVectorSizeWithCoarseBoundCheck(int32_t *size) const;
-
void updateWorkSourceRequestHeaderPosition() const;
status_t finishFlattenBinder(const sp<IBinder>& binder);
@@ -540,53 +572,544 @@
status_t writeRawNullableParcelable(const Parcelable*
parcelable);
- template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool> = 0>
- status_t writeEnum(const T& val);
- template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool> = 0>
- status_t writeEnum(const T& val);
+ //-----------------------------------------------------------------------------
+ // Generic type read and write methods for Parcel:
+ //
+ // readData(T *value) will read a value from the Parcel.
+ // writeData(const T& value) will write a value to the Parcel.
+ //
+ // Our approach to parceling is based on two overloaded functions
+ // readData() and writeData() that generate parceling code for an
+ // object automatically based on its type. The code from templates are generated at
+ // compile time (if constexpr), and decomposes an object through a call graph matching
+ // recursive descent of the template typename.
+ //
+ // This approach unifies handling of complex objects,
+ // resulting in fewer lines of code, greater consistency,
+ // extensibility to nested types, efficiency (decisions made at compile time),
+ // and better code maintainability and optimization.
+ //
+ // Design decision: Incorporate the read and write code into Parcel rather than
+ // as a non-intrusive serializer that emits a byte stream, as we have
+ // active objects, alignment, legacy code, and historical idiosyncrasies.
+ //
+ // --- Overview
+ //
+ // Parceling is a way of serializing objects into a sequence of bytes for communication
+ // between processes, as part of marshaling data for remote procedure calls.
+ //
+ // The Parcel instance contains objects serialized as bytes, such as the following:
+ //
+ // 1) Ordinary primitive data such as int, float.
+ // 2) Established structured data such as String16, std::string.
+ // 3) Parcelables, which are C++ objects that derive from Parcelable (and thus have a
+ // readFromParcel and writeToParcel method). (Similar for Java)
+ // 4) A std::vector<> of such data.
+ // 5) Nullable objects contained in std::optional, std::unique_ptr, or std::shared_ptr.
+ //
+ // And active objects from the Android ecosystem such as:
+ // 6) File descriptors, base::unique_fd (kernel object handles)
+ // 7) Binder objects, sp<IBinder> (active Android RPC handles)
+ //
+ // Objects from (1) through (5) serialize into the mData buffer.
+ // Active objects (6) and (7) serialize into both mData and mObjects buffers.
+ //
+ // --- Data layout details
+ //
+ // Data is read or written to the parcel by recursively decomposing the type of the parameter
+ // type T through readData() and writeData() methods.
+ //
+ // We focus on writeData() here in our explanation of the data layout.
+ //
+ // 1) Alignment
+ // Implementation detail: Regardless of the parameter type, writeData() calls are designed
+ // to finish at a multiple of 4 bytes, the default alignment of the Parcel.
+ //
+ // Writes of single uint8_t, int8_t, enums based on types of size 1, char16_t, etc
+ // will result in 4 bytes being written. The data is widened to int32 and then written;
+ // hence the position of the nonzero bytes depend on the native endianness of the CPU.
+ //
+ // Writes of primitive values with 8 byte size, double, int64_t, uint64_t,
+ // are stored with 4 byte alignment. The ARM and x86/x64 permit unaligned reads
+ // and writes (albeit with potential latency/throughput penalty) which may or may
+ // not be observable unless the process is IO bound.
+ //
+ // 2) Parcelables
+ // Parcelables are detected by the type's base class, and implemented through calling
+ // into the Parcelable type's readFromParcel() or writeToParcel() methods.
+ // Historically, due to null object detection, a (int32_t) 1 is prepended to the data written.
+ // Parcelables must have a default constructor (i.e. one that takes no arguments).
+ //
+ // 3) Arrays
+ // Arrays of uint8_t and int8_t, and enums based on size 1 are written as
+ // a contiguous packed byte stream. Hidden zero padding is applied at the end of the byte
+ // stream to make a multiple of 4 bytes (and prevent info leakage when writing).
+ //
+ // All other array writes can be conceptually thought of as recursively calling
+ // writeData on the individual elements (though may be implemented differently for speed).
+ // As discussed in (1), alignment rules are therefore applied for each element
+ // write (not as an aggregate whole), so the wire representation of data can be
+ // substantially larger.
+ //
+ // Historical Note:
+ // Because of element-wise alignment, CharVector and BoolVector are expanded
+ // element-wise into integers even though they could have been optimized to be packed
+ // just like uint8_t, int8_t (size 1 data).
+ //
+ // 3.1) Arrays accessed by the std::vector type. This is the default for AIDL.
+ //
+ // 4) Nullables
+ // std::optional, std::unique_ptr, std::shared_ptr are all parceled identically
+ // (i.e. result in identical byte layout).
+ // The target of the std::optional, std::unique_ptr, or std::shared_ptr
+ // can either be a std::vector, String16, std::string, or a Parcelable.
+ //
+ // Detection of null relies on peeking the first int32 data and checking if the
+ // the peeked value is considered invalid for the object:
+ // (-1 for vectors, String16, std::string) (0 for Parcelables). If the peeked value
+ // is invalid, then a null is returned.
+ //
+ // Application Note: When to use each nullable type:
+ //
+ // std::optional: Embeds the object T by value rather than creating a new instance
+ // by managed pointer as std::unique_ptr or std::shared_ptr. This will save a malloc
+ // when creating an optional instance.
+ //
+ // Use of std::optionals by value can result in copies of the underlying value stored in it,
+ // so a std::move may be used to move in and move out (for example) a vector value into
+ // the std::optional or for the std::optional itself.
+ //
+ // std::unique_ptr, std::shared_ptr: These are preferred when the lifetime of the object is
+ // already managed by the application. This reduces unnecessary copying of data
+ // especially when the calls are local in-proc (rather than via binder rpc).
+ //
+ // 5) StrongBinder (sp<IBinder>)
+ // StrongBinder objects are written regardless of null. When read, null StrongBinder values
+ // will be interpreted as UNKNOWN_ERROR if the type is a single argument <sp<T>>
+ // or in a vector argument <std::vector<sp<T>>. However, they will be read without an error
+ // if present in a std::optional, std::unique_ptr, or std::shared_ptr vector, e.g.
+ // <std::optional<std::vector<sp<T>>>.
+ //
+ // See AIDL annotation @Nullable, readStrongBinder(), and readNullableStrongBinder().
+ //
+ // Historical Note: writing a vector of StrongBinder objects <std::vector<sp<T>>
+ // containing a null will not cause an error. However reading such a vector will cause
+ // an error _and_ early termination of the read.
- template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool> = 0>
- status_t readEnum(T* pArg) const;
- template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool> = 0>
- status_t readEnum(T* pArg) const;
+ // --- Examples
+ //
+ // Using recursive parceling, we can parcel complex data types so long
+ // as they obey the rules described above.
+ //
+ // Example #1
+ // Parceling of a 3D vector
+ //
+ // std::vector<std::vector<std::vector<int32_t>>> v1 {
+ // { {1}, {2, 3}, {4} },
+ // {},
+ // { {10}, {20}, {30, 40} },
+ // };
+ // Parcel p1;
+ // p1.writeData(v1);
+ // decltype(v1) v2;
+ // p1.setDataPosition(0);
+ // p1.readData(&v2);
+ // ASSERT_EQ(v1, v2);
+ //
+ // Example #2
+ // Parceling of mixed shared pointers
+ //
+ // Parcel p1;
+ // auto sp1 = std::make_shared<std::vector<std::shared_ptr<std::vector<int>>>>(3);
+ // (*sp1)[2] = std::make_shared<std::vector<int>>(3);
+ // (*(*sp1)[2])[2] = 2;
+ // p1.writeData(sp1);
+ // decltype(sp1) sp2;
+ // p1.setDataPosition(0);
+ // p1.readData(&sp2);
+ // ASSERT_EQ((*sp1)[0], (*sp2)[0]); // nullptr
+ // ASSERT_EQ((*sp1)[1], (*sp2)[1]); // nullptr
+ // ASSERT_EQ(*(*sp1)[2], *(*sp2)[2]); // { 0, 0, 2}
- status_t writeByteVectorInternal(const int8_t* data, size_t size);
- template<typename T>
- status_t readByteVectorInternal(std::vector<T>* val, size_t size) const;
+ // --- Helper Methods
+ // TODO: move this to a utils header.
+ //
+ // Determine if a type is a specialization of a templated type
+ // Example: is_specialization_v<T, std::vector>
- template<typename T, typename U>
- status_t unsafeReadTypedVector(std::vector<T>* val,
- status_t(Parcel::*read_func)(U*) const) const;
- template<typename T>
- status_t readNullableTypedVector(std::optional<std::vector<T>>* val,
- status_t(Parcel::*read_func)(T*) const) const;
- template<typename T>
- status_t readNullableTypedVector(std::unique_ptr<std::vector<T>>* val,
- status_t(Parcel::*read_func)(T*) const) const __attribute__((deprecated("use std::optional version instead")));
- template<typename T>
- status_t readTypedVector(std::vector<T>* val,
- status_t(Parcel::*read_func)(T*) const) const;
- template<typename T, typename U>
- status_t unsafeWriteTypedVector(const std::vector<T>& val,
- status_t(Parcel::*write_func)(U));
- template<typename T>
- status_t writeNullableTypedVector(const std::optional<std::vector<T>>& val,
- status_t(Parcel::*write_func)(const T&));
- template<typename T>
- status_t writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
- status_t(Parcel::*write_func)(const T&)) __attribute__((deprecated("use std::optional version instead")));
- template<typename T>
- status_t writeNullableTypedVector(const std::optional<std::vector<T>>& val,
- status_t(Parcel::*write_func)(T));
- template<typename T>
- status_t writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
- status_t(Parcel::*write_func)(T)) __attribute__((deprecated("use std::optional version instead")));
- template<typename T>
- status_t writeTypedVector(const std::vector<T>& val,
- status_t(Parcel::*write_func)(const T&));
- template<typename T>
- status_t writeTypedVector(const std::vector<T>& val,
- status_t(Parcel::*write_func)(T));
+ template <typename Test, template <typename...> class Ref>
+ struct is_specialization : std::false_type {};
+
+ template <template <typename...> class Ref, typename... Args>
+ struct is_specialization<Ref<Args...>, Ref>: std::true_type {};
+
+ template <typename Test, template <typename...> class Ref>
+ static inline constexpr bool is_specialization_v = is_specialization<Test, Ref>::value;
+
+ // Get the first template type from a container, the T from MyClass<T, ...>.
+ template<typename T> struct first_template_type;
+
+ template <template <typename ...> class V, typename T, typename... Args>
+ struct first_template_type<V<T, Args...>> {
+ using type_t = T;
+ };
+
+ template <typename T>
+ using first_template_type_t = typename first_template_type<T>::type_t;
+
+ // For static assert(false) we need a template version to avoid early failure.
+ template <typename T>
+ static inline constexpr bool dependent_false_v = false;
+
+ // primitive types that we consider packed and trivially copyable as an array
+ template <typename T>
+ static inline constexpr bool is_pointer_equivalent_array_v =
+ std::is_same_v<T, int8_t>
+ || std::is_same_v<T, uint8_t>
+ // We could support int16_t and uint16_t, but those aren't currently AIDL types.
+ || std::is_same_v<T, int32_t>
+ || std::is_same_v<T, uint32_t>
+ || std::is_same_v<T, float>
+ // are unaligned reads and write support is assumed.
+ || std::is_same_v<T, uint64_t>
+ || std::is_same_v<T, int64_t>
+ || std::is_same_v<T, double>
+ || (std::is_enum_v<T> && (sizeof(T) == 1 || sizeof(T) == 4)); // size check not type
+
+ // allowed "nullable" types
+ // These are nonintrusive containers std::optional, std::unique_ptr, std::shared_ptr.
+ template <typename T>
+ static inline constexpr bool is_parcel_nullable_type_v =
+ is_specialization_v<T, std::optional>
+ || is_specialization_v<T, std::unique_ptr>
+ || is_specialization_v<T, std::shared_ptr>;
+
+ // special int32 value to indicate NonNull or Null parcelables
+ // This is fixed to be only 0 or 1 by contract, do not change.
+ static constexpr int32_t kNonNullParcelableFlag = 1;
+ static constexpr int32_t kNullParcelableFlag = 0;
+
+ // special int32 size representing a null vector, when applicable in Nullable data.
+ // This fixed as -1 by contract, do not change.
+ static constexpr int32_t kNullVectorSize = -1;
+
+ // --- readData and writeData methods.
+ // We choose a mixture of function and template overloads to improve code readability.
+ // TODO: Consider C++20 concepts when they become available.
+
+ // writeData function overloads.
+ // Implementation detail: Function overloading improves code readability over
+ // template overloading, but prevents writeData<T> from being used for those types.
+
+ status_t writeData(bool t) {
+ return writeBool(t); // this writes as int32_t
+ }
+
+ status_t writeData(int8_t t) {
+ return writeByte(t); // this writes as int32_t
+ }
+
+ status_t writeData(uint8_t t) {
+ return writeByte(static_cast<int8_t>(t)); // this writes as int32_t
+ }
+
+ status_t writeData(char16_t t) {
+ return writeChar(t); // this writes as int32_t
+ }
+
+ status_t writeData(int32_t t) {
+ return writeInt32(t);
+ }
+
+ status_t writeData(uint32_t t) {
+ return writeUint32(t);
+ }
+
+ status_t writeData(int64_t t) {
+ return writeInt64(t);
+ }
+
+ status_t writeData(uint64_t t) {
+ return writeUint64(t);
+ }
+
+ status_t writeData(float t) {
+ return writeFloat(t);
+ }
+
+ status_t writeData(double t) {
+ return writeDouble(t);
+ }
+
+ status_t writeData(const String16& t) {
+ return writeString16(t);
+ }
+
+ status_t writeData(const std::string& t) {
+ return writeUtf8AsUtf16(t);
+ }
+
+ status_t writeData(const base::unique_fd& t) {
+ return writeUniqueFileDescriptor(t);
+ }
+
+ status_t writeData(const Parcelable& t) { // std::is_base_of_v<Parcelable, T>
+ // implemented here. writeParcelable() calls this.
+ status_t status = writeData(static_cast<int32_t>(kNonNullParcelableFlag));
+ if (status != OK) return status;
+ return t.writeToParcel(this);
+ }
+
+ // writeData<T> template overloads.
+ // Written such that the first template type parameter is the complete type
+ // of the first function parameter.
+ template <typename T,
+ typename std::enable_if_t<std::is_enum_v<T>, bool> = true>
+ status_t writeData(const T& t) {
+ // implemented here. writeEnum() calls this.
+ using UT = std::underlying_type_t<T>;
+ return writeData(static_cast<UT>(t)); // recurse
+ }
+
+ template <typename T,
+ typename std::enable_if_t<is_specialization_v<T, sp>, bool> = true>
+ status_t writeData(const T& t) {
+ return writeStrongBinder(t);
+ }
+
+ // std::optional, std::unique_ptr, std::shared_ptr special case.
+ template <typename CT,
+ typename std::enable_if_t<is_parcel_nullable_type_v<CT>, bool> = true>
+ status_t writeData(const CT& c) {
+ using T = first_template_type_t<CT>; // The T in CT == C<T, ...>
+ if constexpr (is_specialization_v<T, std::vector>
+ || std::is_same_v<T, String16>
+ || std::is_same_v<T, std::string>) {
+ if (!c) return writeData(static_cast<int32_t>(kNullVectorSize));
+ } else if constexpr (std::is_base_of_v<Parcelable, T>) {
+ if (!c) return writeData(static_cast<int32_t>(kNullParcelableFlag));
+ } else /* constexpr */ { // could define this, but raise as error.
+ static_assert(dependent_false_v<CT>);
+ }
+ return writeData(*c);
+ }
+
+ template <typename CT,
+ typename std::enable_if_t<is_specialization_v<CT, std::vector>, bool> = true>
+ status_t writeData(const CT& c) {
+ using T = first_template_type_t<CT>; // The T in CT == C<T, ...>
+ if (c.size() > std::numeric_limits<int32_t>::max()) return BAD_VALUE;
+ const auto size = static_cast<int32_t>(c.size());
+ writeData(size);
+ if constexpr (is_pointer_equivalent_array_v<T>) {
+ constexpr size_t limit = std::numeric_limits<size_t>::max() / sizeof(T);
+ if (c.size() > limit) return BAD_VALUE;
+ // is_pointer_equivalent types do not have gaps which could leak info,
+ // which is only a concern when writing through binder.
+
+ // TODO: Padding of the write is suboptimal when the length of the
+ // data is not a multiple of 4. Consider improving the write() method.
+ return write(c.data(), c.size() * sizeof(T));
+ } else if constexpr (std::is_same_v<T, bool>
+ || std::is_same_v<T, char16_t>) {
+ // reserve data space to write to
+ auto data = reinterpret_cast<int32_t*>(writeInplace(c.size() * sizeof(int32_t)));
+ if (data == nullptr) return BAD_VALUE;
+ for (const auto t: c) {
+ *data++ = static_cast<int32_t>(t);
+ }
+ } else /* constexpr */ {
+ for (const auto &t : c) {
+ const status_t status = writeData(t);
+ if (status != OK) return status;
+ }
+ }
+ return OK;
+ }
+
+ // readData function overloads.
+ // Implementation detail: Function overloading improves code readability over
+ // template overloading, but prevents readData<T> from being used for those types.
+
+ status_t readData(bool* t) const {
+ return readBool(t); // this reads as int32_t
+ }
+
+ status_t readData(int8_t* t) const {
+ return readByte(t); // this reads as int32_t
+ }
+
+ status_t readData(uint8_t* t) const {
+ return readByte(reinterpret_cast<int8_t*>(t)); // NOTE: this reads as int32_t
+ }
+
+ status_t readData(char16_t* t) const {
+ return readChar(t); // this reads as int32_t
+ }
+
+ status_t readData(int32_t* t) const {
+ return readInt32(t);
+ }
+
+ status_t readData(uint32_t* t) const {
+ return readUint32(t);
+ }
+
+ status_t readData(int64_t* t) const {
+ return readInt64(t);
+ }
+
+ status_t readData(uint64_t* t) const {
+ return readUint64(t);
+ }
+
+ status_t readData(float* t) const {
+ return readFloat(t);
+ }
+
+ status_t readData(double* t) const {
+ return readDouble(t);
+ }
+
+ status_t readData(String16* t) const {
+ return readString16(t);
+ }
+
+ status_t readData(std::string* t) const {
+ return readUtf8FromUtf16(t);
+ }
+
+ status_t readData(base::unique_fd* t) const {
+ return readUniqueFileDescriptor(t);
+ }
+
+ status_t readData(Parcelable* t) const { // std::is_base_of_v<Parcelable, T>
+ // implemented here. readParcelable() calls this.
+ int32_t present;
+ status_t status = readData(&present);
+ if (status != OK) return status;
+ if (present != kNonNullParcelableFlag) return UNEXPECTED_NULL;
+ return t->readFromParcel(this);
+ }
+
+ // readData<T> template overloads.
+ // Written such that the first template type parameter is the complete type
+ // of the first function parameter.
+
+ template <typename T,
+ typename std::enable_if_t<std::is_enum_v<T>, bool> = true>
+ status_t readData(T* t) const {
+ // implemented here. readEnum() calls this.
+ using UT = std::underlying_type_t<T>;
+ return readData(reinterpret_cast<UT*>(t));
+ }
+
+ template <typename T,
+ typename std::enable_if_t<is_specialization_v<T, sp>, bool> = true>
+ status_t readData(T* t) const {
+ return readStrongBinder(t); // Note: on null, returns failure
+ }
+
+
+ template <typename CT,
+ typename std::enable_if_t<is_parcel_nullable_type_v<CT>, bool> = true>
+ status_t readData(CT* c) const {
+ using T = first_template_type_t<CT>; // The T in CT == C<T, ...>
+ const size_t startPos = dataPosition();
+ int32_t peek;
+ status_t status = readData(&peek);
+ if (status != OK) return status;
+ if constexpr (is_specialization_v<T, std::vector>
+ || std::is_same_v<T, String16>
+ || std::is_same_v<T, std::string>) {
+ if (peek == kNullVectorSize) {
+ c->reset();
+ return OK;
+ }
+ } else if constexpr (std::is_base_of_v<Parcelable, T>) {
+ if (peek == kNullParcelableFlag) {
+ c->reset();
+ return OK;
+ }
+ } else /* constexpr */ { // could define this, but raise as error.
+ static_assert(dependent_false_v<CT>);
+ }
+ // create a new object.
+ if constexpr (is_specialization_v<CT, std::optional>) {
+ c->emplace();
+ } else /* constexpr */ {
+ T* const t = new (std::nothrow) T; // contents read from Parcel below.
+ if (t == nullptr) return NO_MEMORY;
+ c->reset(t);
+ }
+ // rewind data ptr to reread (this is pretty quick), otherwise we could
+ // pass an optional argument to readData to indicate a peeked value.
+ setDataPosition(startPos);
+ if constexpr (is_specialization_v<T, std::vector>) {
+ return readData(&**c, READ_FLAG_SP_NULLABLE); // nullable sp<> allowed now
+ } else {
+ return readData(&**c);
+ }
+ }
+
+ // std::vector special case, incorporating flags whether the vector
+ // accepts nullable sp<> to be read.
+ enum ReadFlags {
+ READ_FLAG_NONE = 0,
+ READ_FLAG_SP_NULLABLE = 1 << 0,
+ };
+
+ template <typename CT,
+ typename std::enable_if_t<is_specialization_v<CT, std::vector>, bool> = true>
+ status_t readData(CT* c, ReadFlags readFlags = READ_FLAG_NONE) const {
+ using T = first_template_type_t<CT>; // The T in CT == C<T, ...>
+ int32_t size;
+ status_t status = readInt32(&size);
+ if (status != OK) return status;
+ if (size < 0) return UNEXPECTED_NULL;
+ const size_t availableBytes = dataAvail(); // coarse bound on vector size.
+ if (static_cast<size_t>(size) > availableBytes) return BAD_VALUE;
+ c->clear(); // must clear before resizing/reserving otherwise move ctors may be called.
+ if constexpr (is_pointer_equivalent_array_v<T>) {
+ // could consider POD without gaps and alignment of 4.
+ auto data = reinterpret_cast<const T*>(
+ readInplace(static_cast<size_t>(size) * sizeof(T)));
+ if (data == nullptr) return BAD_VALUE;
+ c->insert(c->begin(), data, data + size); // insert should do a reserve().
+ } else if constexpr (std::is_same_v<T, bool>
+ || std::is_same_v<T, char16_t>) {
+ c->reserve(size); // avoids default initialization
+ auto data = reinterpret_cast<const int32_t*>(
+ readInplace(static_cast<size_t>(size) * sizeof(int32_t)));
+ if (data == nullptr) return BAD_VALUE;
+ for (int32_t i = 0; i < size; ++i) {
+ c->emplace_back(static_cast<T>(*data++));
+ }
+ } else if constexpr (is_specialization_v<T, sp>) {
+ c->resize(size); // calls ctor
+ if (readFlags & READ_FLAG_SP_NULLABLE) {
+ for (auto &t : *c) {
+ status = readNullableStrongBinder(&t); // allow nullable
+ if (status != OK) return status;
+ }
+ } else {
+ for (auto &t : *c) {
+ status = readStrongBinder(&t);
+ if (status != OK) return status;
+ }
+ }
+ } else /* constexpr */ {
+ c->resize(size); // calls ctor
+ for (auto &t : *c) {
+ status = readData(&t);
+ if (status != OK) return status;
+ }
+ }
+ return OK;
+ }
+
+ //-----------------------------------------------------------------------------
+ private:
status_t mError;
uint8_t* mData;
@@ -600,6 +1123,7 @@
mutable bool mObjectsSorted;
mutable bool mRequestHeaderPresent;
+
mutable size_t mWorkSourceRequestHeaderPosition;
mutable bool mFdsKnown;
@@ -612,8 +1136,7 @@
release_func mOwner;
- // TODO(167966510): reserved for binder/version/stability
- void* mReserved = reinterpret_cast<void*>(0xAAAAAAAA);
+ sp<RpcConnection> mConnection;
class Blob {
public:
@@ -792,7 +1315,6 @@
template<typename T>
status_t Parcel::resizeOutVector(std::vector<T>* val) const {
int32_t size;
- // used for allocating 'out' vector args, do not use readVectorSizeWithCoarseBoundCheck() here
status_t err = readInt32(&size);
if (err != NO_ERROR) {
return err;
@@ -808,7 +1330,6 @@
template<typename T>
status_t Parcel::resizeOutVector(std::optional<std::vector<T>>* val) const {
int32_t size;
- // used for allocating 'out' vector args, do not use readVectorSizeWithCoarseBoundCheck() here
status_t err = readInt32(&size);
if (err != NO_ERROR) {
return err;
@@ -825,7 +1346,6 @@
template<typename T>
status_t Parcel::resizeOutVector(std::unique_ptr<std::vector<T>>* val) const {
int32_t size;
- // used for allocating 'out' vector args, do not use readVectorSizeWithCoarseBoundCheck() here
status_t err = readInt32(&size);
if (err != NO_ERROR) {
return err;
@@ -840,61 +1360,6 @@
}
template<typename T>
-status_t Parcel::reserveOutVector(std::vector<T>* val, size_t* size) const {
- int32_t read_size;
- status_t err = readVectorSizeWithCoarseBoundCheck(&read_size);
- if (err != NO_ERROR) {
- return err;
- }
-
- if (read_size < 0) {
- return UNEXPECTED_NULL;
- }
- *size = static_cast<size_t>(read_size);
- val->reserve(*size);
- return OK;
-}
-
-template<typename T>
-status_t Parcel::reserveOutVector(std::optional<std::vector<T>>* val, size_t* size) const {
- int32_t read_size;
- status_t err = readVectorSizeWithCoarseBoundCheck(&read_size);
- if (err != NO_ERROR) {
- return err;
- }
-
- if (read_size >= 0) {
- *size = static_cast<size_t>(read_size);
- val->emplace();
- (*val)->reserve(*size);
- } else {
- val->reset();
- }
-
- return OK;
-}
-
-template<typename T>
-status_t Parcel::reserveOutVector(std::unique_ptr<std::vector<T>>* val,
- size_t* size) const {
- int32_t read_size;
- status_t err = readVectorSizeWithCoarseBoundCheck(&read_size);
- if (err != NO_ERROR) {
- return err;
- }
-
- if (read_size >= 0) {
- *size = static_cast<size_t>(read_size);
- val->reset(new std::vector<T>());
- (*val)->reserve(*size);
- } else {
- val->reset();
- }
-
- return OK;
-}
-
-template<typename T>
status_t Parcel::readStrongBinder(sp<T>* val) const {
sp<IBinder> tmp;
status_t ret = readStrongBinder(&tmp);
@@ -926,422 +1391,6 @@
return ret;
}
-template<typename T, typename U>
-status_t Parcel::unsafeReadTypedVector(
- std::vector<T>* val,
- status_t(Parcel::*read_func)(U*) const) const {
- int32_t size;
- status_t status = this->readVectorSizeWithCoarseBoundCheck(&size);
-
- if (status != OK) {
- return status;
- }
-
- if (size < 0) {
- return UNEXPECTED_NULL;
- }
-
- if (val->max_size() < static_cast<size_t>(size)) {
- return NO_MEMORY;
- }
-
- val->resize(static_cast<size_t>(size));
-
- if (val->size() < static_cast<size_t>(size)) {
- return NO_MEMORY;
- }
-
- for (auto& v: *val) {
- status = (this->*read_func)(&v);
-
- if (status != OK) {
- return status;
- }
- }
-
- return OK;
-}
-
-template<typename T>
-status_t Parcel::readTypedVector(std::vector<T>* val,
- status_t(Parcel::*read_func)(T*) const) const {
- return unsafeReadTypedVector(val, read_func);
-}
-
-template<typename T>
-status_t Parcel::readNullableTypedVector(std::optional<std::vector<T>>* val,
- status_t(Parcel::*read_func)(T*) const) const {
- const size_t start = dataPosition();
- int32_t size;
- status_t status = readVectorSizeWithCoarseBoundCheck(&size);
- val->reset();
-
- if (status != OK || size < 0) {
- return status;
- }
-
- setDataPosition(start);
- val->emplace();
-
- status = unsafeReadTypedVector(&**val, read_func);
-
- if (status != OK) {
- val->reset();
- }
-
- return status;
-}
-
-template<typename T>
-status_t Parcel::readNullableTypedVector(std::unique_ptr<std::vector<T>>* val,
- status_t(Parcel::*read_func)(T*) const) const {
- const size_t start = dataPosition();
- int32_t size;
- status_t status = readVectorSizeWithCoarseBoundCheck(&size);
- val->reset();
-
- if (status != OK || size < 0) {
- return status;
- }
-
- setDataPosition(start);
- val->reset(new std::vector<T>());
-
- status = unsafeReadTypedVector(val->get(), read_func);
-
- if (status != OK) {
- val->reset();
- }
-
- return status;
-}
-
-template<typename T, typename U>
-status_t Parcel::unsafeWriteTypedVector(const std::vector<T>& val,
- status_t(Parcel::*write_func)(U)) {
- if (val.size() > std::numeric_limits<int32_t>::max()) {
- return BAD_VALUE;
- }
-
- status_t status = this->writeInt32(static_cast<int32_t>(val.size()));
-
- if (status != OK) {
- return status;
- }
-
- for (const auto& item : val) {
- status = (this->*write_func)(item);
-
- if (status != OK) {
- return status;
- }
- }
-
- return OK;
-}
-
-template<typename T>
-status_t Parcel::writeTypedVector(const std::vector<T>& val,
- status_t(Parcel::*write_func)(const T&)) {
- return unsafeWriteTypedVector(val, write_func);
-}
-
-template<typename T>
-status_t Parcel::writeTypedVector(const std::vector<T>& val,
- status_t(Parcel::*write_func)(T)) {
- return unsafeWriteTypedVector(val, write_func);
-}
-
-template<typename T>
-status_t Parcel::writeNullableTypedVector(const std::optional<std::vector<T>>& val,
- status_t(Parcel::*write_func)(const T&)) {
- if (!val) {
- return this->writeInt32(-1);
- }
-
- return unsafeWriteTypedVector(*val, write_func);
-}
-
-template<typename T>
-status_t Parcel::writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
- status_t(Parcel::*write_func)(const T&)) {
- if (val.get() == nullptr) {
- return this->writeInt32(-1);
- }
-
- return unsafeWriteTypedVector(*val, write_func);
-}
-
-template<typename T>
-status_t Parcel::writeNullableTypedVector(const std::optional<std::vector<T>>& val,
- status_t(Parcel::*write_func)(T)) {
- if (!val) {
- return this->writeInt32(-1);
- }
-
- return unsafeWriteTypedVector(*val, write_func);
-}
-
-template<typename T>
-status_t Parcel::writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
- status_t(Parcel::*write_func)(T)) {
- if (val.get() == nullptr) {
- return this->writeInt32(-1);
- }
-
- return unsafeWriteTypedVector(*val, write_func);
-}
-
-template<typename T>
-status_t Parcel::readParcelableVector(std::vector<T>* val) const {
- return unsafeReadTypedVector<T, Parcelable>(val, &Parcel::readParcelable);
-}
-
-template<typename T>
-status_t Parcel::readParcelableVector(std::optional<std::vector<std::optional<T>>>* val) const {
- const size_t start = dataPosition();
- int32_t size;
- status_t status = readVectorSizeWithCoarseBoundCheck(&size);
- val->reset();
-
- if (status != OK || size < 0) {
- return status;
- }
-
- setDataPosition(start);
- val->emplace();
-
- using NullableT = std::optional<T>;
- status = unsafeReadTypedVector<NullableT, NullableT>(&**val, &Parcel::readParcelable);
-
- if (status != OK) {
- val->reset();
- }
-
- return status;
-}
-
-template<typename T>
-status_t Parcel::readParcelableVector(std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const {
- const size_t start = dataPosition();
- int32_t size;
- status_t status = readVectorSizeWithCoarseBoundCheck(&size);
- val->reset();
-
- if (status != OK || size < 0) {
- return status;
- }
-
- setDataPosition(start);
- val->reset(new std::vector<std::unique_ptr<T>>());
-
- using NullableT = std::unique_ptr<T>;
- status = unsafeReadTypedVector<NullableT, NullableT>(val->get(), &Parcel::readParcelable);
-
- if (status != OK) {
- val->reset();
- }
-
- return status;
-}
-
-template<typename T>
-status_t Parcel::readParcelable(std::optional<T>* parcelable) const {
- const size_t start = dataPosition();
- int32_t present;
- status_t status = readInt32(&present);
- parcelable->reset();
-
- if (status != OK || !present) {
- return status;
- }
-
- setDataPosition(start);
- parcelable->emplace();
-
- status = readParcelable(&**parcelable);
-
- if (status != OK) {
- parcelable->reset();
- }
-
- return status;
-}
-
-template<typename T>
-status_t Parcel::readParcelable(std::unique_ptr<T>* parcelable) const {
- const size_t start = dataPosition();
- int32_t present;
- status_t status = readInt32(&present);
- parcelable->reset();
-
- if (status != OK || !present) {
- return status;
- }
-
- setDataPosition(start);
- parcelable->reset(new T());
-
- status = readParcelable(parcelable->get());
-
- if (status != OK) {
- parcelable->reset();
- }
-
- return status;
-}
-
-template<typename T>
-status_t Parcel::writeNullableParcelable(const std::optional<T>& parcelable) {
- return writeRawNullableParcelable(parcelable ? &*parcelable : nullptr);
-}
-
-template<typename T>
-status_t Parcel::writeNullableParcelable(const std::unique_ptr<T>& parcelable) {
- return writeRawNullableParcelable(parcelable.get());
-}
-
-template<typename T>
-status_t Parcel::writeParcelableVector(const std::vector<T>& val) {
- return unsafeWriteTypedVector<T,const Parcelable&>(val, &Parcel::writeParcelable);
-}
-
-template<typename T>
-status_t Parcel::writeParcelableVector(const std::optional<std::vector<std::optional<T>>>& val) {
- if (!val) {
- return this->writeInt32(-1);
- }
-
- using NullableT = std::optional<T>;
- return unsafeWriteTypedVector<NullableT, const NullableT&>(*val, &Parcel::writeNullableParcelable);
-}
-
-template<typename T>
-status_t Parcel::writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val) {
- if (val.get() == nullptr) {
- return this->writeInt32(-1);
- }
-
- return unsafeWriteTypedVector(*val, &Parcel::writeNullableParcelable<T>);
-}
-
-template<typename T>
-status_t Parcel::writeParcelableVector(const std::shared_ptr<std::vector<std::unique_ptr<T>>>& val) {
- if (val.get() == nullptr) {
- return this->writeInt32(-1);
- }
-
- using NullableT = std::unique_ptr<T>;
- return unsafeWriteTypedVector<NullableT, const NullableT&>(*val, &Parcel::writeNullableParcelable);
-}
-
-template<typename T>
-status_t Parcel::writeParcelableVector(const std::shared_ptr<std::vector<std::optional<T>>>& val) {
- if (val.get() == nullptr) {
- return this->writeInt32(-1);
- }
-
- using NullableT = std::optional<T>;
- return unsafeWriteTypedVector<NullableT, const NullableT&>(*val, &Parcel::writeNullableParcelable);
-}
-
-template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool>>
-status_t Parcel::writeEnum(const T& val) {
- return writeInt32(static_cast<int32_t>(val));
-}
-template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool>>
-status_t Parcel::writeEnum(const T& val) {
- return writeInt64(static_cast<int64_t>(val));
-}
-
-template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::writeEnumVector(const std::vector<T>& val) {
- return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val.data()), val.size());
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::writeEnumVector(const std::optional<std::vector<T>>& val) {
- if (!val) return writeInt32(-1);
- return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size());
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::writeEnumVector(const std::unique_ptr<std::vector<T>>& val) {
- if (!val) return writeInt32(-1);
- return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size());
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::writeEnumVector(const std::vector<T>& val) {
- return writeTypedVector(val, &Parcel::writeEnum);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::writeEnumVector(const std::optional<std::vector<T>>& val) {
- return writeNullableTypedVector(val, &Parcel::writeEnum);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::writeEnumVector(const std::unique_ptr<std::vector<T>>& val) {
- return writeNullableTypedVector(val, &Parcel::writeEnum);
-}
-
-template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool>>
-status_t Parcel::readEnum(T* pArg) const {
- return readInt32(reinterpret_cast<int32_t *>(pArg));
-}
-template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool>>
-status_t Parcel::readEnum(T* pArg) const {
- return readInt64(reinterpret_cast<int64_t *>(pArg));
-}
-
-template<typename T>
-inline status_t Parcel::readByteVectorInternal(std::vector<T>* val, size_t size) const {
- // readByteVectorInternal expects a vector that has been reserved (but not
- // resized) to have the provided size.
- const T* data = reinterpret_cast<const T*>(readInplace(size));
- if (!data) return BAD_VALUE;
- val->clear();
- val->insert(val->begin(), data, data+size);
- return NO_ERROR;
-}
-
-template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::readEnumVector(std::vector<T>* val) const {
- size_t size;
- if (status_t status = reserveOutVector(val, &size); status != OK) return status;
- return readByteVectorInternal(val, size);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::readEnumVector(std::optional<std::vector<T>>* val) const {
- size_t size;
- if (status_t status = reserveOutVector(val, &size); status != OK) return status;
- if (!*val) {
- // reserveOutVector does not create the out vector if size is < 0.
- // This occurs when writing a null Enum vector.
- return OK;
- }
- return readByteVectorInternal(&**val, size);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const {
- size_t size;
- if (status_t status = reserveOutVector(val, &size); status != OK) return status;
- if (val->get() == nullptr) {
- // reserveOutVector does not create the out vector if size is < 0.
- // This occurs when writing a null Enum vector.
- return OK;
- }
- return readByteVectorInternal(val->get(), size);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::readEnumVector(std::vector<T>* val) const {
- return readTypedVector(val, &Parcel::readEnum);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::readEnumVector(std::optional<std::vector<T>>* val) const {
- return readNullableTypedVector(val, &Parcel::readEnum);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const {
- return readNullableTypedVector(val, &Parcel::readEnum);
-}
-
// ---------------------------------------------------------------------------
inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)
diff --git a/libs/binder/include/binder/ParcelRef.h b/libs/binder/include/binder/ParcelRef.h
new file mode 100644
index 0000000..497da2d
--- /dev/null
+++ b/libs/binder/include/binder/ParcelRef.h
@@ -0,0 +1,43 @@
+/*
+ * 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 <binder/Parcel.h>
+#include <utils/RefBase.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+/**
+ * internal use only
+ * @internal
+ */
+class ParcelRef : public Parcel, public RefBase
+{
+public:
+ static sp<ParcelRef> create() {
+ return new ParcelRef();
+ }
+
+private:
+ ParcelRef() = default;
+};
+
+} // namespace android
+
+// ---------------------------------------------------------------------------
\ No newline at end of file
diff --git a/libs/binder/include/binder/RpcAddress.h b/libs/binder/include/binder/RpcAddress.h
new file mode 100644
index 0000000..5a3f3a6
--- /dev/null
+++ b/libs/binder/include/binder/RpcAddress.h
@@ -0,0 +1,73 @@
+/*
+ * 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 <memory>
+
+#include <utils/Errors.h>
+
+// WARNING: This is a feature which is still in development, and it is subject
+// to radical change. Any production use of this may subject your code to any
+// number of problems.
+
+namespace android {
+
+class Parcel;
+struct RpcWireAddress;
+
+/**
+ * This class represents an identifier of a binder object.
+ *
+ * The purpose of this class it to hide the ABI of an RpcWireAddress, and
+ * potentially allow us to change the size of it in the future (RpcWireAddress
+ * is PIMPL, essentially - although the type that is used here is not exposed).
+ */
+class RpcAddress {
+public:
+ /**
+ * The zero address is used for special RPC transactions, but it might also
+ * be used in conjunction with readFromParcel.
+ */
+ static RpcAddress zero();
+
+ bool isZero() const;
+
+ /**
+ * Create a new address which is unique
+ */
+ static RpcAddress unique();
+
+ /**
+ * Creates a new address as a copy of an embedded object.
+ */
+ static RpcAddress fromRawEmbedded(const RpcWireAddress* raw);
+ const RpcWireAddress& viewRawEmbedded() const;
+
+ bool operator<(const RpcAddress& rhs) const;
+ std::string toString() const;
+
+ status_t writeToParcel(Parcel* parcel) const;
+ status_t readFromParcel(const Parcel& parcel);
+
+ ~RpcAddress();
+
+private:
+ RpcAddress();
+
+ std::shared_ptr<RpcWireAddress> mRawAddr;
+};
+
+} // namespace android
diff --git a/libs/binder/include/binder/RpcConnection.h b/libs/binder/include/binder/RpcConnection.h
new file mode 100644
index 0000000..a300575
--- /dev/null
+++ b/libs/binder/include/binder/RpcConnection.h
@@ -0,0 +1,179 @@
+/*
+ * 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 <android-base/unique_fd.h>
+#include <binder/IBinder.h>
+#include <binder/RpcAddress.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+#include <optional>
+#include <vector>
+
+// WARNING: This is a feature which is still in development, and it is subject
+// to radical change. Any production use of this may subject your code to any
+// number of problems.
+
+namespace android {
+
+class Parcel;
+class RpcServer;
+class RpcState;
+
+/**
+ * This represents a multi-threaded/multi-socket connection between a client
+ * and a server.
+ */
+class RpcConnection final : public virtual RefBase {
+public:
+ static sp<RpcConnection> make();
+
+ /**
+ * This represents a connection for responses, e.g.:
+ *
+ * process A serves binder a
+ * process B opens a connection to process A
+ * process B makes binder b and sends it to A
+ * A uses this 'back connection' to send things back to B
+ *
+ * This should be called once, and then a call should be made to join per
+ * connection thread.
+ */
+ [[nodiscard]] bool setupUnixDomainServer(const char* path);
+
+ /**
+ * This should be called once per thread, matching 'join' in the remote
+ * process.
+ */
+ [[nodiscard]] bool addUnixDomainClient(const char* path);
+
+#ifdef __BIONIC__
+ /**
+ * Creates an RPC server at the current port.
+ */
+ [[nodiscard]] bool setupVsockServer(unsigned int port);
+
+ /**
+ * Connects to an RPC server at the CVD & port.
+ */
+ [[nodiscard]] bool addVsockClient(unsigned int cvd, unsigned int port);
+#endif // __BIONIC__
+
+ /**
+ * Query the other side of the connection for the root object hosted by that
+ * process's RpcServer (if one exists)
+ */
+ sp<IBinder> getRootObject();
+
+ [[nodiscard]] status_t transact(const RpcAddress& address, uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags);
+ [[nodiscard]] status_t sendDecStrong(const RpcAddress& address);
+
+ /**
+ * Adds a server thread accepting connections. Must be called after
+ * setup*Server.
+ */
+ void join();
+
+ ~RpcConnection();
+
+ void setForServer(const wp<RpcServer>& server);
+ wp<RpcServer> server();
+
+ // internal only
+ const std::unique_ptr<RpcState>& state() { return mState; }
+
+ class SocketAddress {
+ public:
+ virtual ~SocketAddress();
+ virtual std::string toString() const = 0;
+ virtual const sockaddr* addr() const = 0;
+ virtual size_t addrSize() const = 0;
+ };
+
+private:
+ RpcConnection();
+
+ bool addServer(const SocketAddress& address);
+ bool addClient(const SocketAddress& address);
+ void assignServerToThisThread(base::unique_fd&& fd);
+
+ struct ConnectionSocket : public RefBase {
+ base::unique_fd fd;
+
+ // whether this or another thread is currently using this fd to make
+ // or receive transactions.
+ std::optional<pid_t> exclusiveTid;
+ };
+
+ enum class SocketUse {
+ CLIENT,
+ CLIENT_ASYNC,
+ CLIENT_REFCOUNT,
+ SERVER,
+ };
+
+ // RAII object for connection socket
+ class ExclusiveSocket {
+ public:
+ explicit ExclusiveSocket(const sp<RpcConnection>& connection, SocketUse use);
+ ~ExclusiveSocket();
+ const base::unique_fd& fd() { return mSocket->fd; }
+
+ private:
+ static void findSocket(pid_t tid, sp<ConnectionSocket>* exclusive,
+ sp<ConnectionSocket>* available,
+ std::vector<sp<ConnectionSocket>>& sockets, size_t socketsIndexHint);
+
+ sp<RpcConnection> mConnection; // avoid deallocation
+ sp<ConnectionSocket> mSocket;
+
+ // whether this is being used for a nested transaction (being on the same
+ // thread guarantees we won't write in the middle of a message, the way
+ // the wire protocol is constructed guarantees this is safe).
+ bool mReentrant = false;
+ };
+
+ // On the other side of a connection, for each of mClients here, there should
+ // be one of mServers on the other side (and vice versa).
+ //
+ // For the simplest connection, a single server with one client, you would
+ // have:
+ // - the server has a single 'mServers' and a thread listening on this
+ // - the client has a single 'mClients' and makes calls to this
+ // - here, when the client makes a call, the server can call back into it
+ // (nested calls), but outside of this, the client will only ever read
+ // calls from the server when it makes a call itself.
+ //
+ // For a more complicated case, the client might itself open up a thread to
+ // serve calls to the server at all times (e.g. if it hosts a callback)
+
+ wp<RpcServer> mForServer; // maybe null, for client connections
+
+ std::unique_ptr<RpcState> mState;
+
+ base::unique_fd mServer; // socket we are accepting connections on
+
+ std::mutex mSocketMutex; // for all below
+ std::condition_variable mSocketCv; // for mWaitingThreads
+ size_t mWaitingThreads = 0;
+ size_t mClientsOffset = 0; // hint index into clients, ++ when sending an async transaction
+ std::vector<sp<ConnectionSocket>> mClients;
+ std::vector<sp<ConnectionSocket>> mServers;
+};
+
+} // namespace android
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
new file mode 100644
index 0000000..a2c2aee
--- /dev/null
+++ b/libs/binder/include/binder/RpcServer.h
@@ -0,0 +1,84 @@
+/*
+ * 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 <android-base/unique_fd.h>
+#include <binder/IBinder.h>
+#include <binder/RpcConnection.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+// WARNING: This is a feature which is still in development, and it is subject
+// to radical change. Any production use of this may subject your code to any
+// number of problems.
+
+namespace android {
+
+/**
+ * This represents a server of an interface, which may be connected to by any
+ * number of clients over sockets.
+ *
+ * This object is not (currently) thread safe. All calls to it are expected to
+ * happen at process startup.
+ */
+class RpcServer final : public virtual RefBase {
+public:
+ static sp<RpcServer> make();
+
+ void iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
+
+ /**
+ * Setup a static connection, when the number of clients are known.
+ *
+ * Each call to this function corresponds to a different client, and clients
+ * each have their own threadpools.
+ *
+ * TODO(b/167966510): support dynamic creation of connections/threads
+ */
+ sp<RpcConnection> addClientConnection();
+
+ /**
+ * Allowing a server to explicitly drop clients would be easy to add here,
+ * but it is not currently implemented, since users of this functionality
+ * could not use similar functionality if they are running under real
+ * binder.
+ */
+ // void drop(const sp<RpcConnection>& connection);
+
+ /**
+ * The root object can be retrieved by any client, without any
+ * authentication.
+ */
+ void setRootObject(const sp<IBinder>& binder);
+
+ /**
+ * Root object set with setRootObject
+ */
+ sp<IBinder> getRootObject();
+
+ ~RpcServer();
+
+private:
+ RpcServer();
+
+ bool mAgreedExperimental = false;
+
+ sp<IBinder> mRootObject;
+
+ std::vector<sp<RpcConnection>> mConnections; // per-client
+};
+
+} // namespace android
diff --git a/libs/binder/include/binder/Stability.h b/libs/binder/include/binder/Stability.h
index 12272ba..a09e587 100644
--- a/libs/binder/include/binder/Stability.h
+++ b/libs/binder/include/binder/Stability.h
@@ -49,10 +49,17 @@
// that it knows how to process. The summary of stability of a binder is
// represented by a Stability::Category object.
-// WARNING: These APIs are only ever expected to be called by auto-generated code.
-// Instead of calling them, you should set the stability of a .aidl interface
class Stability final {
public:
+ // Given a binder interface at a certain stability, there may be some
+ // requirements associated with that higher stability level. For instance, a
+ // VINTF stability binder is required to be in the VINTF manifest. This API
+ // can be called to use that same interface within a partition.
+ static void forceDowngradeCompilationUnit(const sp<IBinder>& binder);
+
+ // WARNING: Below APIs are only ever expected to be called by auto-generated code.
+ // Instead of calling them, you should set the stability of a .aidl interface
+
// WARNING: This is only ever expected to be called by auto-generated code. You likely want to
// change or modify the stability class of the interface you are using.
// This must be called as soon as the binder in question is constructed. No thread safety
@@ -139,9 +146,14 @@
// returns the stability according to how this was built
static Level getLocalLevel();
+ enum {
+ REPR_NONE = 0,
+ REPR_LOG = 1,
+ REPR_ALLOW_DOWNGRADE = 2,
+ };
// applies stability to binder if stability level is known
__attribute__((warn_unused_result))
- static status_t setRepr(IBinder* binder, int32_t representation, bool log);
+ static status_t setRepr(IBinder* binder, int32_t representation, uint32_t flags);
// get stability information as encoded on the wire
static Category getCategory(IBinder* binder);
diff --git a/libs/binder/include/private/binder/binder_module.h b/libs/binder/include/private/binder/binder_module.h
index 5a719b8..1579199 100644
--- a/libs/binder/include/private/binder/binder_module.h
+++ b/libs/binder/include/private/binder/binder_module.h
@@ -88,10 +88,6 @@
};
#endif //BINDER_GET_FROZEN_INFO
-enum transaction_flags_ext {
- TF_CLEAR_BUF = 0x20, /* clear buffer on txn complete */
-};
-
#ifdef __cplusplus
} // namespace android
#endif
diff --git a/libs/binder/include/binder/IBatteryStats.h b/libs/binder/include_batterystats/batterystats/IBatteryStats.h
similarity index 100%
rename from libs/binder/include/binder/IBatteryStats.h
rename to libs/binder/include_batterystats/batterystats/IBatteryStats.h
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 82f3882..eb103d3 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -15,6 +15,23 @@
*/
// TODO(b/31559095): bionic on host should define this
+package {
+ default_applicable_licenses: ["frameworks_native_libs_binder_ndk_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_libs_binder_ndk_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_defaults {
name: "libbinder_ndk_host_user",
target: {
@@ -129,6 +146,26 @@
],
}
+cc_library_headers {
+ name: "libbinder_headers_platform_shared",
+ export_include_dirs: ["include_cpp"],
+ vendor_available: true,
+ host_supported: true,
+ // TODO(b/153609531): remove when no longer needed.
+ native_bridge_supported: true,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media",
+ "com.android.media.swcodec",
+ ],
+ min_sdk_version: "29",
+}
+
ndk_headers {
name: "libbinder_ndk_headers",
from: "include_ndk/android",
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 3c90681..0f59de4 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -181,7 +181,7 @@
binder_status_t status = getClass()->onTransact(this, code, &in, &out);
return PruneStatusT(status);
- } else if (code == SHELL_COMMAND_TRANSACTION && getClass()->handleShellCommand != nullptr) {
+ } else if (code == SHELL_COMMAND_TRANSACTION) {
int in = data.readFileDescriptor();
int out = data.readFileDescriptor();
int err = data.readFileDescriptor();
diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h
index 6824306..22cacb4 100644
--- a/libs/binder/ndk/ibinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -116,13 +116,13 @@
const char* getInterfaceDescriptorUtf8() const { return mInterfaceDescriptor.c_str(); }
// required to be non-null, implemented for every class
- const AIBinder_Class_onCreate onCreate = nullptr;
- const AIBinder_Class_onDestroy onDestroy = nullptr;
- const AIBinder_Class_onTransact onTransact = nullptr;
+ const AIBinder_Class_onCreate onCreate;
+ const AIBinder_Class_onDestroy onDestroy;
+ const AIBinder_Class_onTransact onTransact;
// optional methods for a class
- AIBinder_onDump onDump = nullptr;
- AIBinder_handleShellCommand handleShellCommand = nullptr;
+ AIBinder_onDump onDump;
+ AIBinder_handleShellCommand handleShellCommand;
private:
// Copy of the raw char string for when we don't have to return UTF-16
diff --git a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
index 05eb64b..6c44726 100644
--- a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
@@ -82,7 +82,10 @@
*/
template <class T, class... Args>
static std::shared_ptr<T> make(Args&&... args) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
T* t = new T(std::forward<Args>(args)...);
+#pragma clang diagnostic pop
// warning: Potential leak of memory pointed to by 't' [clang-analyzer-unix.Malloc]
return t->template ref<T>(); // NOLINT(clang-analyzer-unix.Malloc)
}
diff --git a/libs/binder/ndk/include_cpp/android/binder_to_string.h b/libs/binder/ndk/include_cpp/android/binder_to_string.h
new file mode 100644
index 0000000..ef71a81
--- /dev/null
+++ b/libs/binder/ndk/include_cpp/android/binder_to_string.h
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_to_string.h
+ * @brief Helper for parcelable.
+ */
+
+#pragma once
+
+#include <codecvt>
+#include <locale>
+#include <memory>
+#include <optional>
+#include <sstream>
+#include <string>
+#include <type_traits>
+
+#if __has_include(<utils/StrongPointer.h>)
+#include <utils/StrongPointer.h>
+#define HAS_STRONG_POINTER
+#endif
+
+#if __has_include(<utils/String16.h>)
+#include <utils/String16.h>
+#define HAS_STRING16
+#endif
+
+#if __has_include(<android/binder_ibinder.h>)
+#include <android/binder_auto_utils.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#define HAS_NDK_INTERFACE
+#else
+#include <binder/IBinder.h>
+#include <binder/IInterface.h>
+#include <binder/ParcelFileDescriptor.h>
+#include <binder/ParcelableHolder.h>
+#endif //_has_include
+
+namespace android {
+namespace internal {
+
+// ToString is a utility to generate string representation for various AIDL-supported types.
+template <typename _T>
+std::string ToString(const _T& t);
+
+namespace details {
+
+// Truthy if _T has toString() method.
+template <typename _T>
+class HasToStringMethod {
+ template <typename _U>
+ static auto _test(int) -> decltype(std::declval<_U>().toString(), std::true_type());
+ template <typename _U>
+ static std::false_type _test(...);
+
+ public:
+ enum { value = decltype(_test<_T>(0))::value };
+};
+
+// Truthy if _T has a overloaded toString(T)
+template <typename _T>
+class HasToStringFunction {
+ template <typename _U>
+ static auto _test(int) -> decltype(toString(std::declval<_U>()), std::true_type());
+ template <typename _U>
+ static std::false_type _test(...);
+
+ public:
+ enum { value = decltype(_test<_T>(0))::value };
+};
+
+template <typename T, template <typename...> typename U>
+struct IsInstantiationOf : std::false_type {};
+
+template <template <typename...> typename U, typename... Args>
+struct IsInstantiationOf<U<Args...>, U> : std::true_type {};
+
+// Truthy if _T is like a pointer: one of sp/optional/shared_ptr
+template <typename _T>
+class IsPointerLike {
+ template <typename _U>
+ static std::enable_if_t<
+#ifdef HAS_STRONG_POINTER
+ IsInstantiationOf<_U, sp>::value || // for IBinder and interface types in the C++
+ // backend
+#endif
+ IsInstantiationOf<_U, std::optional>::value || // for @nullable types in the
+ // C++/NDK backends
+ IsInstantiationOf<_U, std::shared_ptr>::value, // for interface types in the
+ // NDK backends
+
+ std::true_type>
+ _test(int);
+ template <typename _U>
+ static std::false_type _test(...);
+
+ public:
+ enum { value = decltype(_test<_T>(0))::value };
+};
+
+// Truthy if _T is like a container
+template <typename _T>
+class IsIterable {
+ template <typename _U>
+ static auto _test(int)
+ -> decltype(begin(std::declval<_U>()), end(std::declval<_U>()), std::true_type());
+ template <typename _U>
+ static std::false_type _test(...);
+
+ public:
+ enum { value = decltype(_test<_T>(0))::value };
+};
+
+template <typename _T>
+class ToEmptyString {
+ template <typename _U>
+ static std::enable_if_t<
+#ifdef HAS_NDK_INTERFACE
+ std::is_base_of_v<::ndk::ICInterface, _U> ||
+ std::is_same_v<::ndk::AParcelableHolder, _U>
+#else
+ std::is_base_of_v<IInterface, _U> || std::is_same_v<IBinder, _U> ||
+ std::is_same_v<os::ParcelFileDescriptor, _U> ||
+ std::is_same_v<os::ParcelableHolder, _U>
+#endif
+ ,
+ std::true_type>
+ _test(int);
+ template <typename _U>
+ static std::false_type _test(...);
+
+ public:
+ enum { value = decltype(_test<_T>(0))::value };
+};
+
+} // namespace details
+
+template <typename _T>
+std::string ToString(const _T& t) {
+ if constexpr (details::ToEmptyString<_T>::value) {
+ return "";
+ } else if constexpr (std::is_same_v<bool, _T>) {
+ return t ? "true" : "false";
+ } else if constexpr (std::is_same_v<char16_t, _T>) {
+ return std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>().to_bytes(t);
+ } else if constexpr (std::is_arithmetic_v<_T>) {
+ return std::to_string(t);
+ } else if constexpr (std::is_same_v<std::string, _T>) {
+ return t;
+#ifdef HAS_NDK_INTERFACE
+ } else if constexpr (std::is_same_v<::ndk::SpAIBinder, _T>) {
+ return (t.get() == nullptr) ? "(null)" : "";
+ } else if constexpr (std::is_same_v<::ndk::ScopedFileDescriptor, _T>) {
+ return (t.get() == -1) ? "(null)" : "";
+#endif
+#ifdef HAS_STRING16
+ } else if constexpr (std::is_same_v<String16, _T>) {
+ std::stringstream out;
+ out << t;
+ return out.str();
+#endif
+ } else if constexpr (details::IsPointerLike<_T>::value || std::is_pointer_v<_T>) {
+ if (!t) return "(null)";
+ std::stringstream out;
+ out << ToString(*t);
+ return out.str();
+ } else if constexpr (details::HasToStringMethod<_T>::value) {
+ return t.toString();
+ } else if constexpr (details::HasToStringFunction<_T>::value) {
+ return toString(t);
+ } else if constexpr (details::IsIterable<_T>::value) {
+ std::stringstream out;
+ bool first = true;
+ out << "[";
+ for (const auto& e : t) {
+ if (first) {
+ first = false;
+ } else {
+ out << ", ";
+ }
+ // Use explicit type parameter in case deref of iterator has different type
+ // e.g. vector<bool>
+ out << ToString<typename _T::value_type>(e);
+ }
+ out << "]";
+ return out.str();
+ } else {
+ return "{no toString() implemented}";
+ }
+}
+
+} // namespace internal
+} // namespace android
+
+/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index bb70588..8941e49 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -36,13 +36,6 @@
__BEGIN_DECLS
-#ifndef __ANDROID_API__
-#error Android builds must be compiled against a specific API. If this is an \
- android platform host build, you must use libbinder_ndk_host_user.
-#endif
-
-#if __ANDROID_API__ >= 29
-
typedef uint32_t binder_flags_t;
enum {
/**
@@ -567,10 +560,6 @@
*/
void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient* recipient) __INTRODUCED_IN(29);
-#endif //__ANDROID_API__ >= 29
-
-#if __ANDROID_API__ >= 30
-
/**
* Gets the extension registered with AIBinder_setExtension.
*
@@ -640,10 +629,6 @@
*/
binder_status_t AIBinder_setExtension(AIBinder* binder, AIBinder* ext) __INTRODUCED_IN(30);
-#endif //__ANDROID_API__ >= 30
-
-#if __ANDROID_API__ >= 31
-
/**
* Retrieve the class descriptor for the class.
*
@@ -728,8 +713,6 @@
*/
bool AIBinder_Weak_lt(const AIBinder_Weak* lhs, const AIBinder_Weak* rhs);
-#endif //__ANDROID_API__ >= 31
-
__END_DECLS
/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h b/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
index cd1ff1f..6880d86 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
@@ -31,7 +31,6 @@
#include <jni.h>
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
/**
* Converts an android.os.IBinder object into an AIBinder* object.
@@ -67,7 +66,6 @@
__attribute__((warn_unused_result)) jobject AIBinder_toJavaBinder(JNIEnv* env, AIBinder* binder)
__INTRODUCED_IN(29);
-#endif //__ANDROID_API__ >= 29
__END_DECLS
/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index ab67017..527b151 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -36,7 +36,6 @@
typedef struct AIBinder AIBinder;
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
/**
* This object represents a package of data that can be sent between processes. When transacting, an
@@ -1119,7 +1118,6 @@
// @END-PRIMITIVE-READ-WRITE
-#endif //__ANDROID_API__ >= 29
/**
* Reset the parcel to the initial status.
*
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel_jni.h b/libs/binder/ndk/include_ndk/android/binder_parcel_jni.h
index 65e1704..384d4f7 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel_jni.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel_jni.h
@@ -31,7 +31,6 @@
#include <jni.h>
__BEGIN_DECLS
-#if __ANDROID_API__ >= 30
/**
* Converts an android.os.Parcel object into an AParcel* object.
@@ -50,7 +49,6 @@
__attribute__((warn_unused_result)) AParcel* AParcel_fromJavaParcel(JNIEnv* env, jobject parcel)
__INTRODUCED_IN(30);
-#endif //__ANDROID_API__ >= 30
__END_DECLS
/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_status.h b/libs/binder/ndk/include_ndk/android/binder_status.h
index 3a55f94..b4dc08a 100644
--- a/libs/binder/ndk/include_ndk/android/binder_status.h
+++ b/libs/binder/ndk/include_ndk/android/binder_status.h
@@ -31,8 +31,17 @@
#include <sys/cdefs.h>
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
+#ifndef __ANDROID_API__
+#error Android builds must be compiled against a specific API. If this is an \
+ android platform host build, you must use libbinder_ndk_host_user.
+#endif
+
+/**
+ * Low-level status types for use in binder. This is the least preferable way to
+ * return an error for binder services (where binder_exception_t should be used,
+ * particularly EX_SERVICE_SPECIFIC).
+ */
enum {
STATUS_OK = 0,
@@ -63,6 +72,10 @@
*/
typedef int32_t binder_status_t;
+/**
+ * Top level exceptions types for Android binder errors, mapping to Java
+ * exceptions. Also see Parcel.java.
+ */
enum {
EX_NONE = 0,
EX_SECURITY = -1,
@@ -171,7 +184,8 @@
/**
* New status with binder_status_t. This is typically for low level failures when a binder_status_t
* is returned by an API on AIBinder or AParcel, and that is to be returned from a method returning
- * an AStatus instance.
+ * an AStatus instance. This is the least preferable way to return errors.
+ * Prefer exceptions (particularly service-specific errors) when possible.
*
* Available since API level 29.
*
@@ -275,7 +289,6 @@
*/
void AStatus_delete(AStatus* status) __INTRODUCED_IN(29);
-#endif //__ANDROID_API__ >= 29
__END_DECLS
/** @} */
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
index 2784aa8..5516914 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -26,18 +26,25 @@
* This registers the service with the default service manager under this instance name. This does
* not take ownership of binder.
*
+ * WARNING: when using this API across an APEX boundary, do not use with unstable
+ * AIDL services. TODO(b/139325195)
+ *
* \param binder object to register globally with the service manager.
* \param instance identifier of the service. This will be used to lookup the service.
*
* \return EX_NONE on success.
*/
-binder_exception_t AServiceManager_addService(AIBinder* binder, const char* instance);
+__attribute__((warn_unused_result)) binder_exception_t AServiceManager_addService(
+ AIBinder* binder, const char* instance);
/**
* Gets a binder object with this specific instance name. Will return nullptr immediately if the
* service is not available This also implicitly calls AIBinder_incStrong (so the caller of this
* function is responsible for calling AIBinder_decStrong).
*
+ * WARNING: when using this API across an APEX boundary, do not use with unstable
+ * AIDL services. TODO(b/139325195)
+ *
* \param instance identifier of the service used to lookup the service.
*/
__attribute__((warn_unused_result)) AIBinder* AServiceManager_checkService(const char* instance);
@@ -47,6 +54,9 @@
* it. This also implicitly calls AIBinder_incStrong (so the caller of this function is responsible
* for calling AIBinder_decStrong).
*
+ * WARNING: when using this API across an APEX boundary, do not use with unstable
+ * AIDL services. TODO(b/139325195)
+ *
* \param instance identifier of the service used to lookup the service.
*/
__attribute__((warn_unused_result)) AIBinder* AServiceManager_getService(const char* instance);
@@ -77,6 +87,9 @@
* This also implicitly calls AIBinder_incStrong (so the caller of this function is responsible
* for calling AIBinder_decStrong).
*
+ * WARNING: when using this API across an APEX boundary, do not use with unstable
+ * AIDL services. TODO(b/139325195)
+ *
* \param instance identifier of the service used to lookup the service.
*
* \return service if registered, null if not.
@@ -94,4 +107,68 @@
*/
bool AServiceManager_isDeclared(const char* instance) __INTRODUCED_IN(31);
+/**
+ * Returns all declared instances for a particular interface.
+ *
+ * For instance, if 'android.foo.IFoo/foo' is declared, and 'android.foo.IFoo' is
+ * passed here, then ["foo"] would be returned.
+ *
+ * See also AServiceManager_isDeclared.
+ *
+ * \param interface interface, e.g. 'android.foo.IFoo'
+ * \param context to pass to callback
+ * \param callback taking instance (e.g. 'foo') and context
+ */
+void AServiceManager_forEachDeclaredInstance(const char* interface, void* context,
+ void (*callback)(const char*, void*))
+ __INTRODUCED_IN(31);
+
+/**
+ * Prevent lazy services without client from shutting down their process
+ *
+ * \param persist 'true' if the process should not exit.
+ */
+void AServiceManager_forceLazyServicesPersist(bool persist) __INTRODUCED_IN(31);
+
+/**
+ * Set a callback that is invoked when the active service count (i.e. services with clients)
+ * registered with this process drops to zero (or becomes nonzero).
+ * The callback takes a boolean argument, which is 'true' if there is
+ * at least one service with clients.
+ *
+ * \param callback function to call when the number of services
+ * with clients changes.
+ * \param context opaque pointer passed back as second parameter to the
+ * callback.
+ *
+ * The callback takes two arguments. The first is a boolean that represents if there are
+ * services with clients (true) or not (false).
+ * The second is the 'context' pointer passed during the registration.
+ *
+ * Callback return value:
+ * - false: Default behavior for lazy services (shut down the process if there
+ * are no clients).
+ * - true: Don't shut down the process even if there are no clients.
+ *
+ * This callback gives a chance to:
+ * 1 - Perform some additional operations before exiting;
+ * 2 - Prevent the process from exiting by returning "true" from the callback.
+ */
+void AServiceManager_setActiveServicesCallback(bool (*callback)(bool, void*), void* context)
+ __INTRODUCED_IN(31);
+
+/**
+ * Try to unregister all services previously registered with 'registerService'.
+ *
+ * \return true on success.
+ */
+bool AServiceManager_tryUnregister() __INTRODUCED_IN(31);
+
+/**
+ * Re-register services that were unregistered by 'tryUnregister'.
+ * This method should be called in the case 'tryUnregister' fails
+ * (and should be called on the same thread).
+ */
+void AServiceManager_reRegister() __INTRODUCED_IN(31);
+
__END_DECLS
diff --git a/libs/binder/ndk/include_platform/android/binder_parcel_platform.h b/libs/binder/ndk/include_platform/android/binder_parcel_platform.h
index d54c1a1..6372449 100644
--- a/libs/binder/ndk/include_platform/android/binder_parcel_platform.h
+++ b/libs/binder/ndk/include_platform/android/binder_parcel_platform.h
@@ -20,9 +20,7 @@
__BEGIN_DECLS
-#if defined(__ANDROID_APEX__) || defined(__ANDROID_VNDK__)
-#error this is only for platform code
-#endif
+#if !defined(__ANDROID_APEX__) && !defined(__ANDROID_VNDK__)
/**
* Gets whether or not FDs are allowed by this AParcel
@@ -33,6 +31,9 @@
*/
bool AParcel_getAllowFds(const AParcel*);
+#endif
+
+#if !defined(__ANDROID_APEX__)
/**
* Data written to the parcel will be zero'd before being deleted or realloced.
*
@@ -43,5 +44,6 @@
* \param parcel The parcel to clear associated data from.
*/
void AParcel_markSensitive(const AParcel* parcel);
+#endif
__END_DECLS
diff --git a/libs/binder/ndk/include_platform/android/binder_stability.h b/libs/binder/ndk/include_platform/android/binder_stability.h
index f5e8bf6..c23716c 100644
--- a/libs/binder/ndk/include_platform/android/binder_stability.h
+++ b/libs/binder/ndk/include_platform/android/binder_stability.h
@@ -30,7 +30,7 @@
FLAG_PRIVATE_VENDOR = 0x10000000,
};
-#if defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#if defined(__ANDROID_VENDOR__)
enum {
FLAG_PRIVATE_LOCAL = FLAG_PRIVATE_VENDOR,
@@ -45,7 +45,7 @@
AIBinder_markVendorStability(binder);
}
-#else // defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#else // defined(__ANDROID_VENDOR__)
enum {
FLAG_PRIVATE_LOCAL = 0,
@@ -62,9 +62,15 @@
AIBinder_markSystemStability(binder);
}
-#endif // defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#endif // defined(__ANDROID_VENDOR__)
/**
+ * WARNING: this is not expected to be used manually. When the build system has
+ * versioned checks in place for an interface that prevent it being changed year
+ * over year (specifically like those for @VintfStability stable AIDL
+ * interfaces), this could be called. Calling this without this or equivalent
+ * infrastructure will lead to de facto frozen APIs or GSI test failures.
+ *
* This interface has system<->vendor stability
*/
void AIBinder_markVintfStability(AIBinder* binder);
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 9a93bf3..f1db653 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -117,9 +117,15 @@
ABinderProcess_setupPolling; # apex
AIBinder_getCallingSid; # apex
AIBinder_setRequestingSid; # apex
+ AParcel_markSensitive; # llndk
AServiceManager_isDeclared; # apex llndk
+ AServiceManager_forEachDeclaredInstance; # apex llndk
AServiceManager_registerLazyService; # llndk
AServiceManager_waitForService; # apex llndk
+ AServiceManager_forceLazyServicesPersist; # llndk
+ AServiceManager_setActiveServicesCallback; # llndk
+ AServiceManager_tryUnregister; # llndk
+ AServiceManager_reRegister; # llndk
AIBinder_Class_getDescriptor;
AIBinder_Weak_clone;
@@ -134,7 +140,6 @@
LIBBINDER_NDK_PLATFORM {
global:
AParcel_getAllowFds;
- AParcel_markSensitive;
extern "C++" {
AIBinder_fromPlatformBinder*;
AIBinder_toPlatformBinder*;
diff --git a/libs/binder/ndk/parcel_internal.h b/libs/binder/ndk/parcel_internal.h
index 6b7295e..aebc7f4 100644
--- a/libs/binder/ndk/parcel_internal.h
+++ b/libs/binder/ndk/parcel_internal.h
@@ -27,10 +27,13 @@
const ::android::Parcel* get() const { return mParcel; }
::android::Parcel* get() { return mParcel; }
- explicit AParcel(const AIBinder* binder)
- : AParcel(binder, new ::android::Parcel, true /*owns*/) {}
- AParcel(const AIBinder* binder, ::android::Parcel* parcel, bool owns)
- : mBinder(binder), mParcel(parcel), mOwns(owns) {}
+ explicit AParcel(AIBinder* binder) : AParcel(binder, new ::android::Parcel, true /*owns*/) {}
+ AParcel(AIBinder* binder, ::android::Parcel* parcel, bool owns)
+ : mBinder(binder), mParcel(parcel), mOwns(owns) {
+ if (binder != nullptr) {
+ parcel->markForBinder(binder->getBinder());
+ }
+ }
~AParcel() {
if (mOwns) {
@@ -38,7 +41,7 @@
}
}
- static const AParcel readOnly(const AIBinder* binder, const ::android::Parcel* parcel) {
+ static const AParcel readOnly(AIBinder* binder, const ::android::Parcel* parcel) {
return AParcel(binder, const_cast<::android::Parcel*>(parcel), false);
}
diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp
index c782d47..1ccd0d2 100644
--- a/libs/binder/ndk/service_manager.cpp
+++ b/libs/binder/ndk/service_manager.cpp
@@ -19,6 +19,7 @@
#include "ibinder_internal.h"
#include "status_internal.h"
+#include <android-base/logging.h>
#include <binder/IServiceManager.h>
#include <binder/LazyServiceRegistrar.h>
@@ -28,6 +29,7 @@
using ::android::sp;
using ::android::status_t;
using ::android::String16;
+using ::android::String8;
binder_exception_t AServiceManager_addService(AIBinder* binder, const char* instance) {
if (binder == nullptr || instance == nullptr) {
@@ -92,3 +94,33 @@
sp<IServiceManager> sm = defaultServiceManager();
return sm->isDeclared(String16(instance));
}
+void AServiceManager_forEachDeclaredInstance(const char* interface, void* context,
+ void (*callback)(const char*, void*)) {
+ CHECK(interface != nullptr);
+ // context may be nullptr
+ CHECK(callback != nullptr);
+
+ sp<IServiceManager> sm = defaultServiceManager();
+ for (const String16& instance : sm->getDeclaredInstances(String16(interface))) {
+ callback(String8(instance).c_str(), context);
+ }
+}
+void AServiceManager_forceLazyServicesPersist(bool persist) {
+ auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
+ serviceRegistrar.forcePersist(persist);
+}
+void AServiceManager_setActiveServicesCallback(bool (*callback)(bool, void*), void* context) {
+ auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
+ std::function<bool(bool)> fn = [=](bool hasClients) -> bool {
+ return callback(hasClients, context);
+ };
+ serviceRegistrar.setActiveServicesCallback(fn);
+}
+bool AServiceManager_tryUnregister() {
+ auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
+ return serviceRegistrar.tryUnregister();
+}
+void AServiceManager_reRegister() {
+ auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
+ serviceRegistrar.reRegister();
+}
diff --git a/libs/binder/ndk/tests/Android.bp b/libs/binder/ndk/tests/Android.bp
index 46e6270..bb51bf0 100644
--- a/libs/binder/ndk/tests/Android.bp
+++ b/libs/binder/ndk/tests/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_libs_binder_ndk_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_libs_binder_ndk_license"],
+}
+
cc_defaults {
name: "test_libbinder_ndk_defaults",
shared_libs: [
diff --git a/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl b/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl
index dc77467d..ecbd649 100644
--- a/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl
+++ b/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl
@@ -28,4 +28,7 @@
void forceFlushCommands();
boolean getsRequestedSid();
+
+ void forcePersist(boolean persist);
+ void setCustomActiveServicesCallback();
}
diff --git a/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp b/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp
index ad78e31..f3cd218 100644
--- a/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp
+++ b/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp
@@ -163,7 +163,8 @@
// LOCAL SERVERS
std::shared_ptr<NdkServer> ndkServer = SharedRefBase::make<NdkServer>();
- AServiceManager_addService(ndkServer->asBinder().get(), kLocalNdkServerName.c_str());
+ CHECK(STATUS_OK ==
+ AServiceManager_addService(ndkServer->asBinder().get(), kLocalNdkServerName.c_str()));
return RUN_ALL_TESTS();
}
diff --git a/libs/binder/ndk/tests/iface.cpp b/libs/binder/ndk/tests/iface.cpp
index 2afe5d2..53b5c3c 100644
--- a/libs/binder/ndk/tests/iface.cpp
+++ b/libs/binder/ndk/tests/iface.cpp
@@ -118,7 +118,7 @@
AIBinder_Weak_delete(mWeakBinder);
}
-AIBinder* IFoo::getBinder() {
+binder_status_t IFoo::addService(const char* instance) {
AIBinder* binder = nullptr;
if (mWeakBinder != nullptr) {
@@ -132,18 +132,8 @@
AIBinder_Weak_delete(mWeakBinder);
}
mWeakBinder = AIBinder_Weak_new(binder);
-
- // WARNING: it is important that this class does not implement debug or
- // shell functions because it does not use special C++ wrapper
- // functions, and so this is how we test those functions.
}
- return binder;
-}
-
-binder_status_t IFoo::addService(const char* instance) {
- AIBinder* binder = getBinder();
-
binder_status_t status = AServiceManager_addService(binder, instance);
// Strong references we care about kept by remote process
AIBinder_decStrong(binder);
diff --git a/libs/binder/ndk/tests/include/iface/iface.h b/libs/binder/ndk/tests/include/iface/iface.h
index 7408d0c..244c985 100644
--- a/libs/binder/ndk/tests/include/iface/iface.h
+++ b/libs/binder/ndk/tests/include/iface/iface.h
@@ -31,9 +31,6 @@
static AIBinder_Class* kClass;
- // binder representing this interface with one reference count
- AIBinder* getBinder();
-
// Takes ownership of IFoo
binder_status_t addService(const char* instance);
static ::android::sp<IFoo> getService(const char* instance, AIBinder** outBinder = nullptr);
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 0d1989e..496a915 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -46,6 +46,11 @@
constexpr char kExistingNonNdkService[] = "SurfaceFlinger";
constexpr char kBinderNdkUnitTestService[] = "BinderNdkUnitTest";
constexpr char kLazyBinderNdkUnitTestService[] = "LazyBinderNdkUnitTest";
+constexpr char kForcePersistNdkUnitTestService[] = "ForcePersistNdkUnitTestService";
+constexpr char kActiveServicesNdkUnitTestService[] = "ActiveServicesNdkUnitTestService";
+
+constexpr unsigned int kShutdownWaitTime = 10;
+constexpr uint64_t kContextTestValue = 0xb4e42fb4d9a1d715;
class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest {
ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) {
@@ -76,6 +81,46 @@
fsync(out);
return STATUS_OK;
}
+ ndk::ScopedAStatus forcePersist(bool persist) {
+ AServiceManager_forceLazyServicesPersist(persist);
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus setCustomActiveServicesCallback() {
+ AServiceManager_setActiveServicesCallback(activeServicesCallback, this);
+ return ndk::ScopedAStatus::ok();
+ }
+ static bool activeServicesCallback(bool hasClients, void* context) {
+ if (hasClients) {
+ return false;
+ }
+
+ // Unregister all services
+ if (!AServiceManager_tryUnregister()) {
+ // Prevent shutdown (test will fail)
+ return false;
+ }
+
+ // Re-register all services
+ AServiceManager_reRegister();
+
+ // Unregister again before shutdown
+ if (!AServiceManager_tryUnregister()) {
+ // Prevent shutdown (test will fail)
+ return false;
+ }
+
+ // Check if the context was passed correctly
+ MyBinderNdkUnitTest* service = static_cast<MyBinderNdkUnitTest*>(context);
+ if (service->contextTestValue != kContextTestValue) {
+ // Prevent shutdown (test will fail)
+ return false;
+ }
+
+ exit(EXIT_SUCCESS);
+ // Unreachable
+ }
+
+ uint64_t contextTestValue = kContextTestValue;
};
int generatedService() {
@@ -168,6 +213,16 @@
return 1; // should not return
}
+bool isServiceRunning(const char* serviceName) {
+ AIBinder* binder = AServiceManager_checkService(serviceName);
+ if (binder == nullptr) {
+ return false;
+ }
+ AIBinder_decStrong(binder);
+
+ return true;
+}
+
TEST(NdkBinder, GetServiceThatDoesntExist) {
sp<IFoo> foo = IFoo::getService("asdfghkl;");
EXPECT_EQ(nullptr, foo.get());
@@ -186,26 +241,6 @@
AIBinder_decStrong(binder);
}
-TEST(NdkBinder, UnimplementedDump) {
- sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName);
- ASSERT_NE(foo, nullptr);
- AIBinder* binder = foo->getBinder();
- EXPECT_EQ(OK, AIBinder_dump(binder, STDOUT_FILENO, nullptr, 0));
- AIBinder_decStrong(binder);
-}
-
-TEST(NdkBinder, UnimplementedShell) {
- // libbinder_ndk doesn't support calling shell, so we are calling from the
- // libbinder across processes to the NDK service which doesn't implement
- // shell
- static const sp<android::IServiceManager> sm(android::defaultServiceManager());
- sp<IBinder> testService = sm->getService(String16(IFoo::kSomeInstanceName));
-
- Vector<String16> argsVec;
- EXPECT_EQ(OK, IBinder::shellCommand(testService, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO,
- argsVec, nullptr, nullptr));
-}
-
TEST(NdkBinder, DoubleNumber) {
sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName);
ASSERT_NE(foo, nullptr);
@@ -215,6 +250,25 @@
EXPECT_EQ(2, out);
}
+void defaultInstanceCounter(const char* instance, void* context) {
+ if (strcmp(instance, "default") == 0) {
+ ++*(size_t*)(context);
+ }
+}
+
+TEST(NdkBinder, GetDeclaredInstances) {
+ bool hasLight = AServiceManager_isDeclared("android.hardware.light.ILights/default");
+
+ size_t count;
+ AServiceManager_forEachDeclaredInstance("android.hardware.light.ILights", &count,
+ defaultInstanceCounter);
+
+ // At the time of writing this test, there is no good interface guaranteed
+ // to be on all devices. Cuttlefish has light, so this will generally test
+ // things.
+ EXPECT_EQ(count, hasLight ? 1 : 0);
+}
+
TEST(NdkBinder, GetLazyService) {
// Not declared in the vintf manifest
ASSERT_FALSE(AServiceManager_isDeclared(kLazyBinderNdkUnitTestService));
@@ -238,10 +292,51 @@
service = nullptr;
IPCThreadState::self()->flushCommands();
// Make sure the service is dead after some time of no use
- sleep(10);
+ sleep(kShutdownWaitTime);
ASSERT_EQ(nullptr, AServiceManager_checkService(kLazyBinderNdkUnitTestService));
}
+TEST(NdkBinder, ForcedPersistenceTest) {
+ for (int i = 0; i < 2; i++) {
+ ndk::SpAIBinder binder(AServiceManager_waitForService(kForcePersistNdkUnitTestService));
+ std::shared_ptr<aidl::IBinderNdkUnitTest> service =
+ aidl::IBinderNdkUnitTest::fromBinder(binder);
+ ASSERT_NE(service, nullptr);
+ ASSERT_TRUE(service->forcePersist(i == 0).isOk());
+
+ binder = nullptr;
+ service = nullptr;
+ IPCThreadState::self()->flushCommands();
+
+ sleep(kShutdownWaitTime);
+
+ bool isRunning = isServiceRunning(kForcePersistNdkUnitTestService);
+
+ if (i == 0) {
+ ASSERT_TRUE(isRunning) << "Service shut down when it shouldn't have.";
+ } else {
+ ASSERT_FALSE(isRunning) << "Service failed to shut down.";
+ }
+ }
+}
+
+TEST(NdkBinder, ActiveServicesCallbackTest) {
+ ndk::SpAIBinder binder(AServiceManager_waitForService(kActiveServicesNdkUnitTestService));
+ std::shared_ptr<aidl::IBinderNdkUnitTest> service =
+ aidl::IBinderNdkUnitTest::fromBinder(binder);
+ ASSERT_NE(service, nullptr);
+ ASSERT_TRUE(service->setCustomActiveServicesCallback().isOk());
+
+ binder = nullptr;
+ service = nullptr;
+ IPCThreadState::self()->flushCommands();
+
+ sleep(kShutdownWaitTime);
+
+ ASSERT_FALSE(isServiceRunning(kActiveServicesNdkUnitTestService))
+ << "Service failed to shut down.";
+}
+
void LambdaOnDeath(void* cookie) {
auto onDeath = static_cast<std::function<void(void)>*>(cookie);
(*onDeath)();
@@ -564,10 +659,18 @@
}
if (fork() == 0) {
prctl(PR_SET_PDEATHSIG, SIGHUP);
+ return lazyService(kForcePersistNdkUnitTestService);
+ }
+ if (fork() == 0) {
+ prctl(PR_SET_PDEATHSIG, SIGHUP);
+ return lazyService(kActiveServicesNdkUnitTestService);
+ }
+ if (fork() == 0) {
+ prctl(PR_SET_PDEATHSIG, SIGHUP);
return generatedService();
}
- ABinderProcess_setThreadPoolMaxThreadCount(1); // to recieve death notifications/callbacks
+ ABinderProcess_setThreadPoolMaxThreadCount(1); // to receive death notifications/callbacks
ABinderProcess_startThreadPool();
return RUN_ALL_TESTS();
diff --git a/libs/binder/parcel_fuzzer/Android.bp b/libs/binder/parcel_fuzzer/Android.bp
index 3e6fe99..74b8eb8 100644
--- a/libs/binder/parcel_fuzzer/Android.bp
+++ b/libs/binder/parcel_fuzzer/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_fuzz {
name: "binder_parcel_fuzzer",
defaults: ["libbinder_ndk_host_user"],
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index fd5f2f5..e12a429 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
rust_library {
name: "libbinder_rs",
crate_name: "binder",
@@ -14,7 +23,11 @@
darwin: {
enabled: false,
}
- }
+ },
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.virt",
+ ],
}
rust_library {
@@ -32,7 +45,11 @@
darwin: {
enabled: false,
}
- }
+ },
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.virt",
+ ],
}
rust_bindgen {
@@ -78,6 +95,10 @@
enabled: false,
},
},
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.virt",
+ ],
}
rust_test {
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
index 42c1e0a..321b422 100644
--- a/libs/binder/rust/src/binder.rs
+++ b/libs/binder/rust/src/binder.rs
@@ -16,25 +16,30 @@
//! Trait definitions for binder objects
-use crate::error::{status_t, Result};
+use crate::error::{status_t, Result, StatusCode};
use crate::parcel::Parcel;
-use crate::proxy::{DeathRecipient, SpIBinder};
+use crate::proxy::{DeathRecipient, SpIBinder, WpIBinder};
use crate::sys;
+use std::borrow::Borrow;
+use std::cmp::Ordering;
use std::ffi::{c_void, CStr, CString};
+use std::fmt;
+use std::marker::PhantomData;
+use std::ops::Deref;
use std::os::raw::c_char;
use std::os::unix::io::AsRawFd;
use std::ptr;
/// Binder action to perform.
///
-/// This must be a number between [`IBinder::FIRST_CALL_TRANSACTION`] and
-/// [`IBinder::LAST_CALL_TRANSACTION`].
+/// This must be a number between [`FIRST_CALL_TRANSACTION`] and
+/// [`LAST_CALL_TRANSACTION`].
pub type TransactionCode = u32;
/// Additional operation flags.
///
-/// `IBinder::FLAG_*` values.
+/// `FLAG_*` values.
pub type TransactionFlags = u32;
/// Super-trait for Binder interfaces.
@@ -44,13 +49,33 @@
/// interfaces) must implement this trait.
///
/// This is equivalent `IInterface` in C++.
-pub trait Interface {
+pub trait Interface: Send {
/// Convert this binder object into a generic [`SpIBinder`] reference.
fn as_binder(&self) -> SpIBinder {
panic!("This object was not a Binder object and cannot be converted into an SpIBinder.")
}
}
+/// Interface stability promise
+///
+/// An interface can promise to be a stable vendor interface ([`Vintf`]), or
+/// makes no stability guarantees ([`Local`]). [`Local`] is
+/// currently the default stability.
+pub enum Stability {
+ /// Default stability, visible to other modules in the same compilation
+ /// context (e.g. modules on system.img)
+ Local,
+
+ /// A Vendor Interface Object, which promises to be stable
+ Vintf,
+}
+
+impl Default for Stability {
+ fn default() -> Self {
+ Stability::Local
+ }
+}
+
/// A local service that can be remotable via Binder.
///
/// An object that implement this interface made be made into a Binder service
@@ -80,20 +105,24 @@
fn get_class() -> InterfaceClass;
}
-/// Interface of binder local or remote objects.
+/// First transaction code available for user commands (inclusive)
+pub const FIRST_CALL_TRANSACTION: TransactionCode = sys::FIRST_CALL_TRANSACTION;
+/// Last transaction code available for user commands (inclusive)
+pub const LAST_CALL_TRANSACTION: TransactionCode = sys::LAST_CALL_TRANSACTION;
+
+/// Corresponds to TF_ONE_WAY -- an asynchronous call.
+pub const FLAG_ONEWAY: TransactionFlags = sys::FLAG_ONEWAY;
+/// Corresponds to TF_CLEAR_BUF -- clear transaction buffers after call is made.
+pub const FLAG_CLEAR_BUF: TransactionFlags = sys::FLAG_CLEAR_BUF;
+/// Set to the vendor flag if we are building for the VNDK, 0 otherwise
+pub const FLAG_PRIVATE_LOCAL: TransactionFlags = sys::FLAG_PRIVATE_LOCAL;
+
+/// Internal interface of binder local or remote objects for making
+/// transactions.
///
-/// This trait corresponds to the interface of the C++ `IBinder` class.
-pub trait IBinder {
- /// First transaction code available for user commands (inclusive)
- const FIRST_CALL_TRANSACTION: TransactionCode = sys::FIRST_CALL_TRANSACTION;
- /// Last transaction code available for user commands (inclusive)
- const LAST_CALL_TRANSACTION: TransactionCode = sys::LAST_CALL_TRANSACTION;
-
- /// Corresponds to TF_ONE_WAY -- an asynchronous call.
- const FLAG_ONEWAY: TransactionFlags = sys::FLAG_ONEWAY;
- /// Corresponds to TF_CLEAR_BUF -- clear transaction buffers after call is made.
- const FLAG_CLEAR_BUF: TransactionFlags = sys::FLAG_CLEAR_BUF;
-
+/// This trait corresponds to the parts of the interface of the C++ `IBinder`
+/// class which are internal implementation details.
+pub trait IBinderInternal: IBinder {
/// Is this object still alive?
fn is_binder_alive(&self) -> bool;
@@ -117,19 +146,24 @@
/// * `data` - [`Parcel`] with input data
/// * `reply` - Optional [`Parcel`] for reply data
/// * `flags` - Transaction flags, e.g. marking the transaction as
- /// asynchronous ([`FLAG_ONEWAY`](IBinder::FLAG_ONEWAY))
+ /// asynchronous ([`FLAG_ONEWAY`](FLAG_ONEWAY))
fn transact<F: FnOnce(&mut Parcel) -> Result<()>>(
&self,
code: TransactionCode,
flags: TransactionFlags,
input_callback: F,
) -> Result<Parcel>;
+}
+/// Interface of binder local or remote objects.
+///
+/// This trait corresponds to the parts of the interface of the C++ `IBinder`
+/// class which are public.
+pub trait IBinder {
/// Register the recipient for a notification if this binder
/// goes away. If this binder object unexpectedly goes away
/// (typically because its hosting process has been killed),
- /// then DeathRecipient::binder_died() will be called with a reference
- /// to this.
+ /// then the `DeathRecipient`'s callback will be called.
///
/// You will only receive death notifications for remote binders,
/// as local binders by definition can't die without you dying as well.
@@ -137,11 +171,6 @@
/// INVALID_OPERATION code being returned and nothing happening.
///
/// This link always holds a weak reference to its recipient.
- ///
- /// You will only receive a weak reference to the dead
- /// binder. You should not try to promote this to a strong reference.
- /// (Nor should you need to, as there is nothing useful you can
- /// directly do with it now that it has passed on.)
fn link_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()>;
/// Remove a previously registered death notification.
@@ -217,7 +246,8 @@
// the number of u16 elements before the null terminator.
let raw_descriptor: *const c_char = sys::AIBinder_Class_getDescriptor(self.0);
- CStr::from_ptr(raw_descriptor).to_str()
+ CStr::from_ptr(raw_descriptor)
+ .to_str()
.expect("Expected valid UTF-8 string from AIBinder_Class_getDescriptor")
.into()
}
@@ -230,6 +260,132 @@
}
}
+/// Strong reference to a binder object
+pub struct Strong<I: FromIBinder + ?Sized>(Box<I>);
+
+impl<I: FromIBinder + ?Sized> Strong<I> {
+ /// Create a new strong reference to the provided binder object
+ pub fn new(binder: Box<I>) -> Self {
+ Self(binder)
+ }
+
+ /// Construct a new weak reference to this binder
+ pub fn downgrade(this: &Strong<I>) -> Weak<I> {
+ Weak::new(this)
+ }
+}
+
+impl<I: FromIBinder + ?Sized> Clone for Strong<I> {
+ fn clone(&self) -> Self {
+ // Since we hold a strong reference, we should always be able to create
+ // a new strong reference to the same interface type, so try_from()
+ // should never fail here.
+ FromIBinder::try_from(self.0.as_binder()).unwrap()
+ }
+}
+
+impl<I: FromIBinder + ?Sized> Borrow<I> for Strong<I> {
+ fn borrow(&self) -> &I {
+ &self.0
+ }
+}
+
+impl<I: FromIBinder + ?Sized> AsRef<I> for Strong<I> {
+ fn as_ref(&self) -> &I {
+ &self.0
+ }
+}
+
+impl<I: FromIBinder + ?Sized> Deref for Strong<I> {
+ type Target = I;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl<I: FromIBinder + fmt::Debug + ?Sized> fmt::Debug for Strong<I> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Debug::fmt(&**self, f)
+ }
+}
+
+impl<I: FromIBinder + ?Sized> Ord for Strong<I> {
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.0.as_binder().cmp(&other.0.as_binder())
+ }
+}
+
+impl<I: FromIBinder + ?Sized> PartialOrd for Strong<I> {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ self.0.as_binder().partial_cmp(&other.0.as_binder())
+ }
+}
+
+impl<I: FromIBinder + ?Sized> PartialEq for Strong<I> {
+ fn eq(&self, other: &Self) -> bool {
+ self.0.as_binder().eq(&other.0.as_binder())
+ }
+}
+
+impl<I: FromIBinder + ?Sized> Eq for Strong<I> {}
+
+/// Weak reference to a binder object
+#[derive(Debug)]
+pub struct Weak<I: FromIBinder + ?Sized> {
+ weak_binder: WpIBinder,
+ interface_type: PhantomData<I>,
+}
+
+impl<I: FromIBinder + ?Sized> Weak<I> {
+ /// Construct a new weak reference from a strong reference
+ fn new(binder: &Strong<I>) -> Self {
+ let weak_binder = binder.as_binder().downgrade();
+ Weak {
+ weak_binder,
+ interface_type: PhantomData,
+ }
+ }
+
+ /// Upgrade this weak reference to a strong reference if the binder object
+ /// is still alive
+ pub fn upgrade(&self) -> Result<Strong<I>> {
+ self.weak_binder
+ .promote()
+ .ok_or(StatusCode::DEAD_OBJECT)
+ .and_then(FromIBinder::try_from)
+ }
+}
+
+impl<I: FromIBinder + ?Sized> Clone for Weak<I> {
+ fn clone(&self) -> Self {
+ Self {
+ weak_binder: self.weak_binder.clone(),
+ interface_type: PhantomData,
+ }
+ }
+}
+
+impl<I: FromIBinder + ?Sized> Ord for Weak<I> {
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.weak_binder.cmp(&other.weak_binder)
+ }
+}
+
+impl<I: FromIBinder + ?Sized> PartialOrd for Weak<I> {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ self.weak_binder.partial_cmp(&other.weak_binder)
+ }
+}
+
+impl<I: FromIBinder + ?Sized> PartialEq for Weak<I> {
+ fn eq(&self, other: &Self) -> bool {
+ self.weak_binder == other.weak_binder
+ }
+}
+
+impl<I: FromIBinder + ?Sized> Eq for Weak<I> {}
+
/// Create a function implementing a static getter for an interface class.
///
/// Each binder interface (i.e. local [`Remotable`] service or remote proxy
@@ -354,12 +510,12 @@
/// }
/// }
/// ```
-pub trait FromIBinder {
+pub trait FromIBinder: Interface {
/// Try to interpret a generic Binder object as this interface.
///
/// Returns a trait object for the `Self` interface if this object
/// implements that interface.
- fn try_from(ibinder: SpIBinder) -> Result<Box<Self>>;
+ fn try_from(ibinder: SpIBinder) -> Result<Strong<Self>>;
}
/// Trait for transparent Rust wrappers around android C++ native types.
@@ -468,6 +624,23 @@
$interface[$descriptor] {
native: $native($on_transact),
proxy: $proxy {},
+ stability: $crate::Stability::default(),
+ }
+ }
+ };
+
+ {
+ $interface:path[$descriptor:expr] {
+ native: $native:ident($on_transact:path),
+ proxy: $proxy:ident,
+ stability: $stability:expr,
+ }
+ } => {
+ $crate::declare_binder_interface! {
+ $interface[$descriptor] {
+ native: $native($on_transact),
+ proxy: $proxy {},
+ stability: $stability,
}
}
};
@@ -482,12 +655,33 @@
} => {
$crate::declare_binder_interface! {
$interface[$descriptor] {
+ native: $native($on_transact),
+ proxy: $proxy {
+ $($fname: $fty = $finit),*
+ },
+ stability: $crate::Stability::default(),
+ }
+ }
+ };
+
+ {
+ $interface:path[$descriptor:expr] {
+ native: $native:ident($on_transact:path),
+ proxy: $proxy:ident {
+ $($fname:ident: $fty:ty = $finit:expr),*
+ },
+ stability: $stability:expr,
+ }
+ } => {
+ $crate::declare_binder_interface! {
+ $interface[$descriptor] {
@doc[concat!("A binder [`Remotable`]($crate::Remotable) that holds an [`", stringify!($interface), "`] object.")]
native: $native($on_transact),
@doc[concat!("A binder [`Proxy`]($crate::Proxy) that holds an [`", stringify!($interface), "`] remote interface.")]
proxy: $proxy {
$($fname: $fty = $finit),*
},
+ stability: $stability,
}
}
};
@@ -501,6 +695,8 @@
proxy: $proxy:ident {
$($fname:ident: $fty:ty = $finit:expr),*
},
+
+ stability: $stability:expr,
}
} => {
#[doc = $proxy_doc]
@@ -534,8 +730,9 @@
impl $native {
/// Create a new binder service.
- pub fn new_binder<T: $interface + Sync + Send + 'static>(inner: T) -> impl $interface {
- $crate::Binder::new($native(Box::new(inner)))
+ pub fn new_binder<T: $interface + Sync + Send + 'static>(inner: T) -> $crate::Strong<dyn $interface> {
+ let binder = $crate::Binder::new_with_stability($native(Box::new(inner)), $stability);
+ $crate::Strong::new(Box::new(binder))
}
}
@@ -577,7 +774,7 @@
}
impl $crate::FromIBinder for dyn $interface {
- fn try_from(mut ibinder: $crate::SpIBinder) -> $crate::Result<Box<dyn $interface>> {
+ fn try_from(mut ibinder: $crate::SpIBinder) -> $crate::Result<$crate::Strong<dyn $interface>> {
use $crate::AssociateClass;
let existing_class = ibinder.get_class();
@@ -590,7 +787,7 @@
// associated object as remote, because we can't cast it
// into a Rust service object without a matching class
// pointer.
- return Ok(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?));
+ return Ok($crate::Strong::new(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)));
}
}
@@ -600,10 +797,10 @@
if let Ok(service) = service {
// We were able to associate with our expected class and
// the service is local.
- return Ok(Box::new(service));
+ return Ok($crate::Strong::new(Box::new(service)));
} else {
// Service is remote
- return Ok(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?));
+ return Ok($crate::Strong::new(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)));
}
}
@@ -633,9 +830,9 @@
}
}
- // Convert a &dyn $interface to Box<dyn $interface>
+ /// Convert a &dyn $interface to Strong<dyn $interface>
impl std::borrow::ToOwned for dyn $interface {
- type Owned = Box<dyn $interface>;
+ type Owned = $crate::Strong<dyn $interface>;
fn to_owned(&self) -> Self::Owned {
self.as_binder().into_interface()
.expect(concat!("Error cloning interface ", stringify!($interface)))
diff --git a/libs/binder/rust/src/error.rs b/libs/binder/rust/src/error.rs
index 4492cf7..2598ebc 100644
--- a/libs/binder/rust/src/error.rs
+++ b/libs/binder/rust/src/error.rs
@@ -77,9 +77,7 @@
e if e == ExceptionCode::ILLEGAL_ARGUMENT as i32 => ExceptionCode::ILLEGAL_ARGUMENT,
e if e == ExceptionCode::NULL_POINTER as i32 => ExceptionCode::NULL_POINTER,
e if e == ExceptionCode::ILLEGAL_STATE as i32 => ExceptionCode::ILLEGAL_STATE,
- e if e == ExceptionCode::NETWORK_MAIN_THREAD as i32 => {
- ExceptionCode::NETWORK_MAIN_THREAD
- }
+ e if e == ExceptionCode::NETWORK_MAIN_THREAD as i32 => ExceptionCode::NETWORK_MAIN_THREAD,
e if e == ExceptionCode::UNSUPPORTED_OPERATION as i32 => {
ExceptionCode::UNSUPPORTED_OPERATION
}
@@ -96,6 +94,16 @@
/// Used in AIDL transactions to represent failed transactions.
pub struct Status(*mut 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`
+// in Rust, and the NDK API says we're the owner of our `AStatus` objects so outside code should not
+// be mutating them underneath us.
+unsafe impl Sync for Status {}
+
+// Safety: `Status` always contains an owning pointer to a global, immutable, interned `AStatus`.
+// A thread-local `AStatus` would not be valid.
+unsafe impl Send for Status {}
+
impl Status {
/// Create a status object representing a successful transaction.
pub fn ok() -> Self {
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs
index edfb56a..30928a5 100644
--- a/libs/binder/rust/src/lib.rs
+++ b/libs/binder/rust/src/lib.rs
@@ -107,7 +107,10 @@
pub mod parcel;
pub use crate::binder::{
- FromIBinder, IBinder, Interface, InterfaceClass, Remotable, TransactionCode, TransactionFlags,
+ FromIBinder, IBinder, IBinderInternal, Interface, InterfaceClass, Remotable,
+ Stability, Strong, TransactionCode, TransactionFlags, Weak,
+ FIRST_CALL_TRANSACTION, FLAG_CLEAR_BUF, FLAG_ONEWAY, FLAG_PRIVATE_LOCAL,
+ LAST_CALL_TRANSACTION,
};
pub use error::{status_t, ExceptionCode, Result, Status, StatusCode};
pub use native::add_service;
@@ -122,7 +125,8 @@
pub use super::parcel::ParcelFileDescriptor;
pub use super::{add_service, get_interface};
pub use super::{
- ExceptionCode, Interface, ProcessState, SpIBinder, Status, StatusCode, WpIBinder,
+ DeathRecipient, ExceptionCode, IBinder, Interface, ProcessState, SpIBinder, Status,
+ StatusCode, Strong, ThreadState, Weak, WpIBinder,
};
/// Binder result containing a [`Status`] on error.
diff --git a/libs/binder/rust/src/native.rs b/libs/binder/rust/src/native.rs
index 185645e..3b3fd08 100644
--- a/libs/binder/rust/src/native.rs
+++ b/libs/binder/rust/src/native.rs
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-use crate::binder::{AsNative, Interface, InterfaceClassMethods, Remotable, TransactionCode};
+use crate::binder::{AsNative, Interface, InterfaceClassMethods, Remotable, Stability, TransactionCode};
use crate::error::{status_result, status_t, Result, StatusCode};
use crate::parcel::{Parcel, Serialize};
use crate::proxy::SpIBinder;
@@ -49,11 +49,19 @@
unsafe impl<T: Remotable> Send for Binder<T> {}
impl<T: Remotable> Binder<T> {
- /// Create a new Binder remotable object.
+ /// Create a new Binder remotable object with default stability
///
/// This moves the `rust_object` into an owned [`Box`] and Binder will
/// manage its lifetime.
pub fn new(rust_object: T) -> Binder<T> {
+ Self::new_with_stability(rust_object, Stability::default())
+ }
+
+ /// Create a new Binder remotable object with the given stability
+ ///
+ /// This moves the `rust_object` into an owned [`Box`] and Binder will
+ /// manage its lifetime.
+ pub fn new_with_stability(rust_object: T, stability: Stability) -> Binder<T> {
let class = T::get_class();
let rust_object = Box::into_raw(Box::new(rust_object));
let ibinder = unsafe {
@@ -65,10 +73,12 @@
// ends.
sys::AIBinder_new(class.into(), rust_object as *mut c_void)
};
- Binder {
+ let mut binder = Binder {
ibinder,
rust_object,
- }
+ };
+ binder.mark_stability(stability);
+ binder
}
/// Set the extension of a binder interface. This allows a downstream
@@ -161,6 +171,42 @@
pub fn get_descriptor() -> &'static str {
T::get_descriptor()
}
+
+ /// Mark this binder object with the given stability guarantee
+ fn mark_stability(&mut self, stability: Stability) {
+ match stability {
+ Stability::Local => self.mark_local_stability(),
+ Stability::Vintf => {
+ unsafe {
+ // Safety: Self always contains a valid `AIBinder` pointer, so
+ // we can always call this C API safely.
+ sys::AIBinder_markVintfStability(self.as_native_mut());
+ }
+ }
+ }
+ }
+
+ /// Mark this binder object with local stability, which is vendor if we are
+ /// building for the VNDK and system otherwise.
+ #[cfg(vendor_ndk)]
+ fn mark_local_stability(&mut self) {
+ unsafe {
+ // Safety: Self always contains a valid `AIBinder` pointer, so
+ // we can always call this C API safely.
+ sys::AIBinder_markVendorStability(self.as_native_mut());
+ }
+ }
+
+ /// Mark this binder object with local stability, which is vendor if we are
+ /// building for the VNDK and system otherwise.
+ #[cfg(not(vendor_ndk))]
+ fn mark_local_stability(&mut self) {
+ unsafe {
+ // Safety: Self always contains a valid `AIBinder` pointer, so
+ // we can always call this C API safely.
+ sys::AIBinder_markSystemStability(self.as_native_mut());
+ }
+ }
}
impl<T: Remotable> Interface for Binder<T> {
diff --git a/libs/binder/rust/src/parcel/parcelable.rs b/libs/binder/rust/src/parcel/parcelable.rs
index 8d18fb4..f57788b 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};
+use crate::binder::{AsNative, FromIBinder, Strong};
use crate::error::{status_result, status_t, Result, Status, StatusCode};
use crate::parcel::Parcel;
use crate::proxy::SpIBinder;
@@ -628,26 +628,26 @@
}
}
-impl<T: Serialize + ?Sized> Serialize for Box<T> {
+impl<T: Serialize + FromIBinder + ?Sized> Serialize for Strong<T> {
fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
Serialize::serialize(&**self, parcel)
}
}
-impl<T: SerializeOption + ?Sized> SerializeOption for Box<T> {
+impl<T: SerializeOption + FromIBinder + ?Sized> SerializeOption for Strong<T> {
fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
SerializeOption::serialize_option(this.map(|b| &**b), parcel)
}
}
-impl<T: FromIBinder + ?Sized> Deserialize for Box<T> {
+impl<T: FromIBinder + ?Sized> Deserialize for Strong<T> {
fn deserialize(parcel: &Parcel) -> Result<Self> {
let ibinder: SpIBinder = parcel.read()?;
FromIBinder::try_from(ibinder)
}
}
-impl<T: FromIBinder + ?Sized> DeserializeOption for Box<T> {
+impl<T: FromIBinder + ?Sized> DeserializeOption for Strong<T> {
fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> {
let ibinder: Option<SpIBinder> = parcel.read()?;
ibinder.map(FromIBinder::try_from).transpose()
diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs
index e9e74c0..52036f5 100644
--- a/libs/binder/rust/src/proxy.rs
+++ b/libs/binder/rust/src/proxy.rs
@@ -17,7 +17,8 @@
//! Rust API for interacting with a remote binder service.
use crate::binder::{
- AsNative, FromIBinder, IBinder, Interface, InterfaceClass, TransactionCode, TransactionFlags,
+ AsNative, FromIBinder, IBinder, IBinderInternal, Interface, InterfaceClass, Strong,
+ TransactionCode, TransactionFlags,
};
use crate::error::{status_result, Result, StatusCode};
use crate::parcel::{
@@ -26,6 +27,7 @@
};
use crate::sys;
+use std::cmp::Ordering;
use std::convert::TryInto;
use std::ffi::{c_void, CString};
use std::fmt;
@@ -99,7 +101,7 @@
///
/// If this object does not implement the expected interface, the error
/// `StatusCode::BAD_TYPE` is returned.
- pub fn into_interface<I: FromIBinder + ?Sized>(self) -> Result<Box<I>> {
+ pub fn into_interface<I: FromIBinder + Interface + ?Sized>(self) -> Result<Strong<I>> {
FromIBinder::try_from(self)
}
@@ -148,6 +150,36 @@
}
}
+impl Ord for SpIBinder {
+ fn cmp(&self, other: &Self) -> Ordering {
+ let less_than = unsafe {
+ // Safety: SpIBinder always holds a valid `AIBinder` pointer, so
+ // this pointer is always safe to pass to `AIBinder_lt` (null is
+ // also safe to pass to this function, but we should never do that).
+ sys::AIBinder_lt(self.0, other.0)
+ };
+ let greater_than = unsafe {
+ // Safety: SpIBinder always holds a valid `AIBinder` pointer, so
+ // this pointer is always safe to pass to `AIBinder_lt` (null is
+ // also safe to pass to this function, but we should never do that).
+ sys::AIBinder_lt(other.0, self.0)
+ };
+ if !less_than && !greater_than {
+ Ordering::Equal
+ } else if less_than {
+ Ordering::Less
+ } else {
+ Ordering::Greater
+ }
+ }
+}
+
+impl PartialOrd for SpIBinder {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
impl PartialEq for SpIBinder {
fn eq(&self, other: &Self) -> bool {
ptr::eq(self.0, other.0)
@@ -180,7 +212,7 @@
}
}
-impl<T: AsNative<sys::AIBinder>> IBinder for T {
+impl<T: AsNative<sys::AIBinder>> IBinderInternal for T {
/// Perform a binder transaction
fn transact<F: FnOnce(&mut Parcel) -> Result<()>>(
&self,
@@ -269,9 +301,7 @@
}
fn set_requesting_sid(&mut self, enable: bool) {
- unsafe {
- sys::AIBinder_setRequestingSid(self.as_native_mut(), enable)
- };
+ unsafe { sys::AIBinder_setRequestingSid(self.as_native_mut(), enable) };
}
fn dump<F: AsRawFd>(&mut self, fp: &F, args: &[&str]) -> Result<()> {
@@ -320,13 +350,15 @@
status_result(status)?;
Ok(ibinder)
}
+}
+impl<T: AsNative<sys::AIBinder>> IBinder for T {
fn link_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()> {
status_result(unsafe {
// Safety: `SpIBinder` guarantees that `self` always contains a
// valid pointer to an `AIBinder`. `recipient` can always be
// converted into a valid pointer to an
- // `AIBinder_DeatRecipient`. Any value is safe to pass as the
+ // `AIBinder_DeathRecipient`. Any value is safe to pass as the
// cookie, although we depend on this value being set by
// `get_cookie` when the death recipient callback is called.
sys::AIBinder_linkToDeath(
@@ -342,7 +374,7 @@
// Safety: `SpIBinder` guarantees that `self` always contains a
// valid pointer to an `AIBinder`. `recipient` can always be
// converted into a valid pointer to an
- // `AIBinder_DeatRecipient`. Any value is safe to pass as the
+ // `AIBinder_DeathRecipient`. Any value is safe to pass as the
// cookie, although we depend on this value being set by
// `get_cookie` when the death recipient callback is called.
sys::AIBinder_unlinkToDeath(
@@ -430,6 +462,65 @@
}
}
+impl Clone for WpIBinder {
+ fn clone(&self) -> Self {
+ let ptr = unsafe {
+ // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer,
+ // so this pointer is always safe to pass to `AIBinder_Weak_clone`
+ // (although null is also a safe value to pass to this API).
+ //
+ // We get ownership of the returned pointer, so can construct a new
+ // WpIBinder object from it.
+ sys::AIBinder_Weak_clone(self.0)
+ };
+ assert!(
+ !ptr.is_null(),
+ "Unexpected null pointer from AIBinder_Weak_clone"
+ );
+ Self(ptr)
+ }
+}
+
+impl Ord for WpIBinder {
+ fn cmp(&self, other: &Self) -> Ordering {
+ let less_than = unsafe {
+ // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer,
+ // so this pointer is always safe to pass to `AIBinder_Weak_lt`
+ // (null is also safe to pass to this function, but we should never
+ // do that).
+ sys::AIBinder_Weak_lt(self.0, other.0)
+ };
+ let greater_than = unsafe {
+ // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer,
+ // so this pointer is always safe to pass to `AIBinder_Weak_lt`
+ // (null is also safe to pass to this function, but we should never
+ // do that).
+ sys::AIBinder_Weak_lt(other.0, self.0)
+ };
+ if !less_than && !greater_than {
+ Ordering::Equal
+ } else if less_than {
+ Ordering::Less
+ } else {
+ Ordering::Greater
+ }
+ }
+}
+
+impl PartialOrd for WpIBinder {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl PartialEq for WpIBinder {
+ fn eq(&self, other: &Self) -> bool {
+ self.cmp(other) == Ordering::Equal
+ }
+}
+
+impl Eq for WpIBinder {}
+
impl Drop for WpIBinder {
fn drop(&mut self) {
unsafe {
@@ -564,7 +655,7 @@
/// Retrieve an existing service for a particular interface, blocking for a few
/// seconds if it doesn't yet exist.
-pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Box<T>> {
+pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
let service = get_service(name);
match service {
Some(service) => FromIBinder::try_from(service),
diff --git a/libs/binder/rust/sys/BinderBindings.hpp b/libs/binder/rust/sys/BinderBindings.hpp
index ef142b5..65fa2ca 100644
--- a/libs/binder/rust/sys/BinderBindings.hpp
+++ b/libs/binder/rust/sys/BinderBindings.hpp
@@ -21,6 +21,7 @@
#include <android/binder_parcel_platform.h>
#include <android/binder_process.h>
#include <android/binder_shell.h>
+#include <android/binder_stability.h>
#include <android/binder_status.h>
namespace android {
@@ -80,6 +81,7 @@
enum {
FLAG_ONEWAY = FLAG_ONEWAY,
FLAG_CLEAR_BUF = FLAG_CLEAR_BUF,
+ FLAG_PRIVATE_LOCAL = FLAG_PRIVATE_LOCAL,
};
} // namespace consts
diff --git a/libs/binder/rust/tests/Android.bp b/libs/binder/rust/tests/Android.bp
index 8810b5d..0bf76c6 100644
--- a/libs/binder/rust/tests/Android.bp
+++ b/libs/binder/rust/tests/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
rust_test {
name: "rustBinderTest",
srcs: ["integration.rs"],
diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs
index bb8c492..60e3502 100644
--- a/libs/binder/rust/tests/integration.rs
+++ b/libs/binder/rust/tests/integration.rs
@@ -18,7 +18,10 @@
use binder::declare_binder_interface;
use binder::parcel::Parcel;
-use binder::{Binder, IBinder, Interface, SpIBinder, StatusCode, ThreadState, TransactionCode};
+use binder::{
+ Binder, IBinderInternal, Interface, StatusCode, ThreadState, TransactionCode,
+ FIRST_CALL_TRANSACTION,
+};
use std::convert::{TryFrom, TryInto};
/// Name of service runner.
@@ -83,7 +86,7 @@
#[repr(u32)]
enum TestTransactionCode {
- Test = SpIBinder::FIRST_CALL_TRANSACTION,
+ Test = FIRST_CALL_TRANSACTION,
GetSelinuxContext,
}
@@ -196,7 +199,6 @@
impl ITestSameDescriptor for Binder<BnTestSameDescriptor> {}
-
#[cfg(test)]
mod tests {
use selinux_bindgen as selinux_sys;
@@ -209,9 +211,12 @@
use std::thread;
use std::time::Duration;
- use binder::{Binder, DeathRecipient, FromIBinder, IBinder, Interface, SpIBinder, StatusCode};
+ use binder::{
+ Binder, DeathRecipient, FromIBinder, IBinder, IBinderInternal, Interface, SpIBinder,
+ StatusCode, Strong,
+ };
- use super::{BnTest, ITest, ITestSameDescriptor, RUST_SERVICE_BINARY, TestService};
+ use super::{BnTest, ITest, ITestSameDescriptor, TestService, RUST_SERVICE_BINARY};
pub struct ScopedServiceProcess(Child);
@@ -271,7 +276,7 @@
fn trivial_client() {
let service_name = "trivial_client_test";
let _process = ScopedServiceProcess::new(service_name);
- let test_client: Box<dyn ITest> =
+ let test_client: Strong<dyn ITest> =
binder::get_interface(service_name).expect("Did not get manager binder service");
assert_eq!(test_client.test().unwrap(), "trivial_client_test");
}
@@ -280,7 +285,7 @@
fn get_selinux_context() {
let service_name = "get_selinux_context";
let _process = ScopedServiceProcess::new(service_name);
- let test_client: Box<dyn ITest> =
+ let test_client: Strong<dyn ITest> =
binder::get_interface(service_name).expect("Did not get manager binder service");
let expected_context = unsafe {
let mut out_ptr = ptr::null_mut();
@@ -290,7 +295,9 @@
};
assert_eq!(
test_client.get_selinux_context().unwrap(),
- expected_context.to_str().expect("context was invalid UTF-8"),
+ expected_context
+ .to_str()
+ .expect("context was invalid UTF-8"),
);
}
@@ -453,7 +460,7 @@
let extension = maybe_extension.expect("Remote binder did not have an extension");
- let extension: Box<dyn ITest> = FromIBinder::try_from(extension)
+ let extension: Strong<dyn ITest> = FromIBinder::try_from(extension)
.expect("Extension could not be converted to the expected interface");
assert_eq!(extension.test().unwrap(), extension_name);
@@ -479,20 +486,85 @@
// This should succeed although we will have to treat the service as
// remote.
- let _interface: Box<dyn ITestSameDescriptor> = FromIBinder::try_from(service.as_binder())
- .expect("Could not re-interpret service as the ITestSameDescriptor interface");
+ let _interface: Strong<dyn ITestSameDescriptor> =
+ FromIBinder::try_from(service.as_binder())
+ .expect("Could not re-interpret service as the ITestSameDescriptor interface");
}
/// Test that we can round-trip a rust service through a generic IBinder
#[test]
fn reassociate_rust_binder() {
let service_name = "testing_service";
- let service_ibinder = BnTest::new_binder(TestService { s: service_name.to_string() })
- .as_binder();
+ let service_ibinder = BnTest::new_binder(TestService {
+ s: service_name.to_string(),
+ })
+ .as_binder();
- let service: Box<dyn ITest> = service_ibinder.into_interface()
+ let service: Strong<dyn ITest> = service_ibinder
+ .into_interface()
.expect("Could not reassociate the generic ibinder");
assert_eq!(service.test().unwrap(), service_name);
}
+
+ #[test]
+ fn weak_binder_upgrade() {
+ let service_name = "testing_service";
+ let service = BnTest::new_binder(TestService {
+ s: service_name.to_string(),
+ });
+
+ let weak = Strong::downgrade(&service);
+
+ let upgraded = weak.upgrade().expect("Could not upgrade weak binder");
+
+ assert_eq!(service, upgraded);
+ }
+
+ #[test]
+ fn weak_binder_upgrade_dead() {
+ let service_name = "testing_service";
+ let weak = {
+ let service = BnTest::new_binder(TestService {
+ s: service_name.to_string(),
+ });
+
+ Strong::downgrade(&service)
+ };
+
+ assert_eq!(weak.upgrade(), Err(StatusCode::DEAD_OBJECT));
+ }
+
+ #[test]
+ fn weak_binder_clone() {
+ let service_name = "testing_service";
+ let service = BnTest::new_binder(TestService {
+ s: service_name.to_string(),
+ });
+
+ let weak = Strong::downgrade(&service);
+ let cloned = weak.clone();
+ assert_eq!(weak, cloned);
+
+ let upgraded = weak.upgrade().expect("Could not upgrade weak binder");
+ let clone_upgraded = cloned.upgrade().expect("Could not upgrade weak binder");
+
+ assert_eq!(service, upgraded);
+ assert_eq!(service, clone_upgraded);
+ }
+
+ #[test]
+ #[allow(clippy::eq_op)]
+ fn binder_ord() {
+ let service1 = BnTest::new_binder(TestService {
+ s: "testing_service1".to_string(),
+ });
+ let service2 = BnTest::new_binder(TestService {
+ s: "testing_service2".to_string(),
+ });
+
+ assert!(!(service1 < service1));
+ assert!(!(service1 > service1));
+ assert_eq!(service1 < service2, !(service2 < service1));
+ }
}
diff --git a/libs/binder/rust/tests/ndk_rust_interop.rs b/libs/binder/rust/tests/ndk_rust_interop.rs
index 70a6dc0..ce75ab7 100644
--- a/libs/binder/rust/tests/ndk_rust_interop.rs
+++ b/libs/binder/rust/tests/ndk_rust_interop.rs
@@ -37,7 +37,7 @@
// The Rust class descriptor pointer will not match the NDK one, but the
// descriptor strings match so this needs to still associate.
- let service: Box<dyn IBinderRustNdkInteropTest> = match binder::get_interface(service_name) {
+ let service: binder::Strong<dyn IBinderRustNdkInteropTest> = match binder::get_interface(service_name) {
Err(e) => {
eprintln!("Could not find Ndk service {}: {:?}", service_name, e);
return StatusCode::NAME_NOT_FOUND as c_int;
@@ -53,7 +53,7 @@
}
// Try using the binder service through the wrong interface type
- let wrong_service: Result<Box<dyn IBinderRustNdkInteropTestOther>, StatusCode> =
+ let wrong_service: Result<binder::Strong<dyn IBinderRustNdkInteropTestOther>, StatusCode> =
binder::get_interface(service_name);
match wrong_service {
Err(e) if e == StatusCode::BAD_TYPE => {}
diff --git a/libs/binder/rust/tests/serialization.rs b/libs/binder/rust/tests/serialization.rs
index 2bf3d03..f1b068e 100644
--- a/libs/binder/rust/tests/serialization.rs
+++ b/libs/binder/rust/tests/serialization.rs
@@ -40,6 +40,41 @@
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
}
+macro_rules! assert_eq {
+ ($left:expr, $right:expr $(,)?) => {
+ match (&$left, &$right) {
+ (left, right) => {
+ if *left != *right {
+ eprintln!(
+ "assertion failed: `{:?}` == `{:?}`, {}:{}:{}",
+ &*left,
+ &*right,
+ file!(),
+ line!(),
+ column!()
+ );
+ return Err(StatusCode::FAILED_TRANSACTION);
+ }
+ }
+ }
+ };
+}
+
+macro_rules! assert {
+ ($expr:expr) => {
+ if !$expr {
+ eprintln!(
+ "assertion failed: `{:?}`, {}:{}:{}",
+ $expr,
+ file!(),
+ line!(),
+ column!()
+ );
+ return Err(StatusCode::FAILED_TRANSACTION);
+ }
+ };
+}
+
static SERVICE_ONCE: Once = Once::new();
static mut SERVICE: Option<SpIBinder> = None;
@@ -282,7 +317,7 @@
))?;
}
bindings::Transaction_TEST_FAIL => {
- return Err(StatusCode::FAILED_TRANSACTION)
+ assert!(false);
}
_ => return Err(StatusCode::UNKNOWN_TRANSACTION),
}
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 988f7f3..afc4b1b 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "binder_test_defaults",
cflags: [
@@ -95,6 +104,53 @@
require_root: true,
}
+aidl_interface {
+ name: "binderRpcTestIface",
+ host_supported: true,
+ unstable: true,
+ srcs: [
+ "IBinderRpcSession.aidl",
+ "IBinderRpcTest.aidl",
+ ],
+ backend: {
+ java: {
+ enabled: false,
+ },
+ },
+}
+
+cc_test {
+ name: "binderRpcTest",
+ host_supported: true,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+ defaults: [
+ "binder_test_defaults",
+ "libbinder_ndk_host_user",
+ ],
+
+ srcs: [
+ "binderRpcTest.cpp",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libbinder_ndk",
+ "libbase",
+ "libutils",
+ "libcutils",
+ "liblog",
+ ],
+ static_libs: [
+ "binderRpcTestIface-cpp",
+ "binderRpcTestIface-ndk_platform",
+ ],
+ test_suites: ["general-tests"],
+ require_root: true,
+}
+
cc_test {
name: "binderThroughputTest",
defaults: ["binder_test_defaults"],
@@ -181,6 +237,11 @@
srcs: [
"IBinderStabilityTest.aidl",
],
+ backend: {
+ java: {
+ enabled: false,
+ },
+ },
}
cc_test {
@@ -220,3 +281,15 @@
test_suites: ["device-tests"],
require_root: true,
}
+
+cc_benchmark {
+ name: "binderParcelBenchmark",
+ defaults: ["binder_test_defaults"],
+ srcs: ["binderParcelBenchmark.cpp"],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "liblog",
+ "libutils",
+ ],
+}
diff --git a/libs/binder/tests/IBinderRpcSession.aidl b/libs/binder/tests/IBinderRpcSession.aidl
new file mode 100644
index 0000000..cf5f318
--- /dev/null
+++ b/libs/binder/tests/IBinderRpcSession.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+interface IBinderRpcSession {
+ @utf8InCpp String getName();
+}
diff --git a/libs/binder/tests/IBinderRpcTest.aidl b/libs/binder/tests/IBinderRpcTest.aidl
new file mode 100644
index 0000000..2bdb264
--- /dev/null
+++ b/libs/binder/tests/IBinderRpcTest.aidl
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+interface IBinderRpcTest {
+ oneway void sendString(@utf8InCpp String str);
+ @utf8InCpp String doubleString(@utf8InCpp String str);
+
+ // number of known RPC binders to process, RpcState::countBinders
+ int countBinders();
+
+ // Caller sends server, callee pings caller's server and returns error code.
+ int pingMe(IBinder binder);
+ @nullable IBinder repeatBinder(@nullable IBinder binder);
+
+ void holdBinder(@nullable IBinder binder);
+ @nullable IBinder getHeldBinder();
+
+ // Idea is client creates its own instance of IBinderRpcTest and calls this,
+ // and the server calls 'binder' with (calls - 1) passing itself as 'binder',
+ // going back and forth until calls = 0
+ void nestMe(IBinderRpcTest binder, int calls);
+
+ // should always return the same binder
+ IBinder alwaysGiveMeTheSameBinder();
+
+ // Idea is that the server will not hold onto the session, the remote connection
+ // object must. This is to test lifetimes of binder objects, and consequently, also
+ // identity (since by assigning sessions names, we can make sure a section always
+ // references the session it was originally opened with).
+ IBinderRpcSession openSession(@utf8InCpp String name);
+
+ // Decremented in ~IBinderRpcSession
+ int getNumOpenSessions();
+
+ // primitives to test threading behavior
+ void lock();
+ oneway void unlockInMsAsync(int ms);
+ void lockUnlock(); // locks and unlocks a mutex
+
+ // take up binder thread for some time
+ void sleepMs(int ms);
+ oneway void sleepMsAsync(int ms);
+
+ void die(boolean cleanup);
+}
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index a5261e5..e2193fa 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -21,6 +21,7 @@
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
+#include <thread>
#include <gtest/gtest.h>
@@ -28,6 +29,7 @@
#include <binder/IBinder.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
+#include <binder/ParcelRef.h>
#include <private/binder/binder_module.h>
#include <linux/sched.h>
@@ -916,6 +918,36 @@
}
}
+TEST_F(BinderLibTest, ParcelAllocatedOnAnotherThread) {
+ sp<IBinder> server = addServer();
+ ASSERT_TRUE(server != nullptr);
+
+ Parcel data;
+ sp<ParcelRef> reply = ParcelRef::create();
+
+ // when we have a Parcel which is deleted on another thread, if it gets
+ // deleted, it will tell the kernel this, and it will drop strong references
+ // to binder, so that we can't BR_ACQUIRE would fail
+ IPCThreadState::self()->createTransactionReference(reply.get());
+ ASSERT_EQ(NO_ERROR, server->transact(BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION,
+ data,
+ reply.get()));
+
+ // we have sp to binder, but it is not actually acquired by kernel, the
+ // transaction is sitting on an out buffer
+ sp<IBinder> binder = reply->readStrongBinder();
+
+ std::thread([&] {
+ // without the transaction reference, this would cause the Parcel to be
+ // deallocated before the first thread flushes BR_ACQUIRE
+ reply = nullptr;
+ IPCThreadState::self()->flushCommands();
+ }).join();
+
+ ASSERT_NE(nullptr, binder);
+ ASSERT_EQ(NO_ERROR, binder->pingBinder());
+}
+
TEST_F(BinderLibTest, CheckNoHeaderMappedInUser) {
status_t ret;
Parcel data, reply;
diff --git a/libs/binder/tests/binderParcelBenchmark.cpp b/libs/binder/tests/binderParcelBenchmark.cpp
new file mode 100644
index 0000000..26c50eb
--- /dev/null
+++ b/libs/binder/tests/binderParcelBenchmark.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <binder/Parcel.h>
+#include <benchmark/benchmark.h>
+
+// Usage: atest binderParcelBenchmark
+
+// For static assert(false) we need a template version to avoid early failure.
+// See: https://stackoverflow.com/questions/51523965/template-dependent-false
+template <typename T>
+constexpr bool dependent_false_v = false;
+
+template <template <typename ...> class V, typename T, typename... Args>
+void writeVector(android::Parcel &p, const V<T, Args...> &v) {
+ if constexpr (std::is_same_v<T, bool>) {
+ p.writeBoolVector(v);
+ } else if constexpr (std::is_same_v<T, uint8_t>) {
+ p.writeByteVector(v);
+ } else if constexpr (std::is_same_v<T, char16_t>) {
+ p.writeCharVector(v);
+ } else if constexpr (std::is_same_v<T, int32_t>) {
+ p.writeInt32Vector(v);
+ } else if constexpr (std::is_same_v<T, int64_t>) {
+ p.writeInt64Vector(v);
+ } else {
+ static_assert(dependent_false_v<V<T>>);
+ }
+}
+
+template <template <typename ...> class V, typename T, typename... Args>
+void readVector(android::Parcel &p, V<T, Args...> *v) {
+ if constexpr (std::is_same_v<T, bool>) {
+ p.readBoolVector(v);
+ } else if constexpr (std::is_same_v<T, uint8_t>) {
+ p.readByteVector(v);
+ } else if constexpr (std::is_same_v<T, char16_t>) {
+ p.readCharVector(v);
+ } else if constexpr (std::is_same_v<T, int32_t>) {
+ p.readInt32Vector(v);
+ } else if constexpr (std::is_same_v<T, int64_t>) {
+ p.readInt64Vector(v);
+ } else {
+ static_assert(dependent_false_v<V<T>>);
+ }
+}
+
+// Construct a series of args { 1 << 0, 1 << 1, ..., 1 << 10 }
+static void VectorArgs(benchmark::internal::Benchmark* b) {
+ for (int i = 0; i < 10; ++i) {
+ b->Args({1 << i});
+ }
+}
+
+template <typename T>
+static void BM_ParcelVector(benchmark::State& state) {
+ const size_t elements = state.range(0);
+
+ std::vector<T> v1(elements);
+ std::vector<T> v2(elements);
+ android::Parcel p;
+ while (state.KeepRunning()) {
+ p.setDataPosition(0);
+ writeVector(p, v1);
+
+ p.setDataPosition(0);
+ readVector(p, &v2);
+
+ benchmark::DoNotOptimize(v2[0]);
+ benchmark::ClobberMemory();
+ }
+ state.SetComplexityN(elements);
+}
+
+/*
+ Parcel vector write than read.
+ The read and write vectors are fixed, no resizing required.
+
+ Results on Crosshatch Pixel 3XL
+
+ #BM_BoolVector/1 44 ns 44 ns 15630626
+ #BM_BoolVector/2 54 ns 54 ns 12900340
+ #BM_BoolVector/4 73 ns 72 ns 9749841
+ #BM_BoolVector/8 107 ns 107 ns 6503326
+ #BM_BoolVector/16 186 ns 185 ns 3773627
+ #BM_BoolVector/32 337 ns 336 ns 2083877
+ #BM_BoolVector/64 607 ns 605 ns 1154113
+ #BM_BoolVector/128 1155 ns 1151 ns 608128
+ #BM_BoolVector/256 2259 ns 2253 ns 310973
+ #BM_BoolVector/512 4469 ns 4455 ns 157277
+ #BM_ByteVector/1 41 ns 41 ns 16837425
+ #BM_ByteVector/2 41 ns 41 ns 16820726
+ #BM_ByteVector/4 38 ns 38 ns 18217813
+ #BM_ByteVector/8 38 ns 38 ns 18290298
+ #BM_ByteVector/16 38 ns 38 ns 18117817
+ #BM_ByteVector/32 38 ns 38 ns 18172385
+ #BM_ByteVector/64 41 ns 41 ns 16950055
+ #BM_ByteVector/128 53 ns 53 ns 13170749
+ #BM_ByteVector/256 69 ns 69 ns 10113626
+ #BM_ByteVector/512 106 ns 106 ns 6561936
+ #BM_CharVector/1 38 ns 38 ns 18074831
+ #BM_CharVector/2 40 ns 40 ns 17206266
+ #BM_CharVector/4 50 ns 50 ns 13785944
+ #BM_CharVector/8 67 ns 67 ns 10223316
+ #BM_CharVector/16 96 ns 96 ns 7297285
+ #BM_CharVector/32 156 ns 155 ns 4484845
+ #BM_CharVector/64 277 ns 276 ns 2536003
+ #BM_CharVector/128 520 ns 518 ns 1347070
+ #BM_CharVector/256 1006 ns 1003 ns 695952
+ #BM_CharVector/512 1976 ns 1970 ns 354673
+ #BM_Int32Vector/1 41 ns 41 ns 16951262
+ #BM_Int32Vector/2 41 ns 41 ns 16916883
+ #BM_Int32Vector/4 41 ns 41 ns 16761373
+ #BM_Int32Vector/8 42 ns 42 ns 16553179
+ #BM_Int32Vector/16 43 ns 43 ns 16200362
+ #BM_Int32Vector/32 55 ns 54 ns 12724454
+ #BM_Int32Vector/64 70 ns 69 ns 10049223
+ #BM_Int32Vector/128 107 ns 107 ns 6525796
+ #BM_Int32Vector/256 179 ns 178 ns 3922563
+ #BM_Int32Vector/512 324 ns 323 ns 2160653
+ #BM_Int64Vector/1 41 ns 41 ns 16909470
+ #BM_Int64Vector/2 41 ns 41 ns 16740788
+ #BM_Int64Vector/4 42 ns 42 ns 16564197
+ #BM_Int64Vector/8 43 ns 42 ns 16284082
+ #BM_Int64Vector/16 54 ns 54 ns 12839474
+ #BM_Int64Vector/32 69 ns 69 ns 10011010
+ #BM_Int64Vector/64 107 ns 106 ns 6557956
+ #BM_Int64Vector/128 177 ns 177 ns 3925618
+ #BM_Int64Vector/256 324 ns 323 ns 2163321
+ #BM_Int64Vector/512 613 ns 611 ns 1140418
+*/
+
+static void BM_BoolVector(benchmark::State& state) {
+ BM_ParcelVector<bool>(state);
+}
+
+static void BM_ByteVector(benchmark::State& state) {
+ BM_ParcelVector<uint8_t>(state);
+}
+
+static void BM_CharVector(benchmark::State& state) {
+ BM_ParcelVector<char16_t>(state);
+}
+
+static void BM_Int32Vector(benchmark::State& state) {
+ BM_ParcelVector<int32_t>(state);
+}
+
+static void BM_Int64Vector(benchmark::State& state) {
+ BM_ParcelVector<int64_t>(state);
+}
+
+BENCHMARK(BM_BoolVector)->Apply(VectorArgs);
+BENCHMARK(BM_ByteVector)->Apply(VectorArgs);
+BENCHMARK(BM_CharVector)->Apply(VectorArgs);
+BENCHMARK(BM_Int32Vector)->Apply(VectorArgs);
+BENCHMARK(BM_Int64Vector)->Apply(VectorArgs);
+
+BENCHMARK_MAIN();
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
new file mode 100644
index 0000000..27f18df
--- /dev/null
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -0,0 +1,857 @@
+/*
+ * 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.
+ */
+
+#include <BnBinderRpcSession.h>
+#include <BnBinderRpcTest.h>
+#include <aidl/IBinderRpcTest.h>
+#include <android-base/logging.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_libbinder.h>
+#include <binder/Binder.h>
+#include <binder/BpBinder.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <binder/RpcConnection.h>
+#include <binder/RpcServer.h>
+#include <gtest/gtest.h>
+
+#include <chrono>
+#include <cstdlib>
+#include <iostream>
+#include <thread>
+
+#ifdef __BIONIC__
+#include <linux/vm_sockets.h>
+#endif //__BIONIC__
+
+#include <sys/prctl.h>
+#include <unistd.h>
+
+#include "../RpcState.h" // for debugging
+
+namespace android {
+
+using android::binder::Status;
+
+#define EXPECT_OK(status) \
+ do { \
+ Status stat = (status); \
+ EXPECT_TRUE(stat.isOk()) << stat; \
+ } while (false)
+
+class MyBinderRpcSession : public BnBinderRpcSession {
+public:
+ static std::atomic<int32_t> gNum;
+
+ MyBinderRpcSession(const std::string& name) : mName(name) { gNum++; }
+ Status getName(std::string* name) override {
+ *name = mName;
+ return Status::ok();
+ }
+ ~MyBinderRpcSession() { gNum--; }
+
+private:
+ std::string mName;
+};
+std::atomic<int32_t> MyBinderRpcSession::gNum;
+
+class MyBinderRpcTest : public BnBinderRpcTest {
+public:
+ sp<RpcConnection> connection;
+
+ Status sendString(const std::string& str) override {
+ std::cout << "Child received string: " << str << std::endl;
+ return Status::ok();
+ }
+ Status doubleString(const std::string& str, std::string* strstr) override {
+ std::cout << "Child received string to double: " << str << std::endl;
+ *strstr = str + str;
+ return Status::ok();
+ }
+ Status countBinders(int32_t* out) override {
+ if (connection == nullptr) {
+ return Status::fromExceptionCode(Status::EX_NULL_POINTER);
+ }
+ *out = connection->state()->countBinders();
+ if (*out != 1) {
+ connection->state()->dump();
+ }
+ return Status::ok();
+ }
+ Status pingMe(const sp<IBinder>& binder, int32_t* out) override {
+ if (binder == nullptr) {
+ std::cout << "Received null binder!" << std::endl;
+ return Status::fromExceptionCode(Status::EX_NULL_POINTER);
+ }
+ *out = binder->pingBinder();
+ return Status::ok();
+ }
+ Status repeatBinder(const sp<IBinder>& binder, sp<IBinder>* out) override {
+ *out = binder;
+ return Status::ok();
+ }
+ static sp<IBinder> mHeldBinder;
+ Status holdBinder(const sp<IBinder>& binder) override {
+ mHeldBinder = binder;
+ return Status::ok();
+ }
+ Status getHeldBinder(sp<IBinder>* held) override {
+ *held = mHeldBinder;
+ return Status::ok();
+ }
+ Status nestMe(const sp<IBinderRpcTest>& binder, int count) override {
+ if (count <= 0) return Status::ok();
+ return binder->nestMe(this, count - 1);
+ }
+ Status alwaysGiveMeTheSameBinder(sp<IBinder>* out) override {
+ static sp<IBinder> binder = new BBinder;
+ *out = binder;
+ return Status::ok();
+ }
+ Status openSession(const std::string& name, sp<IBinderRpcSession>* out) override {
+ *out = new MyBinderRpcSession(name);
+ return Status::ok();
+ }
+ Status getNumOpenSessions(int32_t* out) override {
+ *out = MyBinderRpcSession::gNum;
+ return Status::ok();
+ }
+
+ std::mutex blockMutex;
+ Status lock() override {
+ blockMutex.lock();
+ return Status::ok();
+ }
+ Status unlockInMsAsync(int32_t ms) override {
+ usleep(ms * 1000);
+ blockMutex.unlock();
+ return Status::ok();
+ }
+ Status lockUnlock() override {
+ std::lock_guard<std::mutex> _l(blockMutex);
+ return Status::ok();
+ }
+
+ Status sleepMs(int32_t ms) override {
+ usleep(ms * 1000);
+ return Status::ok();
+ }
+
+ Status sleepMsAsync(int32_t ms) override {
+ // In-process binder calls are asynchronous, but the call to this method
+ // is synchronous wrt its client. This in/out-process threading model
+ // diffentiation is a classic binder leaky abstraction (for better or
+ // worse) and is preserved here the way binder sockets plugs itself
+ // into BpBinder, as nothing is changed at the higher levels
+ // (IInterface) which result in this behavior.
+ return sleepMs(ms);
+ }
+
+ Status die(bool cleanup) override {
+ if (cleanup) {
+ exit(1);
+ } else {
+ _exit(1);
+ }
+ }
+};
+sp<IBinder> MyBinderRpcTest::mHeldBinder;
+
+class Process {
+public:
+ Process(const std::function<void()>& f) {
+ if (0 == (mPid = fork())) {
+ // racey: assume parent doesn't crash before this is set
+ prctl(PR_SET_PDEATHSIG, SIGHUP);
+
+ f();
+ }
+ }
+ ~Process() {
+ if (mPid != 0) {
+ kill(mPid, SIGKILL);
+ }
+ }
+
+private:
+ pid_t mPid = 0;
+};
+
+static std::string allocateSocketAddress() {
+ static size_t id = 0;
+ static bool gUseTmp = access("/tmp/", F_OK) != -1;
+
+ if (gUseTmp) {
+ return "/tmp/binderRpcTest_" + std::to_string(id++);
+ } else {
+ return "/dev/binderRpcTest_" + std::to_string(id++);
+ }
+};
+
+struct ProcessConnection {
+ // reference to process hosting a socket server
+ Process host;
+
+ // client connection object associated with other process
+ sp<RpcConnection> connection;
+
+ // pre-fetched root object
+ sp<IBinder> rootBinder;
+
+ // whether connection should be invalidated by end of run
+ bool expectInvalid = false;
+
+ ~ProcessConnection() {
+ rootBinder = nullptr;
+ EXPECT_NE(nullptr, connection);
+ EXPECT_NE(nullptr, connection->state());
+ EXPECT_EQ(0, connection->state()->countBinders()) << (connection->state()->dump(), "dump:");
+
+ wp<RpcConnection> weakConnection = connection;
+ connection = nullptr;
+ EXPECT_EQ(nullptr, weakConnection.promote()) << "Leaked connection";
+ }
+};
+
+// Process connection where the process hosts IBinderRpcTest, the server used
+// for most testing here
+struct BinderRpcTestProcessConnection {
+ ProcessConnection proc;
+
+ // pre-fetched root object
+ sp<IBinder> rootBinder;
+
+ // pre-casted root object
+ sp<IBinderRpcTest> rootIface;
+
+ ~BinderRpcTestProcessConnection() {
+ if (!proc.expectInvalid) {
+ int32_t remoteBinders = 0;
+ EXPECT_OK(rootIface->countBinders(&remoteBinders));
+ // should only be the root binder object, iface
+ EXPECT_EQ(remoteBinders, 1);
+ }
+
+ rootIface = nullptr;
+ rootBinder = nullptr;
+ }
+};
+
+enum class SocketType {
+ UNIX,
+#ifdef __BIONIC__
+ VSOCK,
+#endif // __BIONIC__
+};
+static inline std::string PrintSocketType(const testing::TestParamInfo<SocketType>& info) {
+ switch (info.param) {
+ case SocketType::UNIX:
+ return "unix_domain_socket";
+#ifdef __BIONIC__
+ case SocketType::VSOCK:
+ return "vm_socket";
+#endif // __BIONIC__
+ default:
+ LOG_ALWAYS_FATAL("Unknown socket type");
+ return "";
+ }
+}
+class BinderRpc : public ::testing::TestWithParam<SocketType> {
+public:
+ // This creates a new process serving an interface on a certain number of
+ // threads.
+ ProcessConnection createRpcTestSocketServerProcess(
+ size_t numThreads,
+ const std::function<void(const sp<RpcServer>&, const sp<RpcConnection>&)>& configure) {
+ CHECK_GT(numThreads, 0);
+
+ SocketType socketType = GetParam();
+
+ std::string addr = allocateSocketAddress();
+ unlink(addr.c_str());
+ static unsigned int port = 3456;
+ port++;
+
+ auto ret = ProcessConnection{
+ .host = Process([&] {
+ sp<RpcServer> server = RpcServer::make();
+
+ server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
+
+ // server supporting one client on one socket
+ sp<RpcConnection> connection = server->addClientConnection();
+
+ switch (socketType) {
+ case SocketType::UNIX:
+ CHECK(connection->setupUnixDomainServer(addr.c_str())) << addr;
+ break;
+#ifdef __BIONIC__
+ case SocketType::VSOCK:
+ CHECK(connection->setupVsockServer(port));
+ break;
+#endif // __BIONIC__
+ default:
+ LOG_ALWAYS_FATAL("Unknown socket type");
+ }
+
+ configure(server, connection);
+
+ // accept 'numThreads' connections
+ std::vector<std::thread> pool;
+ for (size_t i = 0; i + 1 < numThreads; i++) {
+ pool.push_back(std::thread([=] { connection->join(); }));
+ }
+ connection->join();
+ for (auto& t : pool) t.join();
+ }),
+ .connection = RpcConnection::make(),
+ };
+
+ // create remainder of connections
+ for (size_t i = 0; i < numThreads; i++) {
+ for (size_t tries = 0; tries < 5; tries++) {
+ usleep(10000);
+ switch (socketType) {
+ case SocketType::UNIX:
+ if (ret.connection->addUnixDomainClient(addr.c_str())) goto success;
+ break;
+#ifdef __BIONIC__
+ case SocketType::VSOCK:
+ if (ret.connection->addVsockClient(VMADDR_CID_LOCAL, port)) goto success;
+ break;
+#endif // __BIONIC__
+ default:
+ LOG_ALWAYS_FATAL("Unknown socket type");
+ }
+ }
+ LOG_ALWAYS_FATAL("Could not connect");
+ success:;
+ }
+
+ ret.rootBinder = ret.connection->getRootObject();
+ return ret;
+ }
+
+ BinderRpcTestProcessConnection createRpcTestSocketServerProcess(size_t numThreads) {
+ BinderRpcTestProcessConnection ret{
+ .proc = createRpcTestSocketServerProcess(numThreads,
+ [&](const sp<RpcServer>& server,
+ const sp<RpcConnection>& connection) {
+ sp<MyBinderRpcTest> service =
+ new MyBinderRpcTest;
+ server->setRootObject(service);
+ service->connection =
+ connection; // for testing only
+ }),
+ };
+
+ ret.rootBinder = ret.proc.rootBinder;
+ ret.rootIface = interface_cast<IBinderRpcTest>(ret.rootBinder);
+
+ return ret;
+ }
+};
+
+TEST_P(BinderRpc, RootObjectIsNull) {
+ auto proc = createRpcTestSocketServerProcess(1,
+ [](const sp<RpcServer>& server,
+ const sp<RpcConnection>&) {
+ // this is the default, but to be explicit
+ server->setRootObject(nullptr);
+ });
+
+ // retrieved by getRootObject when process is created above
+ EXPECT_EQ(nullptr, proc.rootBinder);
+
+ // make sure we can retrieve it again (process doesn't crash)
+ EXPECT_EQ(nullptr, proc.connection->getRootObject());
+}
+
+TEST_P(BinderRpc, Ping) {
+ auto proc = createRpcTestSocketServerProcess(1);
+ ASSERT_NE(proc.rootBinder, nullptr);
+ EXPECT_EQ(OK, proc.rootBinder->pingBinder());
+}
+
+TEST_P(BinderRpc, GetInterfaceDescriptor) {
+ auto proc = createRpcTestSocketServerProcess(1);
+ ASSERT_NE(proc.rootBinder, nullptr);
+ EXPECT_EQ(IBinderRpcTest::descriptor, proc.rootBinder->getInterfaceDescriptor());
+}
+
+TEST_P(BinderRpc, TransactionsMustBeMarkedRpc) {
+ auto proc = createRpcTestSocketServerProcess(1);
+ Parcel data;
+ Parcel reply;
+ EXPECT_EQ(BAD_TYPE, proc.rootBinder->transact(IBinder::PING_TRANSACTION, data, &reply, 0));
+}
+
+TEST_P(BinderRpc, UnknownTransaction) {
+ auto proc = createRpcTestSocketServerProcess(1);
+ Parcel data;
+ data.markForBinder(proc.rootBinder);
+ Parcel reply;
+ EXPECT_EQ(UNKNOWN_TRANSACTION, proc.rootBinder->transact(1337, data, &reply, 0));
+}
+
+TEST_P(BinderRpc, SendSomethingOneway) {
+ auto proc = createRpcTestSocketServerProcess(1);
+ EXPECT_OK(proc.rootIface->sendString("asdf"));
+}
+
+TEST_P(BinderRpc, SendAndGetResultBack) {
+ auto proc = createRpcTestSocketServerProcess(1);
+ std::string doubled;
+ EXPECT_OK(proc.rootIface->doubleString("cool ", &doubled));
+ EXPECT_EQ("cool cool ", doubled);
+}
+
+TEST_P(BinderRpc, SendAndGetResultBackBig) {
+ auto proc = createRpcTestSocketServerProcess(1);
+ std::string single = std::string(1024, 'a');
+ std::string doubled;
+ EXPECT_OK(proc.rootIface->doubleString(single, &doubled));
+ EXPECT_EQ(single + single, doubled);
+}
+
+TEST_P(BinderRpc, CallMeBack) {
+ auto proc = createRpcTestSocketServerProcess(1);
+
+ int32_t pingResult;
+ EXPECT_OK(proc.rootIface->pingMe(new MyBinderRpcSession("foo"), &pingResult));
+ EXPECT_EQ(OK, pingResult);
+
+ EXPECT_EQ(0, MyBinderRpcSession::gNum);
+}
+
+TEST_P(BinderRpc, RepeatBinder) {
+ auto proc = createRpcTestSocketServerProcess(1);
+
+ sp<IBinder> inBinder = new MyBinderRpcSession("foo");
+ sp<IBinder> outBinder;
+ EXPECT_OK(proc.rootIface->repeatBinder(inBinder, &outBinder));
+ EXPECT_EQ(inBinder, outBinder);
+
+ wp<IBinder> weak = inBinder;
+ inBinder = nullptr;
+ outBinder = nullptr;
+
+ // Force reading a reply, to process any pending dec refs from the other
+ // process (the other process will process dec refs there before processing
+ // the ping here).
+ EXPECT_EQ(OK, proc.rootBinder->pingBinder());
+
+ EXPECT_EQ(nullptr, weak.promote());
+
+ EXPECT_EQ(0, MyBinderRpcSession::gNum);
+}
+
+TEST_P(BinderRpc, RepeatTheirBinder) {
+ auto proc = createRpcTestSocketServerProcess(1);
+
+ sp<IBinderRpcSession> session;
+ EXPECT_OK(proc.rootIface->openSession("aoeu", &session));
+
+ sp<IBinder> inBinder = IInterface::asBinder(session);
+ sp<IBinder> outBinder;
+ EXPECT_OK(proc.rootIface->repeatBinder(inBinder, &outBinder));
+ EXPECT_EQ(inBinder, outBinder);
+
+ wp<IBinder> weak = inBinder;
+ session = nullptr;
+ inBinder = nullptr;
+ outBinder = nullptr;
+
+ // Force reading a reply, to process any pending dec refs from the other
+ // process (the other process will process dec refs there before processing
+ // the ping here).
+ EXPECT_EQ(OK, proc.rootBinder->pingBinder());
+
+ EXPECT_EQ(nullptr, weak.promote());
+}
+
+TEST_P(BinderRpc, RepeatBinderNull) {
+ auto proc = createRpcTestSocketServerProcess(1);
+
+ sp<IBinder> outBinder;
+ EXPECT_OK(proc.rootIface->repeatBinder(nullptr, &outBinder));
+ EXPECT_EQ(nullptr, outBinder);
+}
+
+TEST_P(BinderRpc, HoldBinder) {
+ auto proc = createRpcTestSocketServerProcess(1);
+
+ IBinder* ptr = nullptr;
+ {
+ sp<IBinder> binder = new BBinder();
+ ptr = binder.get();
+ EXPECT_OK(proc.rootIface->holdBinder(binder));
+ }
+
+ sp<IBinder> held;
+ EXPECT_OK(proc.rootIface->getHeldBinder(&held));
+
+ EXPECT_EQ(held.get(), ptr);
+
+ // stop holding binder, because we test to make sure references are cleaned
+ // up
+ EXPECT_OK(proc.rootIface->holdBinder(nullptr));
+ // and flush ref counts
+ EXPECT_EQ(OK, proc.rootBinder->pingBinder());
+}
+
+// START TESTS FOR LIMITATIONS OF SOCKET BINDER
+// These are behavioral differences form regular binder, where certain usecases
+// aren't supported.
+
+TEST_P(BinderRpc, CannotMixBindersBetweenUnrelatedSocketConnections) {
+ auto proc1 = createRpcTestSocketServerProcess(1);
+ auto proc2 = createRpcTestSocketServerProcess(1);
+
+ sp<IBinder> outBinder;
+ EXPECT_EQ(INVALID_OPERATION,
+ proc1.rootIface->repeatBinder(proc2.rootBinder, &outBinder).transactionError());
+}
+
+TEST_P(BinderRpc, CannotSendRegularBinderOverSocketBinder) {
+ auto proc = createRpcTestSocketServerProcess(1);
+
+ sp<IBinder> someRealBinder = IInterface::asBinder(defaultServiceManager());
+ sp<IBinder> outBinder;
+ EXPECT_EQ(INVALID_OPERATION,
+ proc.rootIface->repeatBinder(someRealBinder, &outBinder).transactionError());
+}
+
+TEST_P(BinderRpc, CannotSendSocketBinderOverRegularBinder) {
+ auto proc = createRpcTestSocketServerProcess(1);
+
+ // for historical reasons, IServiceManager interface only returns the
+ // exception code
+ EXPECT_EQ(binder::Status::EX_TRANSACTION_FAILED,
+ defaultServiceManager()->addService(String16("not_suspicious"), proc.rootBinder));
+}
+
+// END TESTS FOR LIMITATIONS OF SOCKET BINDER
+
+TEST_P(BinderRpc, RepeatRootObject) {
+ auto proc = createRpcTestSocketServerProcess(1);
+
+ sp<IBinder> outBinder;
+ EXPECT_OK(proc.rootIface->repeatBinder(proc.rootBinder, &outBinder));
+ EXPECT_EQ(proc.rootBinder, outBinder);
+}
+
+TEST_P(BinderRpc, NestedTransactions) {
+ auto proc = createRpcTestSocketServerProcess(1);
+
+ auto nastyNester = sp<MyBinderRpcTest>::make();
+ EXPECT_OK(proc.rootIface->nestMe(nastyNester, 10));
+
+ wp<IBinder> weak = nastyNester;
+ nastyNester = nullptr;
+ EXPECT_EQ(nullptr, weak.promote());
+}
+
+TEST_P(BinderRpc, SameBinderEquality) {
+ auto proc = createRpcTestSocketServerProcess(1);
+
+ sp<IBinder> a;
+ EXPECT_OK(proc.rootIface->alwaysGiveMeTheSameBinder(&a));
+
+ sp<IBinder> b;
+ EXPECT_OK(proc.rootIface->alwaysGiveMeTheSameBinder(&b));
+
+ EXPECT_EQ(a, b);
+}
+
+TEST_P(BinderRpc, SameBinderEqualityWeak) {
+ auto proc = createRpcTestSocketServerProcess(1);
+
+ sp<IBinder> a;
+ EXPECT_OK(proc.rootIface->alwaysGiveMeTheSameBinder(&a));
+ wp<IBinder> weak = a;
+ a = nullptr;
+
+ sp<IBinder> b;
+ EXPECT_OK(proc.rootIface->alwaysGiveMeTheSameBinder(&b));
+
+ // this is the wrong behavior, since BpBinder
+ // doesn't implement onIncStrongAttempted
+ // but make sure there is no crash
+ EXPECT_EQ(nullptr, weak.promote());
+
+ GTEST_SKIP() << "Weak binders aren't currently re-promotable for RPC binder.";
+
+ // In order to fix this:
+ // - need to have incStrongAttempted reflected across IPC boundary (wait for
+ // response to promote - round trip...)
+ // - sendOnLastWeakRef, to delete entries out of RpcState table
+ EXPECT_EQ(b, weak.promote());
+}
+
+#define expectSessions(expected, iface) \
+ do { \
+ int session; \
+ EXPECT_OK((iface)->getNumOpenSessions(&session)); \
+ EXPECT_EQ(expected, session); \
+ } while (false)
+
+TEST_P(BinderRpc, SingleSession) {
+ auto proc = createRpcTestSocketServerProcess(1);
+
+ sp<IBinderRpcSession> session;
+ EXPECT_OK(proc.rootIface->openSession("aoeu", &session));
+ std::string out;
+ EXPECT_OK(session->getName(&out));
+ EXPECT_EQ("aoeu", out);
+
+ expectSessions(1, proc.rootIface);
+ session = nullptr;
+ expectSessions(0, proc.rootIface);
+}
+
+TEST_P(BinderRpc, ManySessions) {
+ auto proc = createRpcTestSocketServerProcess(1);
+
+ std::vector<sp<IBinderRpcSession>> sessions;
+
+ for (size_t i = 0; i < 15; i++) {
+ expectSessions(i, proc.rootIface);
+ sp<IBinderRpcSession> session;
+ EXPECT_OK(proc.rootIface->openSession(std::to_string(i), &session));
+ sessions.push_back(session);
+ }
+ expectSessions(sessions.size(), proc.rootIface);
+ for (size_t i = 0; i < sessions.size(); i++) {
+ std::string out;
+ EXPECT_OK(sessions.at(i)->getName(&out));
+ EXPECT_EQ(std::to_string(i), out);
+ }
+ expectSessions(sessions.size(), proc.rootIface);
+
+ while (!sessions.empty()) {
+ sessions.pop_back();
+ expectSessions(sessions.size(), proc.rootIface);
+ }
+ expectSessions(0, proc.rootIface);
+}
+
+size_t epochMillis() {
+ using std::chrono::duration_cast;
+ using std::chrono::milliseconds;
+ using std::chrono::seconds;
+ using std::chrono::system_clock;
+ return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
+}
+
+TEST_P(BinderRpc, ThreadPoolGreaterThanEqualRequested) {
+ constexpr size_t kNumThreads = 10;
+
+ auto proc = createRpcTestSocketServerProcess(kNumThreads);
+
+ EXPECT_OK(proc.rootIface->lock());
+
+ // block all but one thread taking locks
+ std::vector<std::thread> ts;
+ for (size_t i = 0; i < kNumThreads - 1; i++) {
+ ts.push_back(std::thread([&] { proc.rootIface->lockUnlock(); }));
+ }
+
+ usleep(100000); // give chance for calls on other threads
+
+ // other calls still work
+ EXPECT_EQ(OK, proc.rootBinder->pingBinder());
+
+ constexpr size_t blockTimeMs = 500;
+ size_t epochMsBefore = epochMillis();
+ // after this, we should never see a response within this time
+ EXPECT_OK(proc.rootIface->unlockInMsAsync(blockTimeMs));
+
+ // this call should be blocked for blockTimeMs
+ EXPECT_EQ(OK, proc.rootBinder->pingBinder());
+
+ size_t epochMsAfter = epochMillis();
+ EXPECT_GE(epochMsAfter, epochMsBefore + blockTimeMs) << epochMsBefore;
+
+ for (auto& t : ts) t.join();
+}
+
+TEST_P(BinderRpc, ThreadPoolOverSaturated) {
+ constexpr size_t kNumThreads = 10;
+ constexpr size_t kNumCalls = kNumThreads + 3;
+ constexpr size_t kSleepMs = 500;
+
+ auto proc = createRpcTestSocketServerProcess(kNumThreads);
+
+ size_t epochMsBefore = epochMillis();
+
+ std::vector<std::thread> ts;
+ for (size_t i = 0; i < kNumCalls; i++) {
+ ts.push_back(std::thread([&] { proc.rootIface->sleepMs(kSleepMs); }));
+ }
+
+ for (auto& t : ts) t.join();
+
+ size_t epochMsAfter = epochMillis();
+
+ EXPECT_GE(epochMsAfter, epochMsBefore + 2 * kSleepMs);
+
+ // Potential flake, but make sure calls are handled in parallel.
+ EXPECT_LE(epochMsAfter, epochMsBefore + 3 * kSleepMs);
+}
+
+TEST_P(BinderRpc, ThreadingStressTest) {
+ constexpr size_t kNumClientThreads = 10;
+ constexpr size_t kNumServerThreads = 10;
+ constexpr size_t kNumCalls = 100;
+
+ auto proc = createRpcTestSocketServerProcess(kNumServerThreads);
+
+ std::vector<std::thread> threads;
+ for (size_t i = 0; i < kNumClientThreads; i++) {
+ threads.push_back(std::thread([&] {
+ for (size_t j = 0; j < kNumCalls; j++) {
+ sp<IBinder> out;
+ proc.rootIface->repeatBinder(proc.rootBinder, &out);
+ EXPECT_EQ(proc.rootBinder, out);
+ }
+ }));
+ }
+
+ for (auto& t : threads) t.join();
+}
+
+TEST_P(BinderRpc, OnewayCallDoesNotWait) {
+ constexpr size_t kReallyLongTimeMs = 100;
+ constexpr size_t kSleepMs = kReallyLongTimeMs * 5;
+
+ // more than one thread, just so this doesn't deadlock
+ auto proc = createRpcTestSocketServerProcess(2);
+
+ size_t epochMsBefore = epochMillis();
+
+ EXPECT_OK(proc.rootIface->sleepMsAsync(kSleepMs));
+
+ size_t epochMsAfter = epochMillis();
+ EXPECT_LT(epochMsAfter, epochMsBefore + kReallyLongTimeMs);
+}
+
+TEST_P(BinderRpc, OnewayCallQueueing) {
+ constexpr size_t kNumSleeps = 10;
+ constexpr size_t kNumExtraServerThreads = 4;
+ constexpr size_t kSleepMs = 50;
+
+ // make sure calls to the same object happen on the same thread
+ auto proc = createRpcTestSocketServerProcess(1 + kNumExtraServerThreads);
+
+ EXPECT_OK(proc.rootIface->lock());
+
+ for (size_t i = 0; i < kNumSleeps; i++) {
+ // these should be processed serially
+ proc.rootIface->sleepMsAsync(kSleepMs);
+ }
+ // should also be processesed serially
+ EXPECT_OK(proc.rootIface->unlockInMsAsync(kSleepMs));
+
+ size_t epochMsBefore = epochMillis();
+ EXPECT_OK(proc.rootIface->lockUnlock());
+ size_t epochMsAfter = epochMillis();
+
+ EXPECT_GT(epochMsAfter, epochMsBefore + kSleepMs * kNumSleeps);
+}
+
+TEST_P(BinderRpc, Die) {
+ // TODO(b/183141167): handle this in library
+ signal(SIGPIPE, SIG_IGN);
+
+ for (bool doDeathCleanup : {true, false}) {
+ auto proc = createRpcTestSocketServerProcess(1);
+
+ // make sure there is some state during crash
+ // 1. we hold their binder
+ sp<IBinderRpcSession> session;
+ EXPECT_OK(proc.rootIface->openSession("happy", &session));
+ // 2. they hold our binder
+ sp<IBinder> binder = new BBinder();
+ EXPECT_OK(proc.rootIface->holdBinder(binder));
+
+ EXPECT_EQ(DEAD_OBJECT, proc.rootIface->die(doDeathCleanup).transactionError())
+ << "Do death cleanup: " << doDeathCleanup;
+
+ proc.proc.expectInvalid = true;
+ }
+}
+
+TEST_P(BinderRpc, WorksWithLibbinderNdkPing) {
+ auto proc = createRpcTestSocketServerProcess(1);
+
+ ndk::SpAIBinder binder = ndk::SpAIBinder(AIBinder_fromPlatformBinder(proc.rootBinder));
+ ASSERT_NE(binder, nullptr);
+
+ ASSERT_EQ(STATUS_OK, AIBinder_ping(binder.get()));
+}
+
+TEST_P(BinderRpc, WorksWithLibbinderNdkUserTransaction) {
+ auto proc = createRpcTestSocketServerProcess(1);
+
+ ndk::SpAIBinder binder = ndk::SpAIBinder(AIBinder_fromPlatformBinder(proc.rootBinder));
+ ASSERT_NE(binder, nullptr);
+
+ auto ndkBinder = aidl::IBinderRpcTest::fromBinder(binder);
+ ASSERT_NE(ndkBinder, nullptr);
+
+ std::string out;
+ ndk::ScopedAStatus status = ndkBinder->doubleString("aoeu", &out);
+ ASSERT_TRUE(status.isOk()) << status.getDescription();
+ ASSERT_EQ("aoeuaoeu", out);
+}
+
+ssize_t countFds() {
+ DIR* dir = opendir("/proc/self/fd/");
+ if (dir == nullptr) return -1;
+ ssize_t ret = 0;
+ dirent* ent;
+ while ((ent = readdir(dir)) != nullptr) ret++;
+ closedir(dir);
+ return ret;
+}
+
+TEST_P(BinderRpc, Fds) {
+ ssize_t beforeFds = countFds();
+ ASSERT_GE(beforeFds, 0);
+ {
+ auto proc = createRpcTestSocketServerProcess(10);
+ ASSERT_EQ(OK, proc.rootBinder->pingBinder());
+ }
+ ASSERT_EQ(beforeFds, countFds()) << (system("ls -l /proc/self/fd/"), "fd leak?");
+}
+
+INSTANTIATE_TEST_CASE_P(PerSocket, BinderRpc,
+ ::testing::Values(SocketType::UNIX
+#ifdef __BIONIC__
+ ,
+ SocketType::VSOCK
+#endif // __BIONIC__
+ ),
+ PrintSocketType);
+
+} // namespace android
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ android::base::InitLogging(argv, android::base::StderrLogger, android::base::DefaultAborter);
+ return RUN_ALL_TESTS();
+}
diff --git a/libs/binder/tests/binderStabilityTest.cpp b/libs/binder/tests/binderStabilityTest.cpp
index 1f2779a..4270540 100644
--- a/libs/binder/tests/binderStabilityTest.cpp
+++ b/libs/binder/tests/binderStabilityTest.cpp
@@ -131,6 +131,17 @@
EXPECT_TRUE(Stability::requiresVintfDeclaration(BadStableBinder::vintf()));
}
+TEST(BinderStability, ForceDowngradeStability) {
+ sp<IBinder> someBinder = BadStableBinder::vintf();
+
+ EXPECT_TRUE(Stability::requiresVintfDeclaration(someBinder));
+
+ // silly to do this after already using the binder, but it's for the test
+ Stability::forceDowngradeCompilationUnit(someBinder);
+
+ EXPECT_FALSE(Stability::requiresVintfDeclaration(someBinder));
+}
+
TEST(BinderStability, VintfStabilityServerMustBeDeclaredInManifest) {
sp<IBinder> vintfServer = BadStableBinder::vintf();
diff --git a/libs/binder/tests/binderTextOutputTest.cpp b/libs/binder/tests/binderTextOutputTest.cpp
index ce99f59..b37030e 100644
--- a/libs/binder/tests/binderTextOutputTest.cpp
+++ b/libs/binder/tests/binderTextOutputTest.cpp
@@ -26,7 +26,6 @@
#include <binder/Parcel.h>
#include <binder/TextOutput.h>
-#include <binder/Debug.h>
static void CheckMessage(CapturedStderr& cap,
const char* expected,
diff --git a/libs/binder/tests/fuzzers/Android.bp b/libs/binder/tests/fuzzers/Android.bp
index 5531296..b1263e8 100644
--- a/libs/binder/tests/fuzzers/Android.bp
+++ b/libs/binder/tests/fuzzers/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "binder_fuzz_defaults",
host_supported: true,
diff --git a/libs/binder/tests/fuzzers/TextOutputFuzz.cpp b/libs/binder/tests/fuzzers/TextOutputFuzz.cpp
index c950020..5e3502a 100644
--- a/libs/binder/tests/fuzzers/TextOutputFuzz.cpp
+++ b/libs/binder/tests/fuzzers/TextOutputFuzz.cpp
@@ -16,7 +16,6 @@
#include <fuzzer/FuzzedDataProvider.h>
-#include <binder/Debug.h>
#include <binder/Parcel.h>
#include <binder/TextOutput.h>
#include "android-base/file.h"
diff --git a/libs/binderdebug/Android.bp b/libs/binderdebug/Android.bp
index 343246a..3eeaf3e 100644
--- a/libs/binderdebug/Android.bp
+++ b/libs/binderdebug/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library {
name: "libbinderdebug",
vendor_available: true,
diff --git a/libs/binderdebug/tests/Android.bp b/libs/binderdebug/tests/Android.bp
index 4c06b1d..d141a05 100644
--- a/libs/binderdebug/tests/Android.bp
+++ b/libs/binderdebug/tests/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "libbinderdebug_test",
test_suites: ["general-tests"],
diff --git a/libs/binderthreadstate/1.0/Android.bp b/libs/binderthreadstate/1.0/Android.bp
index ebdc932..99477d8 100644
--- a/libs/binderthreadstate/1.0/Android.bp
+++ b/libs/binderthreadstate/1.0/Android.bp
@@ -1,5 +1,14 @@
// This file is autogenerated by hidl-gen -Landroidbp.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
hidl_interface {
name: "binderthreadstateutilstest@1.0",
root: "binderthreadstateutilstest",
diff --git a/libs/binderthreadstate/Android.bp b/libs/binderthreadstate/Android.bp
index 08c62df..0a82463 100644
--- a/libs/binderthreadstate/Android.bp
+++ b/libs/binderthreadstate/Android.bp
@@ -14,6 +14,15 @@
// DO NOT ADD NEW USAGES OF THIS
// See comments in header file.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "libbinderthreadstateutils",
double_loadable: true,
diff --git a/libs/bufferqueueconverter/Android.bp b/libs/bufferqueueconverter/Android.bp
index bab2674..c5d3a32 100644
--- a/libs/bufferqueueconverter/Android.bp
+++ b/libs/bufferqueueconverter/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "libbufferqueueconverter_headers",
vendor_available: true,
diff --git a/libs/cputimeinstate/Android.bp b/libs/cputimeinstate/Android.bp
index e3cd085..570af71 100644
--- a/libs/cputimeinstate/Android.bp
+++ b/libs/cputimeinstate/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library {
name: "libtimeinstate",
srcs: ["cputimeinstate.cpp"],
@@ -35,4 +44,3 @@
],
require_root: true,
}
-
diff --git a/libs/cputimeinstate/cputimeinstate.cpp b/libs/cputimeinstate/cputimeinstate.cpp
index 462f0db..7e9bb7d 100644
--- a/libs/cputimeinstate/cputimeinstate.cpp
+++ b/libs/cputimeinstate/cputimeinstate.cpp
@@ -155,10 +155,14 @@
return true;
}
-static bool attachTracepointProgram(const std::string &eventType, const std::string &eventName) {
+static int retrieveProgramFd(const std::string &eventType, const std::string &eventName) {
std::string path = StringPrintf(BPF_FS_PATH "prog_time_in_state_tracepoint_%s_%s",
eventType.c_str(), eventName.c_str());
- int prog_fd = retrieveProgram(path.c_str());
+ return retrieveProgram(path.c_str());
+}
+
+static bool attachTracepointProgram(const std::string &eventType, const std::string &eventName) {
+ int prog_fd = retrieveProgramFd(eventType, eventName);
if (prog_fd < 0) return false;
return bpf_attach_tracepoint(prog_fd, eventType.c_str(), eventName.c_str()) >= 0;
}
@@ -174,6 +178,17 @@
return {};
}
+// Check if tracking is expected to work without activating it.
+bool isTrackingUidTimesSupported() {
+ auto freqs = getCpuFreqs();
+ if (!freqs || freqs->empty()) return false;
+ if (gTracking) return true;
+ if (retrieveProgramFd("sched", "sched_switch") < 0) return false;
+ if (retrieveProgramFd("power", "cpu_frequency") < 0) return false;
+ if (retrieveProgramFd("sched", "sched_process_free") < 0) return false;
+ return true;
+}
+
// Start tracking and aggregating data to be reported by getUidCpuFreqTimes and getUidsCpuFreqTimes.
// Returns true on success, false otherwise.
// Tracking is active only once a live process has successfully called this function; if the calling
diff --git a/libs/cputimeinstate/cputimeinstate.h b/libs/cputimeinstate/cputimeinstate.h
index 46de669..4145374 100644
--- a/libs/cputimeinstate/cputimeinstate.h
+++ b/libs/cputimeinstate/cputimeinstate.h
@@ -22,6 +22,7 @@
namespace android {
namespace bpf {
+bool isTrackingUidTimesSupported();
bool startTrackingUidTimes();
std::optional<std::vector<std::vector<uint64_t>>> getTotalCpuFreqTimes();
std::optional<std::vector<std::vector<uint64_t>>> getUidCpuFreqTimes(uint32_t uid);
diff --git a/libs/cputimeinstate/testtimeinstate.cpp b/libs/cputimeinstate/testtimeinstate.cpp
index d25b2e9..2112b10 100644
--- a/libs/cputimeinstate/testtimeinstate.cpp
+++ b/libs/cputimeinstate/testtimeinstate.cpp
@@ -40,6 +40,11 @@
using std::vector;
+TEST(TimeInStateTest, IsTrackingSupported) {
+ isTrackingUidTimesSupported();
+ SUCCEED();
+}
+
TEST(TimeInStateTest, TotalTimeInState) {
auto times = getTotalCpuFreqTimes();
ASSERT_TRUE(times.has_value());
diff --git a/libs/diskusage/Android.bp b/libs/diskusage/Android.bp
index a826306..8684061 100644
--- a/libs/diskusage/Android.bp
+++ b/libs/diskusage/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "libdiskusage",
srcs: ["dirsize.c"],
diff --git a/libs/dumputils/Android.bp b/libs/dumputils/Android.bp
index e403d36..acda402 100644
--- a/libs/dumputils/Android.bp
+++ b/libs/dumputils/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library {
name: "libdumputils",
diff --git a/libs/fakeservicemanager/Android.bp b/libs/fakeservicemanager/Android.bp
index 76518c1..47c0657 100644
--- a/libs/fakeservicemanager/Android.bp
+++ b/libs/fakeservicemanager/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "fakeservicemanager_defaults",
host_supported: true,
diff --git a/libs/gralloc/types/Android.bp b/libs/gralloc/types/Android.bp
index 243d7f1..a0032ae 100644
--- a/libs/gralloc/types/Android.bp
+++ b/libs/gralloc/types/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library {
name: "libgralloctypes",
defaults: ["libbinder_ndk_host_user"],
@@ -43,14 +52,14 @@
],
shared_libs: [
- "android.hardware.graphics.common-unstable-ndk_platform",
+ "android.hardware.graphics.common-V2-ndk_platform",
"android.hardware.graphics.mapper@4.0",
"libhidlbase",
"liblog",
],
export_shared_lib_headers: [
- "android.hardware.graphics.common-unstable-ndk_platform",
+ "android.hardware.graphics.common-V2-ndk_platform",
"android.hardware.graphics.mapper@4.0",
"libhidlbase",
],
diff --git a/libs/gralloc/types/fuzzer/Android.bp b/libs/gralloc/types/fuzzer/Android.bp
index 8933dc3..6689771 100644
--- a/libs/gralloc/types/fuzzer/Android.bp
+++ b/libs/gralloc/types/fuzzer/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_fuzz {
name: "libgralloctypes_fuzzer",
defaults: ["libbinder_ndk_host_user"],
diff --git a/libs/gralloc/types/tests/Android.bp b/libs/gralloc/types/tests/Android.bp
index b939c1d..66eb0aa 100644
--- a/libs/gralloc/types/tests/Android.bp
+++ b/libs/gralloc/types/tests/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "GrallocTypes_test",
shared_libs: [
diff --git a/libs/graphicsenv/Android.bp b/libs/graphicsenv/Android.bp
index 642c5f2..a96a07a 100644
--- a/libs/graphicsenv/Android.bp
+++ b/libs/graphicsenv/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libgraphicsenv",
diff --git a/libs/graphicsenv/OWNERS b/libs/graphicsenv/OWNERS
index c0bb75f..8c28464 100644
--- a/libs/graphicsenv/OWNERS
+++ b/libs/graphicsenv/OWNERS
@@ -1,6 +1,4 @@
chrisforbes@google.com
cnorthrop@google.com
-courtneygo@google.com
lpy@google.com
timvp@google.com
-zzyiwei@google.com
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 18ade37..8398794 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -11,6 +11,15 @@
// 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.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "libgui_headers",
vendor_available: true,
@@ -123,7 +132,16 @@
aidl: {
export_aidl_headers: true,
- }
+ },
+
+ pgo: {
+ sampling: true,
+ profile_file: "libgui/libgui.profdata",
+ },
+
+ lto: {
+ thin: true,
+ },
}
// Used by media codec services exclusively as a static lib for
diff --git a/libs/gui/OWNERS b/libs/gui/OWNERS
index 1667fb0..45c958e 100644
--- a/libs/gui/OWNERS
+++ b/libs/gui/OWNERS
@@ -1,5 +1,4 @@
adyabr@google.com
-akrulec@google.com
alecmouri@google.com
chaviw@google.com
chrisforbes@google.com
@@ -7,7 +6,6 @@
lpy@google.com
mathias@google.com
racarr@google.com
-stoza@google.com
vishnun@google.com
per-file EndToEndNativeInputTest.cpp = svv@google.com
diff --git a/libs/gui/sysprop/Android.bp b/libs/gui/sysprop/Android.bp
index 64b1eac..bddb0ac 100644
--- a/libs/gui/sysprop/Android.bp
+++ b/libs/gui/sysprop/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
sysprop_library {
name: "LibGuiProperties",
srcs: ["*.sysprop"],
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index a6bcd10..6077b4e 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -2,6 +2,15 @@
// Build the binary to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
// to integrate with auto-test framework.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "libgui_test",
test_suites: ["device-tests"],
diff --git a/libs/incidentcompanion/Android.bp b/libs/incidentcompanion/Android.bp
index 63411b9..ef7f523 100644
--- a/libs/incidentcompanion/Android.bp
+++ b/libs/incidentcompanion/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
filegroup {
name: "incidentcompanion_aidl",
srcs: [
@@ -49,4 +58,3 @@
"-Wunused-parameter",
],
}
-
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 6a5d434..393c0f6 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -14,6 +14,15 @@
// libinput is partially built for the host (used by build time keymap validation tool)
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library {
name: "libinput",
host_supported: true,
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index 3b57146..cacce92 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -1,4 +1,13 @@
// Build the unit tests.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "libinput_tests",
srcs: [
diff --git a/libs/math/Android.bp b/libs/math/Android.bp
index 3b1edcb..5595587 100644
--- a/libs/math/Android.bp
+++ b/libs/math/Android.bp
@@ -12,6 +12,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_applicable_licenses: ["frameworks_native_libs_math_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_libs_math_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_static {
name: "libmath",
host_supported: true,
diff --git a/libs/math/OWNERS b/libs/math/OWNERS
index 6fb149a..72d33bc 100644
--- a/libs/math/OWNERS
+++ b/libs/math/OWNERS
@@ -1,6 +1,3 @@
-jaesoo@google.com
-jiyong@google.com
mathias@google.com
-pawin@google.com
randolphs@google.com
romainguy@google.com
diff --git a/libs/math/tests/Android.bp b/libs/math/tests/Android.bp
index 0184f56..4a7c4dd 100644
--- a/libs/math/tests/Android.bp
+++ b/libs/math/tests/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_libs_math_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_libs_math_license"],
+}
+
cc_test {
name: "vec_test",
srcs: ["vec_test.cpp"],
diff --git a/libs/nativebase/Android.bp b/libs/nativebase/Android.bp
index 8399e8c..1a4729c 100644
--- a/libs/nativebase/Android.bp
+++ b/libs/nativebase/Android.bp
@@ -12,6 +12,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_applicable_licenses: ["frameworks_native_libs_nativebase_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_libs_nativebase_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_headers {
name: "libnativebase_headers",
vendor_available: true,
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index b431cbb..62a4d7f 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -21,7 +21,7 @@
#include <gui/DisplayEventDispatcher.h>
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
-#include <nativehelper/JNIHelp.h>
+#include <jni.h>
#include <private/android/choreographer.h>
#include <utils/Looper.h>
#include <utils/Timers.h>
diff --git a/libs/nativedisplay/Android.bp b/libs/nativedisplay/Android.bp
index f56b3a2..6e9c999 100644
--- a/libs/nativedisplay/Android.bp
+++ b/libs/nativedisplay/Android.bp
@@ -12,6 +12,25 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_applicable_licenses: [
+ "frameworks_native_libs_nativedisplay_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_libs_nativedisplay_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_headers {
name: "libnativedisplay_headers",
export_include_dirs: ["include",],
@@ -53,15 +72,12 @@
"libcutils",
"libEGL",
"libGLESv2",
- "libnativehelper",
- ],
-
- export_shared_lib_headers: [
- "libnativehelper",
],
header_libs: [
"libnativedisplay_headers",
+ "libnativehelper_header_only",
],
+ export_header_lib_headers: ["libnativehelper_header_only"],
}
diff --git a/libs/nativedisplay/include-private/private/android/choreographer.h b/libs/nativedisplay/include-private/private/android/choreographer.h
index 2164930..c00ce4e 100644
--- a/libs/nativedisplay/include-private/private/android/choreographer.h
+++ b/libs/nativedisplay/include-private/private/android/choreographer.h
@@ -18,7 +18,7 @@
#include <apex/choreographer.h>
#include <inttypes.h>
-#include <nativehelper/JNIHelp.h>
+#include <jni.h>
namespace android {
diff --git a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
index f371667..85fe42f 100644
--- a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
+++ b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
@@ -19,7 +19,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include <nativehelper/JNIHelp.h>
+#include <jni.h>
#include <system/graphics.h>
// This file provides a facade API on top of SurfaceTexture, which avoids using
diff --git a/libs/nativedisplay/surfacetexture/surface_texture.cpp b/libs/nativedisplay/surfacetexture/surface_texture.cpp
index ebe4484..c214ab7 100644
--- a/libs/nativedisplay/surfacetexture/surface_texture.cpp
+++ b/libs/nativedisplay/surfacetexture/surface_texture.cpp
@@ -29,8 +29,7 @@
#include <mutex>
#include <jni.h>
-#include <nativehelper/JNIHelp.h>
-#include <nativehelper/ScopedLocalRef.h>
+#include <nativehelper/scoped_local_ref.h>
struct ASurfaceTexture {
android::sp<android::SurfaceTexture> consumer;
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index 1ec73ce..3030068 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -51,13 +51,13 @@
std::string("AHardwareBuffer pid [") + std::to_string(getpid()) + "]"));
status_t err = gbuffer->initCheck();
- if (err != 0 || gbuffer->handle == 0) {
+ if (err != 0 || gbuffer->handle == nullptr) {
if (err == NO_MEMORY) {
GraphicBuffer::dumpAllocationsToSystemLog();
}
ALOGE("GraphicBuffer(w=%u, h=%u, lc=%u) failed (%s), handle=%p",
desc->width, desc->height, desc->layers, strerror(-err), gbuffer->handle);
- return err;
+ return err == 0 ? UNKNOWN_ERROR : err;
}
*outBuffer = AHardwareBuffer_from_GraphicBuffer(gbuffer.get());
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index 07e5d86..8675439 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -12,6 +12,25 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_applicable_licenses: [
+ "frameworks_native_libs_nativewindow_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_libs_nativewindow_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
ndk_headers {
name: "libnativewindow_ndk_headers",
from: "include/android",
@@ -28,6 +47,7 @@
// TODO(b/153609531): remove when no longer needed.
native_bridge_supported: true,
min_sdk_version: "29",
+ host_supported: true,
}
ndk_library {
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index ae5e47b..dcb05b5 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -332,8 +332,6 @@
*/
typedef struct AHardwareBuffer AHardwareBuffer;
-#if __ANDROID_API__ >= 26
-
/**
* Allocates a buffer that matches the passed AHardwareBuffer_Desc.
*
@@ -501,10 +499,6 @@
*/
int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** outBuffer) __INTRODUCED_IN(26);
-#endif // __ANDROID_API__ >= 26
-
-#if __ANDROID_API__ >= 29
-
/**
* Test whether the given format and usage flag combination is
* allocatable.
@@ -540,7 +534,6 @@
int AHardwareBuffer_lockAndGetInfo(AHardwareBuffer* buffer, uint64_t usage,
int32_t fence, const ARect* rect, void** outVirtualAddress,
int32_t* outBytesPerPixel, int32_t* outBytesPerStride) __INTRODUCED_IN(29);
-#endif // __ANDROID_API__ >= 29
__END_DECLS
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index 36aad2e..a3a45e3 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -185,8 +185,6 @@
*/
int32_t ANativeWindow_unlockAndPost(ANativeWindow* window);
-#if __ANDROID_API__ >= 26
-
/**
* Set a transform that will be applied to future buffers posted to the window.
*
@@ -197,10 +195,6 @@
*/
int32_t ANativeWindow_setBuffersTransform(ANativeWindow* window, int32_t transform) __INTRODUCED_IN(26);
-#endif // __ANDROID_API__ >= 26
-
-#if __ANDROID_API__ >= 28
-
/**
* All buffers queued after this call will be associated with the dataSpace
* parameter specified.
@@ -229,10 +223,6 @@
*/
int32_t ANativeWindow_getBuffersDataSpace(ANativeWindow* window) __INTRODUCED_IN(28);
-#endif // __ANDROID_API__ >= 28
-
-#if __ANDROID_API__ >= 30
-
/** Compatibility value for ANativeWindow_setFrameRate. */
enum ANativeWindow_FrameRateCompatibility {
/**
@@ -301,8 +291,6 @@
*/
void ANativeWindow_tryAllocateBuffers(ANativeWindow* window);
-#endif // __ANDROID_API__ >= 30
-
#ifdef __cplusplus
};
#endif
diff --git a/libs/nativewindow/tests/Android.bp b/libs/nativewindow/tests/Android.bp
index cdb3d20..2744458 100644
--- a/libs/nativewindow/tests/Android.bp
+++ b/libs/nativewindow/tests/Android.bp
@@ -14,6 +14,17 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_libs_nativewindow_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_native_libs_nativewindow_license",
+ ],
+}
+
cc_test {
name: "libnativewindow_test",
test_suites: [
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index eb6080f..aae1e31 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "renderengine_defaults",
cflags: [
diff --git a/libs/renderengine/OWNERS b/libs/renderengine/OWNERS
index b44456b..c478506 100644
--- a/libs/renderengine/OWNERS
+++ b/libs/renderengine/OWNERS
@@ -1,4 +1,5 @@
alecmouri@google.com
+djsollen@google.com
jreck@google.com
lpy@google.com
-stoza@google.com
+scroggo@google.com
diff --git a/libs/renderengine/tests/Android.bp b/libs/renderengine/tests/Android.bp
index e98babc..fdb3a6f 100644
--- a/libs/renderengine/tests/Android.bp
+++ b/libs/renderengine/tests/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "librenderengine_test",
defaults: ["surfaceflinger_defaults"],
diff --git a/libs/sensor/Android.bp b/libs/sensor/Android.bp
index e8154a6..497c33c 100644
--- a/libs/sensor/Android.bp
+++ b/libs/sensor/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libsensor",
diff --git a/libs/sensor/tests/Android.bp b/libs/sensor/tests/Android.bp
index c9a7668..8fdb003 100644
--- a/libs/sensor/tests/Android.bp
+++ b/libs/sensor/tests/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "libsensor_test",
diff --git a/libs/sensorprivacy/Android.bp b/libs/sensorprivacy/Android.bp
index 4a606ff..00514c4 100644
--- a/libs/sensorprivacy/Android.bp
+++ b/libs/sensorprivacy/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libsensorprivacy",
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 47eb59f..07760ab 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -12,6 +12,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_applicable_licenses: ["frameworks_native_libs_ui_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_libs_ui_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libui",
vendor_available: true,
@@ -72,7 +89,7 @@
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.allocator@4.0",
- "android.hardware.graphics.common-unstable-ndk_platform",
+ "android.hardware.graphics.common-V2-ndk_platform",
"android.hardware.graphics.common@1.2",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.1",
@@ -89,7 +106,7 @@
export_shared_lib_headers: [
"android.hardware.graphics.common@1.2",
- "android.hardware.graphics.common-unstable-ndk_platform",
+ "android.hardware.graphics.common-V2-ndk_platform",
"android.hardware.graphics.mapper@4.0",
"libgralloctypes",
],
diff --git a/libs/ui/OWNERS b/libs/ui/OWNERS
index b1317b1..a0b5fe7 100644
--- a/libs/ui/OWNERS
+++ b/libs/ui/OWNERS
@@ -1,7 +1,7 @@
+adyabr@google.com
alecmouri@google.com
chrisforbes@google.com
jreck@google.com
lpy@google.com
mathias@google.com
romainguy@google.com
-stoza@google.com
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index b53342c..bc53346 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_libs_ui_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_libs_ui_license"],
+}
+
cc_test {
name: "Region_test",
shared_libs: ["libui"],
diff --git a/libs/ui/tools/Android.bp b/libs/ui/tools/Android.bp
index fb46c2b..c28c303 100644
--- a/libs/ui/tools/Android.bp
+++ b/libs/ui/tools/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_libs_ui_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_libs_ui_license"],
+}
+
cc_defaults {
name: "libui_tools_default",
clang_cflags: [
diff --git a/libs/vibrator/Android.bp b/libs/vibrator/Android.bp
index 33ab8ba..11b09bd 100644
--- a/libs/vibrator/Android.bp
+++ b/libs/vibrator/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library {
name: "libvibrator",
diff --git a/libs/vibrator/fuzzer/Android.bp b/libs/vibrator/fuzzer/Android.bp
index 8020151..f2a313c 100644
--- a/libs/vibrator/fuzzer/Android.bp
+++ b/libs/vibrator/fuzzer/Android.bp
@@ -17,6 +17,15 @@
*****************************************************************************
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_fuzz {
name: "vibrator_fuzzer",
diff --git a/libs/vr/Android.bp b/libs/vr/Android.bp
index e8176cf..b308895 100644
--- a/libs/vr/Android.bp
+++ b/libs/vr/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-BSD
+ // legacy_notice
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
subdirs = [
"*",
]
diff --git a/libs/vr/libbroadcastring/Android.bp b/libs/vr/libbroadcastring/Android.bp
index 13af470..2eb2f9f 100644
--- a/libs/vr/libbroadcastring/Android.bp
+++ b/libs/vr/libbroadcastring/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "libbroadcastring",
clang: true,
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index 37c19d4..45bdd35 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -12,6 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "libbufferhub_headers",
export_include_dirs: ["include"],
diff --git a/libs/vr/libbufferhubqueue/Android.bp b/libs/vr/libbufferhubqueue/Android.bp
index 77c7911..f372bd7 100644
--- a/libs/vr/libbufferhubqueue/Android.bp
+++ b/libs/vr/libbufferhubqueue/Android.bp
@@ -12,6 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
sourceFiles = [
"buffer_hub_queue_client.cpp",
"buffer_hub_queue_parcelable.cpp",
diff --git a/libs/vr/libbufferhubqueue/benchmarks/Android.bp b/libs/vr/libbufferhubqueue/benchmarks/Android.bp
index ef1eed6..fc1f376 100644
--- a/libs/vr/libbufferhubqueue/benchmarks/Android.bp
+++ b/libs/vr/libbufferhubqueue/benchmarks/Android.bp
@@ -1,4 +1,15 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_benchmark {
srcs: ["buffer_transport_benchmark.cpp"],
shared_libs: [
diff --git a/libs/vr/libbufferhubqueue/tests/Android.bp b/libs/vr/libbufferhubqueue/tests/Android.bp
index a337921..e883916 100644
--- a/libs/vr/libbufferhubqueue/tests/Android.bp
+++ b/libs/vr/libbufferhubqueue/tests/Android.bp
@@ -1,4 +1,15 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
header_libraries = [
"libdvr_headers",
]
diff --git a/libs/vr/libdisplay/Android.bp b/libs/vr/libdisplay/Android.bp
index 8c354fb..365a676 100644
--- a/libs/vr/libdisplay/Android.bp
+++ b/libs/vr/libdisplay/Android.bp
@@ -12,6 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
sourceFiles = [
"display_client.cpp",
"display_manager_client.cpp",
diff --git a/libs/vr/libdvr/Android.bp b/libs/vr/libdvr/Android.bp
index d5a19d3..83c30d7 100644
--- a/libs/vr/libdvr/Android.bp
+++ b/libs/vr/libdvr/Android.bp
@@ -13,6 +13,17 @@
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "libdvr_headers",
export_include_dirs: ["include"],
diff --git a/libs/vr/libdvr/tests/Android.bp b/libs/vr/libdvr/tests/Android.bp
index 3260447..4ed80a4 100644
--- a/libs/vr/libdvr/tests/Android.bp
+++ b/libs/vr/libdvr/tests/Android.bp
@@ -12,6 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
srcs: [
"dvr_display_manager-test.cpp",
diff --git a/libs/vr/libdvrcommon/Android.bp b/libs/vr/libdvrcommon/Android.bp
index e751768..9e1e516 100644
--- a/libs/vr/libdvrcommon/Android.bp
+++ b/libs/vr/libdvrcommon/Android.bp
@@ -12,6 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
localIncludeFiles = [
"include",
]
diff --git a/libs/vr/libpdx/Android.bp b/libs/vr/libpdx/Android.bp
index 24ba830..c1f6da3 100644
--- a/libs/vr/libpdx/Android.bp
+++ b/libs/vr/libpdx/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "libpdx_headers",
export_include_dirs: ["private"],
diff --git a/libs/vr/libpdx/fuzz/Android.bp b/libs/vr/libpdx/fuzz/Android.bp
index b36e0de..cc32b18 100644
--- a/libs/vr/libpdx/fuzz/Android.bp
+++ b/libs/vr/libpdx/fuzz/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_fuzz {
name: "libpdx_service_dispatcher_fuzzer",
clang: true,
diff --git a/libs/vr/libpdx_default_transport/Android.bp b/libs/vr/libpdx_default_transport/Android.bp
index b3534de..ea73d7a 100644
--- a/libs/vr/libpdx_default_transport/Android.bp
+++ b/libs/vr/libpdx_default_transport/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "pdx_default_transport_compiler_defaults",
clang: true,
@@ -75,4 +86,3 @@
"libpdx_default_transport",
],
}
-
diff --git a/libs/vr/libpdx_uds/Android.bp b/libs/vr/libpdx_uds/Android.bp
index 1d6eea2..532d1a7 100644
--- a/libs/vr/libpdx_uds/Android.bp
+++ b/libs/vr/libpdx_uds/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "libpdx_uds",
clang: true,
diff --git a/libs/vr/libperformance/Android.bp b/libs/vr/libperformance/Android.bp
index 35d3dea..5beee35 100644
--- a/libs/vr/libperformance/Android.bp
+++ b/libs/vr/libperformance/Android.bp
@@ -12,6 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
sourceFiles = [
"performance_client.cpp",
"performance_rpc.cpp",
diff --git a/libs/vr/libvr_manager/Android.bp b/libs/vr/libvr_manager/Android.bp
index 2cd6a28..6f2ada4 100644
--- a/libs/vr/libvr_manager/Android.bp
+++ b/libs/vr/libvr_manager/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "libvr_manager",
srcs: [
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index abc64bd..8aca9a5 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -12,6 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
sourceFiles = [
"acquired_buffer.cpp",
"epoll_event_dispatcher.cpp",
diff --git a/libs/vr/libvrflinger/tests/Android.bp b/libs/vr/libvrflinger/tests/Android.bp
index 7fafd3b..dafd354 100644
--- a/libs/vr/libvrflinger/tests/Android.bp
+++ b/libs/vr/libvrflinger/tests/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
shared_libs = [
"android.hardware.configstore-utils",
"android.hardware.configstore@1.0",
diff --git a/libs/vr/libvrsensor/Android.bp b/libs/vr/libvrsensor/Android.bp
index 8542790..8f566a0 100644
--- a/libs/vr/libvrsensor/Android.bp
+++ b/libs/vr/libvrsensor/Android.bp
@@ -12,6 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
sourceFiles = [
"pose_client.cpp",
"latency_model.cpp",
@@ -52,4 +63,3 @@
header_libs: ["libdvr_headers"],
name: "libvrsensor",
}
-
diff --git a/opengl/Android.bp b/opengl/Android.bp
index 48abdce..748f795 100644
--- a/opengl/Android.bp
+++ b/opengl/Android.bp
@@ -12,6 +12,18 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-BSD
+ // SPDX-license-identifier-MIT
+ // legacy_notice
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
ndk_headers {
name: "libEGL_headers",
from: "include",
diff --git a/opengl/OWNERS b/opengl/OWNERS
index b505712..a9bd4bb 100644
--- a/opengl/OWNERS
+++ b/opengl/OWNERS
@@ -1,7 +1,6 @@
chrisforbes@google.com
cnorthrop@google.com
-courtneygo@google.com
ianelliott@google.com
jessehall@google.com
lpy@google.com
-zzyiwei@google.com
+timvp@google.com
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index ed2ed83..3ee0faf 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -1,4 +1,13 @@
// Build the ETC1 library
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library {
name: "libETC1",
srcs: ["ETC1/etc1.cpp"],
diff --git a/opengl/libs/EGL/egl_angle_platform.cpp b/opengl/libs/EGL/egl_angle_platform.cpp
index f82c2a4..4f85eff 100644
--- a/opengl/libs/EGL/egl_angle_platform.cpp
+++ b/opengl/libs/EGL/egl_angle_platform.cpp
@@ -24,16 +24,16 @@
#include <EGL/Platform.h>
#pragma GCC diagnostic pop
+#include <android-base/properties.h>
#include <android/dlext.h>
#include <dlfcn.h>
#include <graphicsenv/GraphicsEnv.h>
-#include <time.h>
#include <log/log.h>
+#include <time.h>
#include <vndksupport/linker.h>
namespace angle {
-constexpr char kAngleEs2Lib[] = "libGLESv2_angle.so";
constexpr int kAngleDlFlags = RTLD_LOCAL | RTLD_NOW;
static GetDisplayPlatformFunc angleGetDisplayPlatform = nullptr;
@@ -107,18 +107,36 @@
android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
void* so = nullptr;
if (ns) {
+ // Loading from an APK, so hard-code the suffix to "_angle".
+ constexpr char kAngleEs2Lib[] = "libGLESv2_angle.so";
const android_dlextinfo dlextinfo = {
.flags = ANDROID_DLEXT_USE_NAMESPACE,
.library_namespace = ns,
};
so = android_dlopen_ext(kAngleEs2Lib, kAngleDlFlags, &dlextinfo);
+ if (so) {
+ ALOGD("dlopen_ext from APK (%s) success at %p", kAngleEs2Lib, so);
+ } else {
+ ALOGE("dlopen_ext(\"%s\") failed: %s", kAngleEs2Lib, dlerror());
+ return false;
+ }
} else {
// If we are here, ANGLE is loaded as built-in gl driver in the sphal.
- so = android_load_sphal_library(kAngleEs2Lib, kAngleDlFlags);
- }
- if (!so) {
- ALOGE("%s failed to dlopen %s!", __FUNCTION__, kAngleEs2Lib);
- return false;
+ // Get the specified ANGLE library filename suffix.
+ std::string angleEs2LibSuffix = android::base::GetProperty("ro.hardware.egl", "");
+ if (angleEs2LibSuffix.empty()) {
+ ALOGE("%s failed to get valid ANGLE library filename suffix!", __FUNCTION__);
+ return false;
+ }
+
+ std::string angleEs2LibName = "libGLESv2_" + angleEs2LibSuffix + ".so";
+ so = android_load_sphal_library(angleEs2LibName.c_str(), kAngleDlFlags);
+ if (so) {
+ ALOGD("dlopen (%s) success at %p", angleEs2LibName.c_str(), so);
+ } else {
+ ALOGE("%s failed to dlopen %s!", __FUNCTION__, angleEs2LibName.c_str());
+ return false;
+ }
}
angleGetDisplayPlatform =
@@ -130,8 +148,7 @@
}
angleResetDisplayPlatform =
- reinterpret_cast<ResetDisplayPlatformFunc>(
- eglGetProcAddress("ANGLEResetDisplayPlatform"));
+ reinterpret_cast<ResetDisplayPlatformFunc>(dlsym(so, "ANGLEResetDisplayPlatform"));
PlatformMethods* platformMethods = nullptr;
if (!((angleGetDisplayPlatform)(dpy, g_PlatformMethodNames,
diff --git a/opengl/tests/Android.bp b/opengl/tests/Android.bp
index 639f351..da717bd 100644
--- a/opengl/tests/Android.bp
+++ b/opengl/tests/Android.bp
@@ -1,4 +1,16 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-BSD
+ // SPDX-license-identifier-MIT
+ // legacy_notice
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
subdirs = [
"angeles",
"configdump",
@@ -16,4 +28,3 @@
"hwc",
"lib",
]
-
diff --git a/opengl/tests/EGLTest/Android.bp b/opengl/tests/EGLTest/Android.bp
index e3912a8..51c9376 100644
--- a/opengl/tests/EGLTest/Android.bp
+++ b/opengl/tests/EGLTest/Android.bp
@@ -1,4 +1,13 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "EGL_test",
diff --git a/opengl/tests/angeles/Android.bp b/opengl/tests/angeles/Android.bp
index 5c398a6..5b81501 100644
--- a/opengl/tests/angeles/Android.bp
+++ b/opengl/tests/angeles/Android.bp
@@ -1,5 +1,50 @@
// Copyright 2006 The Android Open Source Project
+package {
+ default_applicable_licenses: [
+ "frameworks_native_opengl_tests_angeles_license",
+ ],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+//
+// large-scale-change included anything that looked like it might be a license
+// text as a license_text. e.g. LICENSE, NOTICE, COPYING etc.
+//
+// Please consider removing redundant or irrelevant files from 'license_text:'.
+//
+// large-scale-change filtered out the below license kinds as false-positives:
+// SPDX-license-identifier-LGPL
+// SPDX-license-identifier-LGPL-2.1
+// SPDX-license-identifier-LGPL-3.0
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_opengl_tests_angeles_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-BSD",
+ "SPDX-license-identifier-MIT",
+ "legacy_notice",
+ ],
+ license_text: [
+ "license-BSD.txt",
+ "license-LGPL.txt",
+ "license.txt",
+ ],
+}
+
cc_test {
name: "angeles",
diff --git a/opengl/tests/configdump/Android.bp b/opengl/tests/configdump/Android.bp
index ee967970..ffb0c1f 100644
--- a/opengl/tests/configdump/Android.bp
+++ b/opengl/tests/configdump/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-configdump",
diff --git a/opengl/tests/fillrate/Android.bp b/opengl/tests/fillrate/Android.bp
index 689cee4..e4bff01 100644
--- a/opengl/tests/fillrate/Android.bp
+++ b/opengl/tests/fillrate/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-fillrate",
diff --git a/opengl/tests/filter/Android.bp b/opengl/tests/filter/Android.bp
index 23241e1..3b92b37 100644
--- a/opengl/tests/filter/Android.bp
+++ b/opengl/tests/filter/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-filter",
diff --git a/opengl/tests/finish/Android.bp b/opengl/tests/finish/Android.bp
index be20851..c2dfbc3 100644
--- a/opengl/tests/finish/Android.bp
+++ b/opengl/tests/finish/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-finish",
diff --git a/opengl/tests/gl2_basic/Android.bp b/opengl/tests/gl2_basic/Android.bp
index f4538ad..c54bdf3 100644
--- a/opengl/tests/gl2_basic/Android.bp
+++ b/opengl/tests/gl2_basic/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-gl2_basic",
diff --git a/opengl/tests/gl2_cameraeye/Android.bp b/opengl/tests/gl2_cameraeye/Android.bp
index 00e00df..6b8ee85 100644
--- a/opengl/tests/gl2_cameraeye/Android.bp
+++ b/opengl/tests/gl2_cameraeye/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_app {
name: "GL2CameraEye",
// Only compile source java files in this apk.
diff --git a/opengl/tests/gl2_copyTexImage/Android.bp b/opengl/tests/gl2_copyTexImage/Android.bp
index 87fa7ea..0a84d25 100644
--- a/opengl/tests/gl2_copyTexImage/Android.bp
+++ b/opengl/tests/gl2_copyTexImage/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-gl2_copyTexImage",
diff --git a/opengl/tests/gl2_java/Android.bp b/opengl/tests/gl2_java/Android.bp
index a8e5d7d..a33075e 100644
--- a/opengl/tests/gl2_java/Android.bp
+++ b/opengl/tests/gl2_java/Android.bp
@@ -1,6 +1,15 @@
//########################################################################
// OpenGL ES 2.0 Java sample
//########################################################################
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_app {
name: "GL2Java",
srcs: ["**/*.java"],
diff --git a/opengl/tests/gl2_jni/Android.bp b/opengl/tests/gl2_jni/Android.bp
index 8d4323f..79773cb 100644
--- a/opengl/tests/gl2_jni/Android.bp
+++ b/opengl/tests/gl2_jni/Android.bp
@@ -3,6 +3,15 @@
// This makefile builds both an activity and a shared library.
//########################################################################
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_app {
name: "GL2JNI",
srcs: ["**/*.java"],
diff --git a/opengl/tests/gl2_yuvtex/Android.bp b/opengl/tests/gl2_yuvtex/Android.bp
index b64d94d..fadf0e8 100644
--- a/opengl/tests/gl2_yuvtex/Android.bp
+++ b/opengl/tests/gl2_yuvtex/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-gl2_yuvtex",
diff --git a/opengl/tests/gl_basic/Android.bp b/opengl/tests/gl_basic/Android.bp
index 5eed17e..f777401 100644
--- a/opengl/tests/gl_basic/Android.bp
+++ b/opengl/tests/gl_basic/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-gl_basic",
diff --git a/opengl/tests/gl_jni/Android.bp b/opengl/tests/gl_jni/Android.bp
index 0cb129a..dc46483 100644
--- a/opengl/tests/gl_jni/Android.bp
+++ b/opengl/tests/gl_jni/Android.bp
@@ -4,6 +4,15 @@
//########################################################################
// Build activity
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_app {
name: "GLJNI",
srcs: ["**/*.java"],
diff --git a/opengl/tests/gl_perf/Android.bp b/opengl/tests/gl_perf/Android.bp
index 25a317c..ca0f7e8 100644
--- a/opengl/tests/gl_perf/Android.bp
+++ b/opengl/tests/gl_perf/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-gl2_perf",
diff --git a/opengl/tests/gl_perfapp/Android.bp b/opengl/tests/gl_perfapp/Android.bp
index 66afb6a..2f62346 100644
--- a/opengl/tests/gl_perfapp/Android.bp
+++ b/opengl/tests/gl_perfapp/Android.bp
@@ -2,6 +2,15 @@
// OpenGL ES Perf App
// This makefile builds both an activity and a shared library.
//########################################################################
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_app {
name: "GLPerf",
srcs: ["**/*.java"],
diff --git a/opengl/tests/gl_yuvtex/Android.bp b/opengl/tests/gl_yuvtex/Android.bp
index 9b4924a..7844186 100644
--- a/opengl/tests/gl_yuvtex/Android.bp
+++ b/opengl/tests/gl_yuvtex/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-gl_yuvtex",
diff --git a/opengl/tests/gldual/Android.bp b/opengl/tests/gldual/Android.bp
index 1006d44..3d6e677 100644
--- a/opengl/tests/gldual/Android.bp
+++ b/opengl/tests/gldual/Android.bp
@@ -4,6 +4,15 @@
//########################################################################
// Build activity
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_app {
name: "GLDual",
srcs: ["**/*.java"],
diff --git a/opengl/tests/gralloc/Android.bp b/opengl/tests/gralloc/Android.bp
index 33c3dba..5fb4556 100644
--- a/opengl/tests/gralloc/Android.bp
+++ b/opengl/tests/gralloc/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-gralloc",
diff --git a/opengl/tests/hwc/Android.bp b/opengl/tests/hwc/Android.bp
index 55f058f..719eb11 100644
--- a/opengl/tests/hwc/Android.bp
+++ b/opengl/tests/hwc/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "hwc_tests_defaults",
diff --git a/opengl/tests/lib/Android.bp b/opengl/tests/lib/Android.bp
index 2f6095d..05c9397 100644
--- a/opengl/tests/lib/Android.bp
+++ b/opengl/tests/lib/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "libglTest",
diff --git a/opengl/tests/lighting1709/Android.bp b/opengl/tests/lighting1709/Android.bp
index e734dd1..79daa26 100644
--- a/opengl/tests/lighting1709/Android.bp
+++ b/opengl/tests/lighting1709/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_test {
name: "LightingTest",
srcs: ["**/*.java"],
diff --git a/opengl/tests/linetex/Android.bp b/opengl/tests/linetex/Android.bp
index dbc2cdb..61976e5 100644
--- a/opengl/tests/linetex/Android.bp
+++ b/opengl/tests/linetex/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "test-opengl-linetex",
srcs: ["linetex.cpp"],
diff --git a/opengl/tests/swapinterval/Android.bp b/opengl/tests/swapinterval/Android.bp
index eed4dff..a76f4cf 100644
--- a/opengl/tests/swapinterval/Android.bp
+++ b/opengl/tests/swapinterval/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "test-opengl-swapinterval",
srcs: ["swapinterval.cpp"],
diff --git a/opengl/tests/testFramerate/Android.bp b/opengl/tests/testFramerate/Android.bp
index 5aa83b0..4334d88 100644
--- a/opengl/tests/testFramerate/Android.bp
+++ b/opengl/tests/testFramerate/Android.bp
@@ -2,6 +2,15 @@
// Test framerate and look for hiccups
//########################################################################
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_app {
name: "TestFramerate",
srcs: ["**/*.java"],
diff --git a/opengl/tests/testLatency/Android.bp b/opengl/tests/testLatency/Android.bp
index c516dc3..473cb42 100644
--- a/opengl/tests/testLatency/Android.bp
+++ b/opengl/tests/testLatency/Android.bp
@@ -1,6 +1,15 @@
//########################################################################
// Test end-to-end latency.
//########################################################################
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_app {
name: "TestLatency",
sdk_version: "8",
diff --git a/opengl/tests/testPauseResume/Android.bp b/opengl/tests/testPauseResume/Android.bp
index 810e895..8171e1f 100644
--- a/opengl/tests/testPauseResume/Android.bp
+++ b/opengl/tests/testPauseResume/Android.bp
@@ -1,4 +1,13 @@
// OpenGL ES JNI sample
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_app {
name: "TestEGL",
srcs: ["**/*.java"],
diff --git a/opengl/tests/testViewport/Android.bp b/opengl/tests/testViewport/Android.bp
index 629b573..13ce3ad 100644
--- a/opengl/tests/testViewport/Android.bp
+++ b/opengl/tests/testViewport/Android.bp
@@ -2,6 +2,15 @@
// OpenGL ES JNI sample
// This makefile builds both an activity and a shared library.
//########################################################################
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_app {
name: "TestViewport",
srcs: ["**/*.java"],
diff --git a/opengl/tests/textures/Android.bp b/opengl/tests/textures/Android.bp
index 84adda2..f113ff7 100644
--- a/opengl/tests/textures/Android.bp
+++ b/opengl/tests/textures/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "test-opengl-textures",
srcs: ["textures.cpp"],
diff --git a/opengl/tests/tritex/Android.bp b/opengl/tests/tritex/Android.bp
index 390397b..759582c 100644
--- a/opengl/tests/tritex/Android.bp
+++ b/opengl/tests/tritex/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "test-opengl-tritex",
srcs: ["tritex.cpp"],
diff --git a/services/audiomanager/Android.bp b/services/audiomanager/Android.bp
index 12ad47e..e6fb2c3 100644
--- a/services/audiomanager/Android.bp
+++ b/services/audiomanager/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libaudiomanager",
diff --git a/services/automotive/display/Android.bp b/services/automotive/display/Android.bp
index c3da216..72bd292 100644
--- a/services/automotive/display/Android.bp
+++ b/services/automotive/display/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "android.frameworks.automotive.display@1.0-service",
defaults: ["hidl_defaults"],
diff --git a/services/batteryservice/Android.bp b/services/batteryservice/Android.bp
index 66ee8ff..1e37991 100644
--- a/services/batteryservice/Android.bp
+++ b/services/batteryservice/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "libbatteryservice_headers",
vendor_available: true,
diff --git a/services/displayservice/Android.bp b/services/displayservice/Android.bp
index 4d2d873..8681784 100644
--- a/services/displayservice/Android.bp
+++ b/services/displayservice/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libdisplayservicehidl",
diff --git a/services/gpuservice/Android.bp b/services/gpuservice/Android.bp
index 9a9bca1..b9b6a19 100644
--- a/services/gpuservice/Android.bp
+++ b/services/gpuservice/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "gpuservice_defaults",
cflags: [
diff --git a/services/gpuservice/OWNERS b/services/gpuservice/OWNERS
index 5d02839..ac300d0 100644
--- a/services/gpuservice/OWNERS
+++ b/services/gpuservice/OWNERS
@@ -1,3 +1,2 @@
chrisforbes@google.com
lpy@google.com
-zzyiwei@google.com
diff --git a/services/gpuservice/bpfprogs/Android.bp b/services/gpuservice/bpfprogs/Android.bp
index b875814..9842ed7 100644
--- a/services/gpuservice/bpfprogs/Android.bp
+++ b/services/gpuservice/bpfprogs/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
bpf {
name: "gpu_mem.o",
srcs: ["gpu_mem.c"],
diff --git a/services/gpuservice/gpumem/Android.bp b/services/gpuservice/gpumem/Android.bp
index b2230b6..830e53d 100644
--- a/services/gpuservice/gpumem/Android.bp
+++ b/services/gpuservice/gpumem/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libgpumem",
srcs: [
diff --git a/services/gpuservice/gpustats/Android.bp b/services/gpuservice/gpustats/Android.bp
index f52602a..54291ad 100644
--- a/services/gpuservice/gpustats/Android.bp
+++ b/services/gpuservice/gpustats/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libgfxstats",
srcs: [
diff --git a/services/gpuservice/tests/unittests/Android.bp b/services/gpuservice/tests/unittests/Android.bp
index 9606daa..6d87c45 100644
--- a/services/gpuservice/tests/unittests/Android.bp
+++ b/services/gpuservice/tests/unittests/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "gpuservice_unittest",
test_suites: ["device-tests"],
diff --git a/services/gpuservice/tracing/Android.bp b/services/gpuservice/tracing/Android.bp
index 919fed3..a1bc1ed 100644
--- a/services/gpuservice/tracing/Android.bp
+++ b/services/gpuservice/tracing/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libgpumemtracer",
srcs: [
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index f67c9d0..8610737 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -13,6 +13,15 @@
// limitations under the License.
// Default flags to be used throughout all libraries in inputflinger.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "inputflinger_defaults",
cflags: [
diff --git a/services/inputflinger/benchmarks/Android.bp b/services/inputflinger/benchmarks/Android.bp
index 066a816..67d85d6 100644
--- a/services/inputflinger/benchmarks/Android.bp
+++ b/services/inputflinger/benchmarks/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_benchmark {
name: "inputflinger_benchmarks",
srcs: [
diff --git a/services/inputflinger/dispatcher/Android.bp b/services/inputflinger/dispatcher/Android.bp
index 390c6b8..40c2409 100644
--- a/services/inputflinger/dispatcher/Android.bp
+++ b/services/inputflinger/dispatcher/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "libinputdispatcher_headers",
export_include_dirs: [
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 2517060..6ea64b4 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -58,6 +58,7 @@
#include <sstream>
#include <android-base/chrono_utils.h>
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <binder/Binder.h>
#include <input/InputDevice.h>
@@ -72,13 +73,14 @@
#define INDENT3 " "
#define INDENT4 " "
+using android::base::HwTimeoutMultiplier;
using android::base::StringPrintf;
namespace android::inputdispatcher {
// Default input dispatching timeout if there is no focused application or paused window
// from which to determine an appropriate dispatching timeout.
-constexpr std::chrono::nanoseconds DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5s;
+const std::chrono::nanoseconds DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5s * HwTimeoutMultiplier();
// Amount of time to allow for all pending events to be processed when an app switch
// key is on the way. This is used to preempt input dispatch and drop input events
diff --git a/services/inputflinger/host/Android.bp b/services/inputflinger/host/Android.bp
index b56f356..f0151c9 100644
--- a/services/inputflinger/host/Android.bp
+++ b/services/inputflinger/host/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libinputflingerhost",
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index 83a610f..dadbd0e 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "libinputreader_headers",
export_include_dirs: [
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 4b19e5e..3347ba6 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -84,12 +84,13 @@
bumpGeneration();
}
-void InputDevice::dump(std::string& dump) {
+void InputDevice::dump(std::string& dump, const std::string& eventHubDevStr) {
InputDeviceInfo deviceInfo;
getDeviceInfo(&deviceInfo);
dump += StringPrintf(INDENT "Device %d: %s\n", deviceInfo.getId(),
deviceInfo.getDisplayName().c_str());
+ dump += StringPrintf(INDENT "%s", eventHubDevStr.c_str());
dump += StringPrintf(INDENT2 "Generation: %d\n", mGeneration);
dump += StringPrintf(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
dump += StringPrintf(INDENT2 "AssociatedDisplayPort: ");
@@ -101,6 +102,7 @@
dump += StringPrintf(INDENT2 "HasMic: %s\n", toString(mHasMic));
dump += StringPrintf(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
dump += StringPrintf(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
+ dump += StringPrintf(INDENT2 "ControllerNum: %d\n", deviceInfo.getControllerNumber());
const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
if (!ranges.empty()) {
@@ -200,6 +202,8 @@
// insert the context into the devices set
mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
+ // Must change generation to flag this device as changed
+ bumpGeneration();
}
void InputDevice::removeEventHubDevice(int32_t eventHubId) {
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 06e3743..dff830c 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -206,6 +206,14 @@
}
mDevices.emplace(eventHubId, device);
+ // Add device to device to EventHub ids map.
+ const auto mapIt = mDeviceToEventHubIdsMap.find(device);
+ if (mapIt == mDeviceToEventHubIdsMap.end()) {
+ std::vector<int32_t> ids = {eventHubId};
+ mDeviceToEventHubIdsMap.emplace(device, ids);
+ } else {
+ mapIt->second.push_back(eventHubId);
+ }
bumpGenerationLocked();
if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
@@ -222,6 +230,17 @@
std::shared_ptr<InputDevice> device = std::move(deviceIt->second);
mDevices.erase(deviceIt);
+ // Erase device from device to EventHub ids map.
+ auto mapIt = mDeviceToEventHubIdsMap.find(device);
+ if (mapIt != mDeviceToEventHubIdsMap.end()) {
+ std::vector<int32_t>& eventHubIds = mapIt->second;
+ eventHubIds.erase(std::remove_if(eventHubIds.begin(), eventHubIds.end(),
+ [eventHubId](int32_t eId) { return eId == eventHubId; }),
+ eventHubIds.end());
+ if (eventHubIds.size() == 0) {
+ mDeviceToEventHubIdsMap.erase(mapIt);
+ }
+ }
bumpGenerationLocked();
if (device->isIgnored()) {
@@ -450,8 +469,7 @@
void InputReader::getInputDevicesLocked(std::vector<InputDeviceInfo>& outInputDevices) {
outInputDevices.clear();
- for (auto& devicePair : mDevices) {
- std::shared_ptr<InputDevice>& device = devicePair.second;
+ for (const auto& [device, eventHubIds] : mDeviceToEventHubIdsMap) {
if (!device->isIgnored()) {
InputDeviceInfo info;
device->getDeviceInfo(&info);
@@ -622,11 +640,17 @@
mEventHub->dump(dump);
dump += "\n";
- dump += "Input Reader State:\n";
+ dump += StringPrintf("Input Reader State (Nums of device: %zu):\n",
+ mDeviceToEventHubIdsMap.size());
- for (const auto& devicePair : mDevices) {
- const std::shared_ptr<InputDevice>& device = devicePair.second;
- device->dump(dump);
+ for (const auto& devicePair : mDeviceToEventHubIdsMap) {
+ const std::shared_ptr<InputDevice>& device = devicePair.first;
+ std::string eventHubDevStr = INDENT "EventHub Devices: [ ";
+ for (const auto& eId : devicePair.second) {
+ eventHubDevStr += StringPrintf("%d ", eId);
+ }
+ eventHubDevStr += "] \n";
+ device->dump(dump, eventHubDevStr);
}
dump += INDENT "Configuration:\n";
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index 7c17102..d2bb4f4 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -66,7 +66,7 @@
bool isEnabled();
void setEnabled(bool enabled, nsecs_t when);
- void dump(std::string& dump);
+ void dump(std::string& dump, const std::string& eventHubDevStr);
void addEventHubDevice(int32_t eventHubId, bool populateMappers = true);
void removeEventHubDevice(int32_t eventHubId);
void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 108b9c2..2773f70 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -143,6 +143,11 @@
// to lookup the input device instance from the EventHub device id.
std::unordered_map<int32_t /*eventHubId*/, std::shared_ptr<InputDevice>> mDevices;
+ // An input device contains one or more eventHubId, this map provides a way to lookup the
+ // EventHubIds contained in the input device from the input device instance.
+ std::unordered_map<std::shared_ptr<InputDevice>, std::vector<int32_t> /*eventHubId*/>
+ mDeviceToEventHubIdsMap;
+
// low-level input event decoding and device management
void processEventsLocked(const RawEvent* rawEvents, size_t count);
diff --git a/services/inputflinger/reporter/Android.bp b/services/inputflinger/reporter/Android.bp
index fbc51da..7430731 100644
--- a/services/inputflinger/reporter/Android.bp
+++ b/services/inputflinger/reporter/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "libinputreporter_headers",
export_include_dirs: ["."],
@@ -46,4 +55,3 @@
"libinputreporter_headers",
],
}
-
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index a0d2f4f..86ed60d 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "inputflinger_tests",
defaults: [
diff --git a/services/inputflinger/tests/fuzzers/Android.bp b/services/inputflinger/tests/fuzzers/Android.bp
new file mode 100644
index 0000000..2a90a08
--- /dev/null
+++ b/services/inputflinger/tests/fuzzers/Android.bp
@@ -0,0 +1,121 @@
+//
+// 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.
+//
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
+cc_defaults {
+ name: "inputflinger_fuzz_defaults",
+ defaults: [
+ "inputflinger_defaults",
+ ],
+ include_dirs: [
+ "frameworks/native/services/inputflinger",
+ ],
+ shared_libs: [
+ "android.hardware.input.classifier@1.0",
+ "libbase",
+ "libbinder",
+ "libcutils",
+ "liblog",
+ "libutils",
+ "libui",
+ "libinput",
+ "libinputflinger",
+ "libinputreader",
+ "libinputflinger_base",
+ "libstatslog",
+ ],
+ header_libs: [
+ "libinputreader_headers",
+ ],
+}
+
+cc_fuzz {
+ name: "inputflinger_cursor_input_fuzzer",
+ defaults: [
+ "inputflinger_fuzz_defaults",
+ ],
+ srcs: [
+ "CursorInputFuzzer.cpp",
+ ],
+}
+
+cc_fuzz {
+ name: "inputflinger_keyboard_input_fuzzer",
+ defaults: [
+ "inputflinger_fuzz_defaults",
+ ],
+ srcs: [
+ "KeyboardInputFuzzer.cpp",
+ ],
+}
+
+cc_fuzz {
+ name: "inputflinger_multitouch_input_fuzzer",
+ defaults: [
+ "inputflinger_fuzz_defaults",
+ ],
+ srcs: [
+ "MultiTouchInputFuzzer.cpp",
+ ],
+}
+
+cc_fuzz {
+ name: "inputflinger_switch_input_fuzzer",
+ defaults: [
+ "inputflinger_fuzz_defaults",
+ ],
+ srcs: [
+ "SwitchInputFuzzer.cpp",
+ ],
+}
+
+cc_fuzz {
+ name: "inputflinger_input_reader_device_fuzzer",
+ defaults: [
+ "inputflinger_fuzz_defaults",
+ ],
+ srcs: [
+ "InputReaderDeviceFuzzer.cpp",
+ ],
+}
+
+cc_fuzz {
+ name: "inputflinger_blocking_queue_fuzzer",
+ defaults: [
+ "inputflinger_fuzz_defaults",
+ ],
+ srcs: [
+ "BlockingQueueFuzzer.cpp",
+ ],
+}
+
+cc_fuzz {
+ name: "inputflinger_input_classifier_fuzzer",
+ defaults: [
+ "inputflinger_fuzz_defaults",
+ ],
+ srcs: [
+ "InputClassifierFuzzer.cpp",
+ ],
+}
diff --git a/services/inputflinger/tests/fuzzers/BlockingQueueFuzzer.cpp b/services/inputflinger/tests/fuzzers/BlockingQueueFuzzer.cpp
new file mode 100644
index 0000000..6a136cf
--- /dev/null
+++ b/services/inputflinger/tests/fuzzers/BlockingQueueFuzzer.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright 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.
+ */
+
+#include <fuzzer/FuzzedDataProvider.h>
+#include <thread>
+#include "BlockingQueue.h"
+
+// Chosen to be a number large enough for variation in fuzzer runs, but not consume too much memory.
+static constexpr size_t MAX_CAPACITY = 1024;
+
+namespace android {
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp(data, size);
+ size_t capacity = fdp.ConsumeIntegralInRange<size_t>(1, MAX_CAPACITY);
+ size_t filled = 0;
+ BlockingQueue<int32_t> queue(capacity);
+
+ while (fdp.remaining_bytes() > 0) {
+ fdp.PickValueInArray<std::function<void()>>({
+ [&]() -> void {
+ size_t numPushes = fdp.ConsumeIntegralInRange<size_t>(0, capacity + 1);
+ for (size_t i = 0; i < numPushes; i++) {
+ queue.push(fdp.ConsumeIntegral<int32_t>());
+ }
+ filled = std::min(capacity, filled + numPushes);
+ },
+ [&]() -> void {
+ // Pops blocks if it is empty, so only pop up to num elements inserted.
+ size_t numPops = fdp.ConsumeIntegralInRange<size_t>(0, filled);
+ for (size_t i = 0; i < numPops; i++) {
+ queue.pop();
+ }
+ filled > numPops ? filled -= numPops : filled = 0;
+ },
+ [&]() -> void {
+ queue.clear();
+ filled = 0;
+ },
+ [&]() -> void {
+ int32_t eraseElement = fdp.ConsumeIntegral<int32_t>();
+ queue.erase([&](int32_t element) {
+ if (element == eraseElement) {
+ filled--;
+ return true;
+ }
+ return false;
+ });
+ },
+ })();
+ }
+
+ return 0;
+}
+
+} // namespace android
diff --git a/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp
new file mode 100644
index 0000000..8aa7434
--- /dev/null
+++ b/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright 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.
+ */
+
+#include <CursorInputMapper.h>
+#include <FuzzContainer.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+namespace android {
+
+void addProperty(FuzzContainer& fuzzer, std::shared_ptr<FuzzedDataProvider> fdp) {
+ // Pick a random property to set for the mapper to have set.
+ fdp->PickValueInArray<std::function<void()>>(
+ {[&]() -> void { fuzzer.addProperty(String8("cursor.mode"), String8("pointer")); },
+ [&]() -> void { fuzzer.addProperty(String8("cursor.mode"), String8("navigation")); },
+ [&]() -> void {
+ fuzzer.addProperty(String8("cursor.mode"),
+ String8(fdp->ConsumeRandomLengthString(100).data()));
+ },
+ [&]() -> void {
+ fuzzer.addProperty(String8("cursor.orientationAware"),
+ String8(fdp->ConsumeRandomLengthString(100).data()));
+ }})();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) {
+ std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size);
+ FuzzContainer fuzzer = FuzzContainer(fdp);
+
+ CursorInputMapper& mapper = fuzzer.getMapper<CursorInputMapper>();
+ auto policyConfig = fuzzer.getPolicyConfig();
+
+ // Loop through mapper operations until randomness is exhausted.
+ while (fdp->remaining_bytes() > 0) {
+ fdp->PickValueInArray<std::function<void()>>({
+ [&]() -> void { addProperty(fuzzer, fdp); },
+ [&]() -> void {
+ std::string dump;
+ mapper.dump(dump);
+ },
+ [&]() -> void { mapper.getSources(); },
+ [&]() -> void {
+ mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig,
+ fdp->ConsumeIntegral<int32_t>());
+ },
+ [&]() -> void {
+ // Need to reconfigure with 0 or you risk a NPE.
+ mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0);
+ InputDeviceInfo info;
+ mapper.populateDeviceInfo(&info);
+ },
+ [&]() -> void {
+ // Need to reconfigure with 0 or you risk a NPE.
+ mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0);
+ RawEvent rawEvent{fdp->ConsumeIntegral<nsecs_t>(),
+ fdp->ConsumeIntegral<int32_t>(),
+ fdp->ConsumeIntegral<int32_t>(),
+ fdp->ConsumeIntegral<int32_t>(),
+ fdp->ConsumeIntegral<int32_t>()};
+ mapper.process(&rawEvent);
+ },
+ [&]() -> void { mapper.reset(fdp->ConsumeIntegral<nsecs_t>()); },
+ [&]() -> void {
+ mapper.getScanCodeState(fdp->ConsumeIntegral<uint32_t>(),
+ fdp->ConsumeIntegral<int32_t>());
+ },
+ [&]() -> void {
+ // Need to reconfigure with 0 or you risk a NPE.
+ mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0);
+ mapper.getAssociatedDisplayId();
+ },
+ })();
+ }
+
+ return 0;
+}
+
+} // namespace android
diff --git a/services/inputflinger/tests/fuzzers/FuzzContainer.h b/services/inputflinger/tests/fuzzers/FuzzContainer.h
new file mode 100644
index 0000000..84f0566
--- /dev/null
+++ b/services/inputflinger/tests/fuzzers/FuzzContainer.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 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 <InputDevice.h>
+#include <InputMapper.h>
+#include <InputReader.h>
+#include <MapperHelpers.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+namespace android {
+
+class FuzzContainer {
+ int32_t meventID;
+ std::shared_ptr<FuzzEventHub> mFuzzEventHub;
+ sp<FuzzInputReaderPolicy> mFuzzPolicy;
+ sp<FuzzInputListener> mFuzzListener;
+ std::unique_ptr<FuzzInputReaderContext> mFuzzContext;
+ std::unique_ptr<InputDevice> mFuzzDevice;
+ InputReaderConfiguration mPolicyConfig;
+ std::shared_ptr<FuzzedDataProvider> fdp;
+
+public:
+ FuzzContainer(std::shared_ptr<FuzzedDataProvider> fdp) : fdp(fdp) {
+ // Setup parameters.
+ std::string deviceName = fdp->ConsumeRandomLengthString(16);
+ std::string deviceLocation = fdp->ConsumeRandomLengthString(12);
+ int32_t deviceID = fdp->ConsumeIntegralInRange<int32_t>(0, 5);
+ int32_t deviceGeneration = fdp->ConsumeIntegralInRange<int32_t>(0, 5);
+ meventID = fdp->ConsumeIntegral<int32_t>();
+
+ // Create mocked objects.
+ mFuzzEventHub = std::make_shared<FuzzEventHub>(fdp);
+ mFuzzPolicy = new FuzzInputReaderPolicy(fdp);
+ mFuzzListener = new FuzzInputListener();
+ mFuzzContext = std::make_unique<FuzzInputReaderContext>(mFuzzEventHub, mFuzzPolicy,
+ mFuzzListener, fdp);
+
+ InputDeviceIdentifier identifier;
+ identifier.name = deviceName;
+ identifier.location = deviceLocation;
+ mFuzzDevice = std::make_unique<InputDevice>(mFuzzContext.get(), deviceID, deviceGeneration,
+ identifier);
+ mFuzzPolicy->getReaderConfiguration(&mPolicyConfig);
+ }
+
+ ~FuzzContainer() {}
+
+ void configureDevice() {
+ nsecs_t arbitraryTime = fdp->ConsumeIntegral<nsecs_t>();
+ mFuzzDevice->configure(arbitraryTime, &mPolicyConfig, 0);
+ mFuzzDevice->reset(arbitraryTime);
+ }
+
+ void addProperty(const String8& key, const String8& value) {
+ mFuzzEventHub->addProperty(key, value);
+ configureDevice();
+ }
+
+ InputReaderConfiguration& getPolicyConfig() { return mPolicyConfig; }
+
+ template <class T, typename... Args>
+ T& getMapper(Args... args) {
+ T& mapper = mFuzzDevice->addMapper<T>(fdp->ConsumeIntegral<int32_t>(), args...);
+ configureDevice();
+ return mapper;
+ }
+};
+
+} // namespace android
diff --git a/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp
new file mode 100644
index 0000000..7f91000
--- /dev/null
+++ b/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright 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.
+ */
+
+#include <MapperHelpers.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include "InputClassifier.h"
+#include "InputClassifierConverter.h"
+
+namespace android {
+
+static constexpr int32_t MAX_AXES = 64;
+
+// Used by two fuzz operations and a bit lengthy, so pulled out into a function.
+NotifyMotionArgs generateFuzzedMotionArgs(FuzzedDataProvider &fdp) {
+ // Create a basic motion event for testing
+ PointerProperties properties;
+ properties.id = 0;
+ properties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+ PointerCoords coords;
+ coords.clear();
+ for (int32_t i = 0; i < fdp.ConsumeIntegralInRange<int32_t>(0, MAX_AXES); i++) {
+ coords.setAxisValue(fdp.ConsumeIntegral<int32_t>(), fdp.ConsumeFloatingPoint<float>());
+ }
+
+ nsecs_t downTime = 2;
+ NotifyMotionArgs motionArgs(fdp.ConsumeIntegral<uint32_t>() /*sequenceNum*/,
+ downTime /*eventTime*/, fdp.ConsumeIntegral<int32_t>() /*deviceId*/,
+ AINPUT_SOURCE_ANY, ADISPLAY_ID_DEFAULT,
+ fdp.ConsumeIntegral<uint32_t>() /*policyFlags*/,
+ AMOTION_EVENT_ACTION_DOWN,
+ fdp.ConsumeIntegral<int32_t>() /*actionButton*/,
+ fdp.ConsumeIntegral<int32_t>() /*flags*/, AMETA_NONE,
+ fdp.ConsumeIntegral<int32_t>() /*buttonState*/,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
+ 1 /*pointerCount*/, &properties, &coords,
+ fdp.ConsumeFloatingPoint<float>() /*xPrecision*/,
+ fdp.ConsumeFloatingPoint<float>() /*yPrecision*/,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, downTime,
+ {} /*videoFrames*/);
+ return motionArgs;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp(data, size);
+
+ sp<FuzzInputListener> mFuzzListener = new FuzzInputListener();
+ sp<InputClassifierInterface> mClassifier = new InputClassifier(mFuzzListener);
+
+ while (fdp.remaining_bytes() > 0) {
+ fdp.PickValueInArray<std::function<void()>>({
+ [&]() -> void {
+ // SendToNextStage_NotifyConfigurationChangedArgs
+ NotifyConfigurationChangedArgs
+ args(fdp.ConsumeIntegral<uint32_t>() /*sequenceNum*/,
+ fdp.ConsumeIntegral<nsecs_t>() /*eventTime*/);
+ mClassifier->notifyConfigurationChanged(&args);
+ },
+ [&]() -> void {
+ // SendToNextStage_NotifyKeyArgs
+ NotifyKeyArgs keyArgs(fdp.ConsumeIntegral<uint32_t>() /*sequenceNum*/,
+ fdp.ConsumeIntegral<nsecs_t>() /*eventTime*/,
+ fdp.ConsumeIntegral<int32_t>() /*deviceId*/,
+ AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_DEFAULT,
+ fdp.ConsumeIntegral<uint32_t>() /*policyFlags*/,
+ AKEY_EVENT_ACTION_DOWN,
+ fdp.ConsumeIntegral<int32_t>() /*flags*/, AKEYCODE_HOME,
+ fdp.ConsumeIntegral<int32_t>() /*scanCode*/, AMETA_NONE,
+ fdp.ConsumeIntegral<nsecs_t>() /*downTime*/);
+
+ mClassifier->notifyKey(&keyArgs);
+ },
+ [&]() -> void {
+ // SendToNextStage_NotifyMotionArgs
+ NotifyMotionArgs motionArgs = generateFuzzedMotionArgs(fdp);
+ mClassifier->notifyMotion(&motionArgs);
+ },
+ [&]() -> void {
+ // SendToNextStage_NotifySwitchArgs
+ NotifySwitchArgs switchArgs(fdp.ConsumeIntegral<uint32_t>() /*sequenceNum*/,
+ fdp.ConsumeIntegral<nsecs_t>() /*eventTime*/,
+ fdp.ConsumeIntegral<uint32_t>() /*policyFlags*/,
+ fdp.ConsumeIntegral<uint32_t>() /*switchValues*/,
+ fdp.ConsumeIntegral<uint32_t>() /*switchMask*/);
+
+ mClassifier->notifySwitch(&switchArgs);
+ },
+ [&]() -> void {
+ // SendToNextStage_NotifyDeviceResetArgs
+ NotifyDeviceResetArgs resetArgs(fdp.ConsumeIntegral<uint32_t>() /*sequenceNum*/,
+ fdp.ConsumeIntegral<nsecs_t>() /*eventTime*/,
+ fdp.ConsumeIntegral<int32_t>() /*deviceId*/);
+
+ mClassifier->notifyDeviceReset(&resetArgs);
+ },
+ [&]() -> void {
+ // InputClassifierConverterTest
+ const NotifyMotionArgs motionArgs = generateFuzzedMotionArgs(fdp);
+ hardware::input::common::V1_0::MotionEvent motionEvent =
+ notifyMotionArgsToHalMotionEvent(motionArgs);
+ },
+ })();
+ }
+ return 0;
+}
+
+} // namespace android
diff --git a/services/inputflinger/tests/fuzzers/InputReaderDeviceFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputReaderDeviceFuzzer.cpp
new file mode 100644
index 0000000..9194891
--- /dev/null
+++ b/services/inputflinger/tests/fuzzers/InputReaderDeviceFuzzer.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright 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.
+ */
+
+#include <InputReader.h>
+#include <MapperHelpers.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <chrono>
+#include <thread>
+
+namespace android {
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) {
+ std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size);
+
+ sp<FuzzInputListener> fuzzListener = new FuzzInputListener();
+ sp<FuzzInputReaderPolicy> fuzzPolicy = new FuzzInputReaderPolicy(fdp);
+ std::shared_ptr<FuzzEventHub> fuzzEventHub = std::make_shared<FuzzEventHub>(fdp);
+ std::unique_ptr<InputReader> reader =
+ std::make_unique<InputReader>(fuzzEventHub, fuzzPolicy, fuzzListener);
+
+ fuzzEventHub->addEvents(fdp);
+ reader->start();
+
+ // Loop through mapper operations until randomness is exhausted.
+ while (fdp->remaining_bytes() > 0) {
+ fdp->PickValueInArray<std::function<void()>>({
+ [&]() -> void {
+ std::string dump;
+ reader->dump(dump);
+ },
+ [&]() -> void { reader->monitor(); },
+ [&]() -> void { fuzzEventHub->addEvents(fdp); },
+ [&]() -> void {
+ std::vector<InputDeviceInfo> inputDevices;
+ reader->getInputDevices(inputDevices);
+ },
+ [&]() -> void { reader->isInputDeviceEnabled(fdp->ConsumeIntegral<int32_t>()); },
+ [&]() -> void {
+ reader->getScanCodeState(fdp->ConsumeIntegral<int32_t>(),
+ fdp->ConsumeIntegral<uint32_t>(),
+ fdp->ConsumeIntegral<int32_t>());
+ },
+ [&]() -> void {
+ reader->getKeyCodeState(fdp->ConsumeIntegral<int32_t>(),
+ fdp->ConsumeIntegral<uint32_t>(),
+ fdp->ConsumeIntegral<int32_t>());
+ },
+ [&]() -> void {
+ reader->getSwitchState(fdp->ConsumeIntegral<int32_t>(),
+ fdp->ConsumeIntegral<uint32_t>(),
+ fdp->ConsumeIntegral<int32_t>());
+ },
+ [&]() -> void { reader->toggleCapsLockState(fdp->ConsumeIntegral<int32_t>()); },
+ [&]() -> void {
+ size_t count = fdp->ConsumeIntegralInRange<size_t>(1, 1024);
+ uint8_t* outFlags = new uint8_t[count];
+ reader->hasKeys(fdp->ConsumeIntegral<int32_t>(),
+ fdp->ConsumeIntegral<uint32_t>(), count, nullptr, outFlags);
+ delete[] outFlags;
+ },
+ [&]() -> void {
+ reader->requestRefreshConfiguration(fdp->ConsumeIntegral<uint32_t>());
+ },
+ [&]() -> void {
+ // 260 is slightly higher than the maximum intended size of 256.
+ size_t count = fdp->ConsumeIntegralInRange<size_t>(0, 260);
+ nsecs_t pattern[count];
+
+ for (size_t i = 0; i < count; i++) pattern[i] = fdp->ConsumeIntegral<nsecs_t>();
+
+ reader->vibrate(fdp->ConsumeIntegral<int32_t>(), pattern, count,
+ fdp->ConsumeIntegral<ssize_t>(),
+ fdp->ConsumeIntegral<int32_t>());
+ },
+ [&]() -> void {
+ reader->cancelVibrate(fdp->ConsumeIntegral<int32_t>(),
+ fdp->ConsumeIntegral<int32_t>());
+ },
+ [&]() -> void {
+ reader->canDispatchToDisplay(fdp->ConsumeIntegral<int32_t>(),
+ fdp->ConsumeIntegral<int32_t>());
+ },
+ })();
+ }
+
+ reader->stop();
+ return 0;
+}
+
+} // namespace android
diff --git a/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp
new file mode 100644
index 0000000..854e2fd
--- /dev/null
+++ b/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright 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.
+ */
+
+#include <FuzzContainer.h>
+#include <KeyboardInputMapper.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+namespace android {
+
+void addProperty(FuzzContainer& fuzzer, std::shared_ptr<FuzzedDataProvider> fdp) {
+ // Pick a random property to set for the mapper to have set.
+ fdp->PickValueInArray<std::function<void()>>(
+ {[&]() -> void {
+ fuzzer.addProperty(String8("keyboard.orientationAware"), String8("1"));
+ },
+ [&]() -> void {
+ fuzzer.addProperty(String8("keyboard.orientationAware"),
+ String8(fdp->ConsumeRandomLengthString(100).data()));
+ },
+ [&]() -> void {
+ fuzzer.addProperty(String8("keyboard.doNotWakeByDefault"),
+ String8(fdp->ConsumeRandomLengthString(100).data()));
+ },
+ [&]() -> void {
+ fuzzer.addProperty(String8("keyboard.handlesKeyRepeat"),
+ String8(fdp->ConsumeRandomLengthString(100).data()));
+ }})();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) {
+ std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size);
+ FuzzContainer fuzzer = FuzzContainer(fdp);
+
+ KeyboardInputMapper& mapper =
+ fuzzer.getMapper<KeyboardInputMapper>(fdp->ConsumeIntegral<uint32_t>(),
+ fdp->ConsumeIntegral<int32_t>());
+ auto policyConfig = fuzzer.getPolicyConfig();
+
+ // Loop through mapper operations until randomness is exhausted.
+ while (fdp->remaining_bytes() > 0) {
+ fdp->PickValueInArray<std::function<void()>>({
+ [&]() -> void { addProperty(fuzzer, fdp); },
+ [&]() -> void {
+ std::string dump;
+ mapper.dump(dump);
+ },
+ [&]() -> void {
+ InputDeviceInfo info;
+ mapper.populateDeviceInfo(&info);
+ },
+ [&]() -> void { mapper.getSources(); },
+ [&]() -> void {
+ mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig,
+ fdp->ConsumeIntegral<uint32_t>());
+ },
+ [&]() -> void { mapper.reset(fdp->ConsumeIntegral<nsecs_t>()); },
+ [&]() -> void {
+ RawEvent rawEvent{fdp->ConsumeIntegral<nsecs_t>(),
+ fdp->ConsumeIntegral<int32_t>(),
+ fdp->ConsumeIntegral<int32_t>(),
+ fdp->ConsumeIntegral<int32_t>(),
+ fdp->ConsumeIntegral<int32_t>()};
+ mapper.process(&rawEvent);
+ },
+ [&]() -> void {
+ mapper.getKeyCodeState(fdp->ConsumeIntegral<uint32_t>(),
+ fdp->ConsumeIntegral<int32_t>());
+ },
+ [&]() -> void {
+ mapper.getScanCodeState(fdp->ConsumeIntegral<uint32_t>(),
+ fdp->ConsumeIntegral<int32_t>());
+ },
+ [&]() -> void {
+ mapper.markSupportedKeyCodes(fdp->ConsumeIntegral<uint32_t>(),
+ fdp->ConsumeIntegral<size_t>(), nullptr, nullptr);
+ },
+ [&]() -> void { mapper.getMetaState(); },
+ [&]() -> void { mapper.updateMetaState(fdp->ConsumeIntegral<int32_t>()); },
+ [&]() -> void { mapper.getAssociatedDisplayId(); },
+ })();
+ }
+
+ return 0;
+}
+
+} // namespace android
diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h
new file mode 100644
index 0000000..edfb68d
--- /dev/null
+++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright 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 <InputDevice.h>
+#include <InputMapper.h>
+#include <InputReader.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+namespace android {
+
+class FuzzEventHub : public EventHubInterface {
+ InputDeviceIdentifier mIdentifier;
+ std::vector<TouchVideoFrame> mVideoFrames;
+ PropertyMap mFuzzConfig;
+ std::mutex mEventLock;
+ size_t mCount = 0;
+ RawEvent mBuf[256];
+ std::shared_ptr<FuzzedDataProvider> fdp;
+
+public:
+ FuzzEventHub(std::shared_ptr<FuzzedDataProvider> fdp) : fdp(fdp) {}
+ ~FuzzEventHub() {}
+ void addProperty(const String8& key, const String8 value) {
+ mFuzzConfig.addProperty(key, value);
+ }
+ void addEvents(std::shared_ptr<FuzzedDataProvider> fdp) {
+ std::lock_guard<std::mutex> guard(mEventLock);
+ mCount = fdp->ConsumeIntegralInRange<size_t>(0, 256);
+
+ for (size_t i = 0; i < mCount; i++)
+ mBuf[i] = {fdp->ConsumeIntegral<nsecs_t>(), fdp->ConsumeIntegral<int32_t>(),
+ fdp->ConsumeIntegral<int32_t>(), fdp->ConsumeIntegral<int32_t>(),
+ fdp->ConsumeIntegral<int32_t>()};
+ }
+ uint32_t getDeviceClasses(int32_t deviceId) const override {
+ return fdp->ConsumeIntegral<uint32_t>();
+ }
+ InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const override {
+ return mIdentifier;
+ }
+ int32_t getDeviceControllerNumber(int32_t deviceId) const override {
+ return fdp->ConsumeIntegral<int32_t>();
+ }
+ void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const override {
+ *outConfiguration = mFuzzConfig;
+ }
+ status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
+ RawAbsoluteAxisInfo* outAxisInfo) const override {
+ return fdp->ConsumeIntegral<status_t>();
+ }
+ bool hasRelativeAxis(int32_t deviceId, int axis) const override { return fdp->ConsumeBool(); }
+ bool hasInputProperty(int32_t deviceId, int property) const override {
+ return fdp->ConsumeBool();
+ }
+ status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState,
+ int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const override {
+ return fdp->ConsumeIntegral<status_t>();
+ }
+ status_t mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const override {
+ return fdp->ConsumeIntegral<status_t>();
+ }
+ void setExcludedDevices(const std::vector<std::string>& devices) override {}
+ size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) override {
+ std::lock_guard<std::mutex> guard(mEventLock);
+ for (size_t i = 0; i < mCount; i++) buffer[i] = mBuf[i];
+
+ return mCount;
+ }
+ std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override { return mVideoFrames; }
+ int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override {
+ return fdp->ConsumeIntegral<int32_t>();
+ }
+ int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const override {
+ return fdp->ConsumeIntegral<int32_t>();
+ }
+ int32_t getSwitchState(int32_t deviceId, int32_t sw) const override {
+ return fdp->ConsumeIntegral<int32_t>();
+ }
+ status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
+ int32_t* outValue) const override {
+ return fdp->ConsumeIntegral<status_t>();
+ }
+ bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
+ uint8_t* outFlags) const override {
+ return fdp->ConsumeBool();
+ }
+ bool hasScanCode(int32_t deviceId, int32_t scanCode) const override {
+ return fdp->ConsumeBool();
+ }
+ bool hasLed(int32_t deviceId, int32_t led) const override { return fdp->ConsumeBool(); }
+ void setLedState(int32_t deviceId, int32_t led, bool on) override {}
+ void getVirtualKeyDefinitions(
+ int32_t deviceId, std::vector<VirtualKeyDefinition>& outVirtualKeys) const override {}
+ sp<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const override { return nullptr; }
+ bool setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map) override {
+ return fdp->ConsumeBool();
+ }
+ void vibrate(int32_t deviceId, nsecs_t duration) override {}
+ void cancelVibrate(int32_t deviceId) override {}
+ void requestReopenDevices() override {}
+ void wake() override {}
+ void dump(std::string& dump) override {}
+ void monitor() override {}
+ bool isDeviceEnabled(int32_t deviceId) override { return fdp->ConsumeBool(); }
+ status_t enableDevice(int32_t deviceId) override { return fdp->ConsumeIntegral<status_t>(); }
+ status_t disableDevice(int32_t deviceId) override { return fdp->ConsumeIntegral<status_t>(); }
+};
+
+class FuzzPointerController : public PointerControllerInterface {
+ std::shared_ptr<FuzzedDataProvider> fdp;
+
+public:
+ FuzzPointerController(std::shared_ptr<FuzzedDataProvider> fdp) : fdp(fdp) {}
+ ~FuzzPointerController() {}
+ bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const override {
+ return fdp->ConsumeBool();
+ }
+ void move(float deltaX, float deltaY) override {}
+ void setButtonState(int32_t buttonState) override {}
+ int32_t getButtonState() const override { return fdp->ConsumeIntegral<int32_t>(); }
+ void setPosition(float x, float y) override {}
+ void getPosition(float* outX, float* outY) const override {}
+ void fade(Transition transition) override {}
+ void unfade(Transition transition) override {}
+ void setPresentation(Presentation presentation) override {}
+ void setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
+ BitSet32 spotIdBits, int32_t displayId) override {}
+ void clearSpots() override {}
+ int32_t getDisplayId() const override { return fdp->ConsumeIntegral<int32_t>(); }
+ void setDisplayViewport(const DisplayViewport& displayViewport) override {}
+};
+
+class FuzzInputReaderPolicy : public InputReaderPolicyInterface {
+ TouchAffineTransformation mTransform;
+ std::shared_ptr<FuzzPointerController> mPointerController;
+ std::shared_ptr<FuzzedDataProvider> fdp;
+
+protected:
+ ~FuzzInputReaderPolicy() {}
+
+public:
+ FuzzInputReaderPolicy(std::shared_ptr<FuzzedDataProvider> fdp) : fdp(fdp) {
+ mPointerController = std::make_shared<FuzzPointerController>(fdp);
+ }
+ void getReaderConfiguration(InputReaderConfiguration* outConfig) override {}
+ std::shared_ptr<PointerControllerInterface> obtainPointerController(int32_t deviceId) override {
+ return mPointerController;
+ }
+ void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override {}
+ sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier& identifier) override {
+ return nullptr;
+ }
+ std::string getDeviceAlias(const InputDeviceIdentifier& identifier) {
+ return fdp->ConsumeRandomLengthString(32);
+ }
+ TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor,
+ int32_t surfaceRotation) override {
+ return mTransform;
+ }
+ void setTouchAffineTransformation(const TouchAffineTransformation t) { mTransform = t; }
+};
+
+class FuzzInputListener : public virtual InputListenerInterface {
+protected:
+ ~FuzzInputListener() {}
+
+public:
+ FuzzInputListener() {}
+ void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override {}
+ void notifyKey(const NotifyKeyArgs* args) override {}
+ void notifyMotion(const NotifyMotionArgs* args) override {}
+ void notifySwitch(const NotifySwitchArgs* args) override {}
+ void notifyDeviceReset(const NotifyDeviceResetArgs* args) override {}
+};
+
+class FuzzInputReaderContext : public InputReaderContext {
+ std::shared_ptr<EventHubInterface> mEventHub;
+ sp<InputReaderPolicyInterface> mPolicy;
+ sp<InputListenerInterface> mListener;
+ std::shared_ptr<FuzzedDataProvider> fdp;
+
+public:
+ FuzzInputReaderContext(std::shared_ptr<EventHubInterface> eventHub,
+ const sp<InputReaderPolicyInterface>& policy,
+ const sp<InputListenerInterface>& listener,
+ std::shared_ptr<FuzzedDataProvider> fdp)
+ : mEventHub(eventHub), mPolicy(policy), mListener(listener), fdp(fdp) {}
+ ~FuzzInputReaderContext() {}
+ void updateGlobalMetaState() override {}
+ int32_t getGlobalMetaState() { return fdp->ConsumeIntegral<int32_t>(); }
+ void disableVirtualKeysUntil(nsecs_t time) override {}
+ bool shouldDropVirtualKey(nsecs_t now, int32_t keyCode, int32_t scanCode) override {
+ return fdp->ConsumeBool();
+ }
+ void fadePointer() override {}
+ std::shared_ptr<PointerControllerInterface> getPointerController(int32_t deviceId) override {
+ return mPolicy->obtainPointerController(0);
+ }
+ void requestTimeoutAtTime(nsecs_t when) override {}
+ int32_t bumpGeneration() override { return fdp->ConsumeIntegral<int32_t>(); }
+ void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) override {}
+ void dispatchExternalStylusState(const StylusState& outState) override {}
+ InputReaderPolicyInterface* getPolicy() override { return mPolicy.get(); }
+ InputListenerInterface* getListener() override { return mListener.get(); }
+ EventHubInterface* getEventHub() override { return mEventHub.get(); }
+ int32_t getNextId() override { return fdp->ConsumeIntegral<int32_t>(); }
+};
+
+} // namespace android
diff --git a/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp
new file mode 100644
index 0000000..336ecb6
--- /dev/null
+++ b/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright 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.
+ */
+
+#include <FuzzContainer.h>
+#include <MultiTouchInputMapper.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+namespace android {
+
+void addProperty(FuzzContainer& fuzzer, std::shared_ptr<FuzzedDataProvider> fdp) {
+ // Pick a random property to set for the mapper to have set.
+ fdp->PickValueInArray<std::function<void()>>(
+ {[&]() -> void {
+ fuzzer.addProperty(String8("touch.deviceType"), String8("touchScreen"));
+ },
+ [&]() -> void {
+ fuzzer.addProperty(String8("touch.deviceType"),
+ String8(fdp->ConsumeRandomLengthString(8).data()));
+ },
+ [&]() -> void {
+ fuzzer.addProperty(String8("touch.size.scale"),
+ String8(fdp->ConsumeRandomLengthString(8).data()));
+ },
+ [&]() -> void {
+ fuzzer.addProperty(String8("touch.size.bias"),
+ String8(fdp->ConsumeRandomLengthString(8).data()));
+ },
+ [&]() -> void {
+ fuzzer.addProperty(String8("touch.size.isSummed"),
+ String8(fdp->ConsumeRandomLengthString(8).data()));
+ },
+ [&]() -> void {
+ fuzzer.addProperty(String8("touch.size.calibration"),
+ String8(fdp->ConsumeRandomLengthString(8).data()));
+ },
+ [&]() -> void {
+ fuzzer.addProperty(String8("touch.pressure.scale"),
+ String8(fdp->ConsumeRandomLengthString(8).data()));
+ },
+ [&]() -> void {
+ fuzzer.addProperty(String8("touch.size.calibration"),
+ fdp->ConsumeBool() ? String8("diameter") : String8("area"));
+ },
+ [&]() -> void {
+ fuzzer.addProperty(String8("touch.pressure.calibration"),
+ String8(fdp->ConsumeRandomLengthString(8).data()));
+ }})();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) {
+ std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size);
+ FuzzContainer fuzzer = FuzzContainer(fdp);
+
+ MultiTouchInputMapper& mapper = fuzzer.getMapper<MultiTouchInputMapper>();
+ auto policyConfig = fuzzer.getPolicyConfig();
+
+ // Loop through mapper operations until randomness is exhausted.
+ while (fdp->remaining_bytes() > 0) {
+ fdp->PickValueInArray<std::function<void()>>({
+ [&]() -> void { addProperty(fuzzer, fdp); },
+ [&]() -> void {
+ std::string dump;
+ mapper.dump(dump);
+ },
+ [&]() -> void {
+ InputDeviceInfo info;
+ mapper.populateDeviceInfo(&info);
+ },
+ [&]() -> void { mapper.getSources(); },
+ [&]() -> void {
+ mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig,
+ fdp->ConsumeIntegral<uint32_t>());
+ },
+ [&]() -> void { mapper.reset(fdp->ConsumeIntegral<nsecs_t>()); },
+ [&]() -> void {
+ RawEvent rawEvent{fdp->ConsumeIntegral<nsecs_t>(),
+ fdp->ConsumeIntegral<int32_t>(),
+ fdp->ConsumeIntegral<int32_t>(),
+ fdp->ConsumeIntegral<int32_t>(),
+ fdp->ConsumeIntegral<int32_t>()};
+ mapper.process(&rawEvent);
+ },
+ [&]() -> void {
+ mapper.getKeyCodeState(fdp->ConsumeIntegral<uint32_t>(),
+ fdp->ConsumeIntegral<int32_t>());
+ },
+ [&]() -> void {
+ mapper.getScanCodeState(fdp->ConsumeIntegral<uint32_t>(),
+ fdp->ConsumeIntegral<int32_t>());
+ },
+ [&]() -> void {
+ mapper.markSupportedKeyCodes(fdp->ConsumeIntegral<uint32_t>(),
+ fdp->ConsumeIntegral<size_t>(), nullptr, nullptr);
+ },
+ [&]() -> void { mapper.cancelTouch(fdp->ConsumeIntegral<nsecs_t>()); },
+ [&]() -> void { mapper.timeoutExpired(fdp->ConsumeIntegral<nsecs_t>()); },
+ [&]() -> void {
+ StylusState state{fdp->ConsumeIntegral<nsecs_t>(),
+ fdp->ConsumeFloatingPoint<float>(),
+ fdp->ConsumeIntegral<uint32_t>(),
+ fdp->ConsumeIntegral<int32_t>()};
+ mapper.updateExternalStylusState(state);
+ },
+ [&]() -> void { mapper.getAssociatedDisplayId(); },
+ })();
+ }
+
+ return 0;
+}
+
+} // namespace android
diff --git a/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp
new file mode 100644
index 0000000..ae7429c
--- /dev/null
+++ b/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright 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.
+ */
+
+#include <FuzzContainer.h>
+#include <SwitchInputMapper.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+namespace android {
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) {
+ std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size);
+ FuzzContainer fuzzer = FuzzContainer(fdp);
+
+ SwitchInputMapper& mapper = fuzzer.getMapper<SwitchInputMapper>();
+ auto policyConfig = fuzzer.getPolicyConfig();
+
+ // Loop through mapper operations until randomness is exhausted.
+ while (fdp->remaining_bytes() > 0) {
+ fdp->PickValueInArray<std::function<void()>>({
+ [&]() -> void {
+ std::string dump;
+ mapper.dump(dump);
+ },
+ [&]() -> void { mapper.getSources(); },
+ [&]() -> void {
+ RawEvent rawEvent{fdp->ConsumeIntegral<nsecs_t>(),
+ fdp->ConsumeIntegral<int32_t>(),
+ fdp->ConsumeIntegral<int32_t>(),
+ fdp->ConsumeIntegral<int32_t>(),
+ fdp->ConsumeIntegral<int32_t>()};
+ mapper.process(&rawEvent);
+ },
+ [&]() -> void {
+ mapper.getSwitchState(fdp->ConsumeIntegral<uint32_t>(),
+ fdp->ConsumeIntegral<int32_t>());
+ },
+ })();
+ }
+
+ return 0;
+}
+
+} // namespace android
diff --git a/services/powermanager/Android.bp b/services/powermanager/Android.bp
index b0d3e3b..19b6a0f 100644
--- a/services/powermanager/Android.bp
+++ b/services/powermanager/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libpowermanager",
diff --git a/services/schedulerservice/Android.bp b/services/schedulerservice/Android.bp
index 73802db..4ef72d0 100644
--- a/services/schedulerservice/Android.bp
+++ b/services/schedulerservice/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libschedulerservicehidl",
srcs: [
diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp
index 532a2e5..c769e97 100644
--- a/services/sensorservice/Android.bp
+++ b/services/sensorservice/Android.bp
@@ -1,6 +1,12 @@
-subdirs = [
- "hidl"
-]
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libsensorservice",
@@ -43,6 +49,7 @@
"libhardware_legacy",
"libutils",
"liblog",
+ "libbatterystats_aidl",
"libbinder",
"libsensor",
"libsensorprivacy",
diff --git a/services/sensorservice/BatteryService.h b/services/sensorservice/BatteryService.h
index 43a750c..09eb2c1 100644
--- a/services/sensorservice/BatteryService.h
+++ b/services/sensorservice/BatteryService.h
@@ -17,7 +17,7 @@
#include <stdint.h>
#include <sys/types.h>
-#include <binder/IBatteryStats.h>
+#include <batterystats/IBatteryStats.h>
#include <utils/Singleton.h>
namespace android {
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index e355594..4d4cac5 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -689,9 +689,9 @@
ALOGD_IF(DEBUG_CONNECTIONS, "enable index=%zd", info.batchParams.indexOfKey(ident));
if (isClientDisabledLocked(ident)) {
- ALOGE("SensorDevice::activate, isClientDisabledLocked(%p):true, handle:%d",
+ ALOGW("SensorDevice::activate, isClientDisabledLocked(%p):true, handle:%d",
ident, handle);
- return INVALID_OPERATION;
+ return NO_ERROR;
}
if (info.batchParams.indexOfKey(ident) >= 0) {
diff --git a/services/sensorservice/hidl/Android.bp b/services/sensorservice/hidl/Android.bp
index 0e1af59..9bafb3c 100644
--- a/services/sensorservice/hidl/Android.bp
+++ b/services/sensorservice/hidl/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libsensorservicehidl",
srcs: [
diff --git a/services/sensorservice/tests/Android.bp b/services/sensorservice/tests/Android.bp
index d33c0ca..ddc03a1 100644
--- a/services/sensorservice/tests/Android.bp
+++ b/services/sensorservice/tests/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "test-sensorservice",
srcs: ["sensorservicetest.cpp"],
diff --git a/services/stats/Android.bp b/services/stats/Android.bp
index 1ce0524..58e5993 100644
--- a/services/stats/Android.bp
+++ b/services/stats/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libstatshidl",
srcs: [
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 2734ee9..6b3bf8d 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "surfaceflinger_defaults",
cflags: [
@@ -32,7 +41,7 @@
"android.hardware.graphics.composer@2.4",
"android.hardware.power@1.0",
"android.hardware.power@1.3",
- "android.hardware.power-cpp",
+ "android.hardware.power-V1-cpp",
"libbase",
"libbinder",
"libbufferhubqueue",
@@ -103,6 +112,10 @@
thin: true,
},
whole_program_vtables: true, // Requires ThinLTO
+ pgo: {
+ sampling: true,
+ profile_file: "surfaceflinger/surfaceflinger.profdata",
+ },
// TODO(b/131771163): Fix broken fuzzer support with LTO.
sanitize: {
fuzzer: false,
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index df26a3d..5a24d51 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -211,8 +211,8 @@
layer.frameNumber = mCurrentFrameNumber;
layer.bufferId = mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getId() : 0;
- // TODO: we could be more subtle with isFixedSize()
- const bool useFiltering = targetSettings.needsFiltering || mNeedsFiltering || isFixedSize();
+ const bool useFiltering =
+ targetSettings.needsFiltering || mNeedsFiltering || bufferNeedsFiltering();
// Query the texture matrix given our current filtering mode.
float textureMatrix[16];
@@ -847,6 +847,36 @@
}
}
+bool BufferLayer::bufferNeedsFiltering() const {
+ // Layers that don't resize along with their buffer, don't need filtering.
+ if (!isFixedSize()) {
+ return false;
+ }
+
+ if (!mBufferInfo.mBuffer) {
+ return false;
+ }
+
+ uint32_t bufferWidth = mBufferInfo.mBuffer->width;
+ uint32_t bufferHeight = mBufferInfo.mBuffer->height;
+
+ // Undo any transformations on the buffer and return the result.
+ const State& s(getDrawingState());
+ if (s.transform & ui::Transform::ROT_90) {
+ std::swap(bufferWidth, bufferHeight);
+ }
+
+ if (s.transformToDisplayInverse) {
+ uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags();
+ if (invTransform & ui::Transform::ROT_90) {
+ std::swap(bufferWidth, bufferHeight);
+ }
+ }
+
+ const Rect layerSize{getBounds()};
+ return layerSize.width() != bufferWidth || layerSize.height() != bufferHeight;
+}
+
} // namespace android
#if defined(__gl_h_)
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 26bfb49..c7e8ad7 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -118,6 +118,10 @@
ui::Transform::RotationFlags getTransformHint() const override { return mTransformHint; }
+ // Returns true if the transformed buffer size does not match the layer size and we need
+ // to apply filtering.
+ bool bufferNeedsFiltering() const;
+
// -----------------------------------------------------------------------
// Functions that must be implemented by derived classes
// -----------------------------------------------------------------------
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 790f2ec..41dd7bf 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -760,6 +760,7 @@
static_cast<float>(s.active.transform.ty() + s.active.h)),
radius);
}
+
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index 4863297..3f63951 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "libcompositionengine_defaults",
defaults: ["surfaceflinger_defaults"],
diff --git a/services/surfaceflinger/OWNERS b/services/surfaceflinger/OWNERS
index f273725..43a6e55 100644
--- a/services/surfaceflinger/OWNERS
+++ b/services/surfaceflinger/OWNERS
@@ -1,8 +1,6 @@
adyabr@google.com
-akrulec@google.com
alecmouri@google.com
chaviw@google.com
lpy@google.com
racarr@google.com
-stoza@google.com
vishnun@google.com
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b15663e..4698ac6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -596,13 +596,6 @@
if (mWindowManager != 0) {
mWindowManager->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
}
- sp<IBinder> input(defaultServiceManager()->getService(
- String16("inputflinger")));
- if (input == nullptr) {
- ALOGE("Failed to link to input service");
- } else {
- mInputFlinger = interface_cast<IInputFlinger>(input);
- }
// stop boot animation
// formerly we would just kill the process, but we now ask it to exit so it
@@ -613,7 +606,15 @@
LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
- static_cast<void>(schedule([this] {
+ sp<IBinder> input(defaultServiceManager()->getService(String16("inputflinger")));
+
+ static_cast<void>(schedule([=] {
+ if (input == nullptr) {
+ ALOGE("Failed to link to input service");
+ } else {
+ mInputFlinger = interface_cast<IInputFlinger>(input);
+ }
+
readPersistentProperties();
mPowerAdvisor.onBootFinished();
mBootStage = BootStage::FINISHED;
diff --git a/services/surfaceflinger/TimeStats/Android.bp b/services/surfaceflinger/TimeStats/Android.bp
index 3901757..d6d0cb8 100644
--- a/services/surfaceflinger/TimeStats/Android.bp
+++ b/services/surfaceflinger/TimeStats/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libtimestats",
srcs: [
diff --git a/services/surfaceflinger/TimeStats/OWNERS b/services/surfaceflinger/TimeStats/OWNERS
index 1441f91..ded3ebb 100644
--- a/services/surfaceflinger/TimeStats/OWNERS
+++ b/services/surfaceflinger/TimeStats/OWNERS
@@ -1,2 +1 @@
alecmouri@google.com
-zzyiwei@google.com
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/Android.bp b/services/surfaceflinger/TimeStats/timestatsproto/Android.bp
index b937f41..4743098 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/Android.bp
+++ b/services/surfaceflinger/TimeStats/timestatsproto/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libtimestats_proto",
export_include_dirs: ["include"],
diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp
index d03cb7b..7f8da5a 100644
--- a/services/surfaceflinger/layerproto/Android.bp
+++ b/services/surfaceflinger/layerproto/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "liblayers_proto",
export_include_dirs: ["include"],
diff --git a/services/surfaceflinger/sysprop/Android.bp b/services/surfaceflinger/sysprop/Android.bp
index 7721d7d2..f579119 100644
--- a/services/surfaceflinger/sysprop/Android.bp
+++ b/services/surfaceflinger/sysprop/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
sysprop_library {
name: "SurfaceFlingerProperties",
srcs: ["*.sysprop"],
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index 1532855..15744a1 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "SurfaceFlinger_test",
defaults: ["surfaceflinger_defaults"],
@@ -44,7 +53,7 @@
"libtrace_proto",
],
shared_libs: [
- "android.hardware.graphics.common-unstable-ndk_platform",
+ "android.hardware.graphics.common-V2-ndk_platform",
"android.hardware.graphics.common@1.2",
"android.hardware.graphics.composer@2.1",
"libandroid",
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index 3535fbb..2551a19 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "sffakehwc_test",
defaults: ["surfaceflinger_defaults"],
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 1bbc3f8..e00c3da 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "libsurfaceflinger_unittest",
defaults: ["libsurfaceflinger_defaults"],
diff --git a/services/surfaceflinger/tests/vsync/Android.bp b/services/surfaceflinger/tests/vsync/Android.bp
index 6a89945..bae9796 100644
--- a/services/surfaceflinger/tests/vsync/Android.bp
+++ b/services/surfaceflinger/tests/vsync/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "test-vsync-events",
defaults: ["surfaceflinger_defaults"],
diff --git a/services/surfaceflinger/tests/waitforvsync/Android.bp b/services/surfaceflinger/tests/waitforvsync/Android.bp
index cb6d0fd..ffed4d7 100644
--- a/services/surfaceflinger/tests/waitforvsync/Android.bp
+++ b/services/surfaceflinger/tests/waitforvsync/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "test-waitforvsync",
cflags: [
diff --git a/services/utils/Android.bp b/services/utils/Android.bp
index f3d2bc9..81e1232 100644
--- a/services/utils/Android.bp
+++ b/services/utils/Android.bp
@@ -15,6 +15,15 @@
//
// Static library used in testing and executables
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "libserviceutils",
diff --git a/services/utils/tests/Android.bp b/services/utils/tests/Android.bp
index f21254c..54cf5b7 100644
--- a/services/utils/tests/Android.bp
+++ b/services/utils/tests/Android.bp
@@ -14,6 +14,15 @@
// Build unit tests.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "prioritydumper_test",
test_suites: ["device-tests"],
diff --git a/services/vr/Android.bp b/services/vr/Android.bp
index 80df479..980dcf4 100644
--- a/services/vr/Android.bp
+++ b/services/vr/Android.bp
@@ -1,3 +1,13 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
subdirs = [
"*",
]
diff --git a/services/vr/bufferhubd/Android.bp b/services/vr/bufferhubd/Android.bp
index 7097e7a..8523bb2 100644
--- a/services/vr/bufferhubd/Android.bp
+++ b/services/vr/bufferhubd/Android.bp
@@ -12,6 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
sharedLibraries = [
"libbase",
"libcutils",
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index 69754f3..eb24a22 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libvr_hwc-hal",
diff --git a/services/vr/hardware_composer/aidl/Android.bp b/services/vr/hardware_composer/aidl/Android.bp
index a1d5392..98afdec 100644
--- a/services/vr/hardware_composer/aidl/Android.bp
+++ b/services/vr/hardware_composer/aidl/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "libvr_hwc-binder",
srcs: [
diff --git a/services/vr/performanced/Android.bp b/services/vr/performanced/Android.bp
index 0ef8cc4..5eca88b 100644
--- a/services/vr/performanced/Android.bp
+++ b/services/vr/performanced/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-MIT
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "performanced_defaults",
static_libs: [
diff --git a/services/vr/virtual_touchpad/Android.bp b/services/vr/virtual_touchpad/Android.bp
index 9cf4905..f2ec5a4 100644
--- a/services/vr/virtual_touchpad/Android.bp
+++ b/services/vr/virtual_touchpad/Android.bp
@@ -2,6 +2,15 @@
// Touchpad implementation.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
src = [
"EvdevInjector.cpp",
"VirtualTouchpadEvdev.cpp",
diff --git a/vulkan/Android.bp b/vulkan/Android.bp
index 4934970..33599ea 100644
--- a/vulkan/Android.bp
+++ b/vulkan/Android.bp
@@ -14,6 +14,16 @@
// This module makes the Vulkan libhardware HAL headers available, for
// the loader and for HAL/driver implementations.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "hwvulkan_headers",
vendor_available: true,
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 1d29bab..67cd875 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -13,6 +13,15 @@
// limitations under the License.
// Headers module is in external/vulkan-headers/Android.bp.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
ndk_library {
name: "libvulkan",
symbol_file: "libvulkan.map.txt",
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index 5b9affd..9aaac5f 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -33,6 +33,7 @@
#include <unordered_set>
#include <utility>
+#include <android-base/properties.h>
#include <android-base/strings.h>
#include <cutils/properties.h>
#include <log/log.h>
@@ -134,7 +135,7 @@
// If no layers specified via Settings, check legacy properties
if (implicit_layers_.count <= 0) {
ParseDebugVulkanLayers();
- property_list(ParseDebugVulkanLayer, this);
+ ParseDebugVulkanLayer();
// sort by priorities
auto& arr = implicit_layers_;
@@ -181,30 +182,39 @@
AddImplicitLayer(prio, p, strlen(p));
}
- static void ParseDebugVulkanLayer(const char* key,
- const char* val,
- void* user_data) {
+ void ParseDebugVulkanLayer() {
+ // Checks for consecutive debug.vulkan.layer.<priority> system
+ // properties after always checking an initial fixed range.
static const char prefix[] = "debug.vulkan.layer.";
- const size_t prefix_len = sizeof(prefix) - 1;
+ static constexpr int kFixedRangeBeginInclusive = 0;
+ static constexpr int kFixedRangeEndInclusive = 9;
- if (strncmp(key, prefix, prefix_len) || val[0] == '\0')
- return;
- key += prefix_len;
+ bool logged = false;
- // debug.vulkan.layer.<priority>
- int priority = -1;
- if (key[0] >= '0' && key[0] <= '9')
- priority = atoi(key);
+ int priority = kFixedRangeBeginInclusive;
+ while (true) {
+ const std::string prop_key =
+ std::string(prefix) + std::to_string(priority);
+ const std::string prop_val =
+ android::base::GetProperty(prop_key, "");
- if (priority < 0) {
- ALOGW("Ignored implicit layer %s with invalid priority %s", val,
- key);
- return;
+ if (!prop_val.empty()) {
+ if (!logged) {
+ ALOGI(
+ "Detected Vulkan layers configured with "
+ "debug.vulkan.layer.<priority>. Checking for "
+ "debug.vulkan.layer.<priority> in the range [%d, %d] "
+ "followed by a consecutive scan.",
+ kFixedRangeBeginInclusive, kFixedRangeEndInclusive);
+ logged = true;
+ }
+ AddImplicitLayer(priority, prop_val.c_str(), prop_val.length());
+ } else if (priority >= kFixedRangeEndInclusive) {
+ return;
+ }
+
+ ++priority;
}
-
- OverrideLayerNames& override_layers =
- *reinterpret_cast<OverrideLayerNames*>(user_data);
- override_layers.AddImplicitLayer(priority, val, strlen(val));
}
void AddImplicitLayer(int priority, const char* name, size_t len) {
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 55d80fb..5d47172 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -149,8 +149,8 @@
Hal Hal::hal_;
const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{
- "ro.hardware.vulkan",
- "ro.board.platform",
+ "ro.hardware." HWVULKAN_HARDWARE_MODULE_ID,
+ "ro.board.platform"
}};
constexpr int LIB_DL_FLAGS = RTLD_LOCAL | RTLD_NOW;
@@ -184,8 +184,9 @@
if (so)
break;
}
- if (!so)
+ if (!so) {
return -ENOENT;
+ }
auto hmi = static_cast<hw_module_t*>(dlsym(so, HAL_MODULE_INFO_SYM_AS_STR));
if (!hmi) {
@@ -230,7 +231,6 @@
bool Hal::Open() {
ATRACE_CALL();
-
const nsecs_t openTime = systemTime();
ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once");
@@ -248,16 +248,16 @@
if (result != 0) {
android::GraphicsEnv::getInstance().setDriverLoaded(
android::GpuStatsInfo::Api::API_VK, false, systemTime() - openTime);
- ALOGV("unable to load Vulkan HAL, using stub HAL (result=%d)", result);
return true;
}
-
hwvulkan_device_t* device;
ATRACE_BEGIN("hwvulkan module open");
result =
module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
reinterpret_cast<hw_device_t**>(&device));
+
+
ATRACE_END();
if (result != 0) {
android::GraphicsEnv::getInstance().setDriverLoaded(
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 6b51817..4b69bec 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -606,44 +606,9 @@
VKAPI_ATTR
VkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice /*pdev*/,
uint32_t /*queue_family*/,
- VkSurfaceKHR surface_handle,
+ VkSurfaceKHR /*surface_handle*/,
VkBool32* supported) {
- ATRACE_CALL();
-
- const Surface* surface = SurfaceFromHandle(surface_handle);
- if (!surface) {
- return VK_ERROR_SURFACE_LOST_KHR;
- }
- const ANativeWindow* window = surface->window.get();
-
- int query_value;
- int err = window->query(window, NATIVE_WINDOW_FORMAT, &query_value);
- if (err != android::OK || query_value < 0) {
- ALOGE("NATIVE_WINDOW_FORMAT query failed: %s (%d) value=%d",
- strerror(-err), err, query_value);
- return VK_ERROR_SURFACE_LOST_KHR;
- }
-
- android_pixel_format native_format =
- static_cast<android_pixel_format>(query_value);
-
- bool format_supported = false;
- switch (native_format) {
- case HAL_PIXEL_FORMAT_RGBA_8888:
- case HAL_PIXEL_FORMAT_RGB_565:
- case HAL_PIXEL_FORMAT_RGBA_FP16:
- case HAL_PIXEL_FORMAT_RGBA_1010102:
- format_supported = true;
- break;
- default:
- break;
- }
-
- *supported = static_cast<VkBool32>(
- format_supported || (surface->consumer_usage &
- (AHARDWAREBUFFER_USAGE_CPU_READ_MASK |
- AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK)) == 0);
-
+ *supported = VK_TRUE;
return VK_SUCCESS;
}
@@ -1130,13 +1095,6 @@
return VK_ERROR_SURFACE_LOST_KHR;
}
- err = native_window_set_buffer_count(window, 0);
- if (err != android::OK) {
- ALOGE("native_window_set_buffer_count(0) failed: %s (%d)",
- strerror(-err), err);
- return VK_ERROR_SURFACE_LOST_KHR;
- }
-
int swap_interval =
create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1;
err = window->setSwapInterval(window, swap_interval);
@@ -1744,7 +1702,7 @@
if (err != android::OK) {
ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err);
swapchain_result = WorstPresentResult(
- swapchain_result, VK_ERROR_OUT_OF_DATE_KHR);
+ swapchain_result, VK_ERROR_SURFACE_LOST_KHR);
} else {
if (img.dequeue_fence >= 0) {
close(img.dequeue_fence);
diff --git a/vulkan/nulldrv/Android.bp b/vulkan/nulldrv/Android.bp
index ba02504..0daad9c 100644
--- a/vulkan/nulldrv/Android.bp
+++ b/vulkan/nulldrv/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
// Real drivers would set this to vulkan.$(TARGET_BOARD_PLATFORM)
name: "vulkan.default",
diff --git a/vulkan/vkjson/Android.bp b/vulkan/vkjson/Android.bp
index 8528898..fa0258b 100644
--- a/vulkan/vkjson/Android.bp
+++ b/vulkan/vkjson/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libvkjson",
srcs: [
diff --git a/vulkan/vkjson/vkjson.cc b/vulkan/vkjson/vkjson.cc
index bfc240e..438e5dd 100644
--- a/vulkan/vkjson/vkjson.cc
+++ b/vulkan/vkjson/vkjson.cc
@@ -842,6 +842,8 @@
bool ret = true;
switch (device->properties.apiVersion ^
VK_VERSION_PATCH(device->properties.apiVersion)) {
+ case VK_API_VERSION_1_2:
+ FALLTHROUGH_INTENDED;
case VK_API_VERSION_1_1:
ret &=
visitor->Visit("subgroupProperties", &device->subgroup_properties) &&
@@ -896,6 +898,8 @@
inline bool Iterate(Visitor* visitor, VkJsonInstance* instance) {
bool ret = true;
switch (instance->api_version ^ VK_VERSION_PATCH(instance->api_version)) {
+ case VK_API_VERSION_1_2:
+ FALLTHROUGH_INTENDED;
case VK_API_VERSION_1_1:
ret &= visitor->Visit("deviceGroups", &instance->device_groups);
FALLTHROUGH_INTENDED;
@@ -1196,10 +1200,10 @@
std::string* errors) {
*t = T();
Json::Value object(Json::objectValue);
- Json::Reader reader;
- reader.parse(json, object, false);
- if (!object) {
- if (errors) errors->assign(reader.getFormatedErrorMessages());
+ Json::CharReaderBuilder builder;
+ builder["collectComments"] = false;
+ std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
+ if (!reader->parse(json.data(), json.data() + json.size(), &object, errors)) {
return false;
}
return AsValue(&object, t);
diff --git a/vulkan/vkjson/vkjson_info.cc b/vulkan/vkjson/vkjson_info.cc
deleted file mode 100644
index 3c4b08b..0000000
--- a/vulkan/vkjson/vkjson_info.cc
+++ /dev/null
@@ -1,184 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-// Copyright (c) 2015-2016 The Khronos Group Inc.
-// Copyright (c) 2015-2016 Valve Corporation
-// Copyright (c) 2015-2016 LunarG, Inc.
-// Copyright (c) 2015-2016 Google, Inc.
-//
-// 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.
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef VK_PROTOTYPES
-#define VK_PROTOTYPES
-#endif
-
-#include "vkjson.h"
-
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <iostream>
-#include <vector>
-
-const uint32_t unsignedNegOne = (uint32_t)(-1);
-
-struct Options {
- bool instance = false;
- uint32_t device_index = unsignedNegOne;
- std::string device_name;
- std::string output_file;
-};
-
-bool ParseOptions(int argc, char* argv[], Options* options) {
- for (int i = 1; i < argc; ++i) {
- std::string arg(argv[i]);
- if (arg == "--instance" || arg == "-i") {
- options->instance = true;
- } else if (arg == "--first" || arg == "-f") {
- options->device_index = 0;
- } else {
- ++i;
- if (i >= argc) {
- std::cerr << "Missing parameter after: " << arg << std::endl;
- return false;
- }
- std::string arg2(argv[i]);
- if (arg == "--device-index" || arg == "-d") {
- int result = sscanf(arg2.c_str(), "%u", &options->device_index);
- if (result != 1) {
- options->device_index = static_cast<uint32_t>(-1);
- std::cerr << "Unable to parse index: " << arg2 << std::endl;
- return false;
- }
- } else if (arg == "--device-name" || arg == "-n") {
- options->device_name = arg2;
- } else if (arg == "--output" || arg == "-o") {
- options->output_file = arg2;
- } else {
- std::cerr << "Unknown argument: " << arg << std::endl;
- return false;
- }
- }
- }
- if (options->instance && (options->device_index != unsignedNegOne ||
- !options->device_name.empty())) {
- std::cerr << "Specifying a specific device is incompatible with dumping "
- "the whole instance." << std::endl;
- return false;
- }
- if (options->device_index != unsignedNegOne && !options->device_name.empty()) {
- std::cerr << "Must specify only one of device index and device name."
- << std::endl;
- return false;
- }
- if (options->instance && options->output_file.empty()) {
- std::cerr << "Must specify an output file when dumping the whole instance."
- << std::endl;
- return false;
- }
- if (!options->output_file.empty() && !options->instance &&
- options->device_index == unsignedNegOne && options->device_name.empty()) {
- std::cerr << "Must specify instance, device index, or device name when "
- "specifying "
- "output file." << std::endl;
- return false;
- }
- return true;
-}
-
-bool Dump(const VkJsonInstance& instance, const Options& options) {
- const VkJsonDevice* out_device = nullptr;
- if (options.device_index != unsignedNegOne) {
- if (static_cast<uint32_t>(options.device_index) >=
- instance.devices.size()) {
- std::cerr << "Error: device " << options.device_index
- << " requested but only " << instance.devices.size()
- << " devices found." << std::endl;
- return false;
- }
- out_device = &instance.devices[options.device_index];
- } else if (!options.device_name.empty()) {
- for (const auto& device : instance.devices) {
- if (device.properties.deviceName == options.device_name) {
- out_device = &device;
- }
- }
- if (!out_device) {
- std::cerr << "Error: device '" << options.device_name
- << "' requested but not found." << std::endl;
- return false;
- }
- }
-
- std::string output_file;
- if (options.output_file.empty()) {
- assert(out_device);
-#if defined(ANDROID)
- output_file.assign("/sdcard/Android/" + std::string(out_device->properties.deviceName));
-#else
- output_file.assign(out_device->properties.deviceName);
-#endif
- output_file.append(".json");
- } else {
- output_file = options.output_file;
- }
- FILE* file = nullptr;
- if (output_file == "-") {
- file = stdout;
- } else {
- file = fopen(output_file.c_str(), "w");
- if (!file) {
- std::cerr << "Unable to open file " << output_file << "." << std::endl;
- return false;
- }
- }
-
- std::string json = out_device ? VkJsonDeviceToJson(*out_device)
- : VkJsonInstanceToJson(instance);
- fwrite(json.data(), 1, json.size(), file);
- fputc('\n', file);
-
- if (output_file != "-") {
- fclose(file);
- std::cout << "Wrote file " << output_file;
- if (out_device)
- std::cout << " for device " << out_device->properties.deviceName;
- std::cout << "." << std::endl;
- }
- return true;
-}
-
-int main(int argc, char* argv[]) {
-#if defined(ANDROID)
- int vulkanSupport = InitVulkan();
- if (vulkanSupport == 0)
- return 1;
-#endif
- Options options;
- if (!ParseOptions(argc, argv, &options))
- return 1;
-
- VkJsonInstance instance = VkJsonGetInstance();
- if (options.instance || options.device_index != unsignedNegOne ||
- !options.device_name.empty()) {
- Dump(instance, options);
- } else {
- for (uint32_t i = 0, n = static_cast<uint32_t>(instance.devices.size()); i < n; i++) {
- options.device_index = i;
- Dump(instance, options);
- }
- }
-
- return 0;
-}
diff --git a/vulkan/vkjson/vkjson_unittest.cc b/vulkan/vkjson/vkjson_unittest.cc
deleted file mode 100644
index de765cd..0000000
--- a/vulkan/vkjson/vkjson_unittest.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-// Copyright (c) 2015-2016 The Khronos Group Inc.
-// Copyright (c) 2015-2016 Valve Corporation
-// Copyright (c) 2015-2016 LunarG, Inc.
-// Copyright (c) 2015-2016 Google, Inc.
-//
-// 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 "vkjson.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <iostream>
-
-#define EXPECT(X) if (!(X)) \
- ReportFailure(__FILE__, __LINE__, #X);
-
-#define ASSERT(X) if (!(X)) { \
- ReportFailure(__FILE__, __LINE__, #X); \
- return 2; \
-}
-
-int g_failures;
-
-void ReportFailure(const char* file, int line, const char* assertion) {
- std::cout << file << ":" << line << ": \"" << assertion << "\" failed."
- << std::endl;
- ++g_failures;
-}
-
-int main(int argc, char* argv[]) {
- std::string errors;
- bool result = false;
-
- VkJsonInstance instance;
- instance.devices.resize(1);
- VkJsonDevice& device = instance.devices[0];
-
- const char name[] = "Test device";
- memcpy(device.properties.deviceName, name, sizeof(name));
- device.properties.limits.maxImageDimension1D = 3;
- device.properties.limits.maxSamplerLodBias = 3.5f;
- device.properties.limits.bufferImageGranularity = 0x1ffffffffull;
- device.properties.limits.maxViewportDimensions[0] = 1;
- device.properties.limits.maxViewportDimensions[1] = 2;
- VkFormatProperties format_props = {
- VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT,
- VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT,
- VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT};
- device.formats.insert(std::make_pair(VK_FORMAT_R8_UNORM, format_props));
- device.formats.insert(std::make_pair(VK_FORMAT_R8G8_UNORM, format_props));
-
- std::string json = VkJsonInstanceToJson(instance);
- std::cout << json << std::endl;
-
- VkJsonInstance instance2;
- result = VkJsonInstanceFromJson(json, &instance2, &errors);
- EXPECT(result);
- if (!result)
- std::cout << "Error: " << errors << std::endl;
- const VkJsonDevice& device2 = instance2.devices.at(0);
-
- EXPECT(!memcmp(&device.properties, &device2.properties,
- sizeof(device.properties)));
- for (auto& kv : device.formats) {
- auto it = device2.formats.find(kv.first);
- EXPECT(it != device2.formats.end());
- EXPECT(!memcmp(&kv.second, &it->second, sizeof(kv.second)));
- }
-
- VkImageFormatProperties props = {};
- json = VkJsonImageFormatPropertiesToJson(props);
- VkImageFormatProperties props2 = {};
- result = VkJsonImageFormatPropertiesFromJson(json, &props2, &errors);
- EXPECT(result);
- if (!result)
- std::cout << "Error: " << errors << std::endl;
-
- EXPECT(!memcmp(&props, &props2, sizeof(props)));
-
- if (g_failures) {
- std::cout << g_failures << " failures." << std::endl;
- return 1;
- } else {
- std::cout << "Success." << std::endl;
- return 0;
- }
-}