Merge changes I02bc2802,I52773be9 into main
* changes:
Implement basic functionality for rust keyboard classifier
Implement KeyboardClassifier interface in rust
diff --git a/cmds/dumpstate/DumpstateUtil.h b/cmds/dumpstate/DumpstateUtil.h
index 9e955e3..ae7152a 100644
--- a/cmds/dumpstate/DumpstateUtil.h
+++ b/cmds/dumpstate/DumpstateUtil.h
@@ -18,6 +18,7 @@
#include <cstdint>
#include <string>
+#include <vector>
/*
* Converts seconds to milliseconds.
diff --git a/cmds/dumpstate/TEST_MAPPING b/cmds/dumpstate/TEST_MAPPING
index 649a13e..a24546a 100644
--- a/cmds/dumpstate/TEST_MAPPING
+++ b/cmds/dumpstate/TEST_MAPPING
@@ -10,6 +10,14 @@
},
{
"name": "dumpstate_test"
+ },
+ {
+ "name": "CtsSecurityHostTestCases",
+ "options": [
+ {
+ "include-filter": "android.security.cts.SELinuxHostTest#testNoBugreportDenials"
+ }
+ ]
}
],
"postsubmit": [
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index d5125f0..6576ffd 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -191,6 +191,7 @@
#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
#define DROPBOX_DIR "/data/system/dropbox"
#define PRINT_FLAGS "/system/bin/printflags"
+#define UWB_LOG_DIR "/data/misc/apexdata/com.android.uwb/log"
// TODO(narayan): Since this information has to be kept in sync
// with tombstoned, we should just put it in a common header.
@@ -1569,6 +1570,7 @@
printf("== ANR Traces\n");
printf("========================================================\n");
+ ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
AddAnrTraceFiles();
printf("========================================================\n");
@@ -1971,6 +1973,9 @@
RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
CommandOptions::WithTimeout(10).Always().DropRoot().Build());
+ // Dump UWB UCI logs here because apexdata requires root access
+ ds.AddDir(UWB_LOG_DIR, true);
+
if (dump_pool_) {
RETURN_IF_USER_DENIED_CONSENT();
WaitForTask(std::move(dump_traces));
@@ -2190,6 +2195,74 @@
ds.AddDir(LOGPERSIST_DATA_DIR, false);
}
+static std::string GetTimestamp(const timespec& ts) {
+ tm tm;
+ localtime_r(&ts.tv_sec, &tm);
+
+ // Reserve enough space for the entire time string, includes the space
+ // for the '\0' to make the calculations below easier by using size for
+ // the total string size.
+ std::string str(sizeof("1970-01-01 00:00:00.123456789+0830"), '\0');
+ size_t n = strftime(str.data(), str.size(), "%F %H:%M", &tm);
+ if (n == 0) {
+ return "TIMESTAMP FAILURE";
+ }
+ int num_chars = snprintf(&str[n], str.size() - n, ":%02d.%09ld", tm.tm_sec, ts.tv_nsec);
+ if (num_chars > str.size() - n) {
+ return "TIMESTAMP FAILURE";
+ }
+ n += static_cast<size_t>(num_chars);
+ if (strftime(&str[n], str.size() - n, "%z", &tm) == 0) {
+ return "TIMESTAMP FAILURE";
+ }
+ return str;
+}
+
+static std::string GetCmdline(pid_t pid) {
+ std::string cmdline;
+ if (!android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/cmdline", pid),
+ &cmdline)) {
+ return "UNKNOWN";
+ }
+ // There are '\0' terminators between arguments, convert them to spaces.
+ // But start by skipping all trailing '\0' values.
+ size_t cur = cmdline.size() - 1;
+ while (cur != 0 && cmdline[cur] == '\0') {
+ cur--;
+ }
+ if (cur == 0) {
+ return "UNKNOWN";
+ }
+ while ((cur = cmdline.rfind('\0', cur)) != std::string::npos) {
+ cmdline[cur] = ' ';
+ }
+ return cmdline;
+}
+
+static void DumpPidHeader(int fd, pid_t pid, const timespec& ts) {
+ // For consistency, the header to this message matches the one
+ // dumped by debuggerd.
+ dprintf(fd, "\n----- pid %d at %s -----\n", pid, GetTimestamp(ts).c_str());
+ dprintf(fd, "Cmd line: %s\n", GetCmdline(pid).c_str());
+}
+
+static void DumpPidFooter(int fd, pid_t pid) {
+ // For consistency, the footer to this message matches the one
+ // dumped by debuggerd.
+ dprintf(fd, "----- end %d -----\n", pid);
+}
+
+static bool DumpBacktrace(int fd, pid_t pid, bool is_java_process) {
+ int ret = dump_backtrace_to_file_timeout(
+ pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
+ if (ret == -1 && is_java_process) {
+ // Tried to unwind as a java process, try a native unwind.
+ dprintf(fd, "Java unwind failed for pid %d, trying a native unwind.\n", pid);
+ ret = dump_backtrace_to_file_timeout(pid, kDebuggerdNativeBacktrace, 3, fd);
+ }
+ return ret != -1;
+}
+
Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
const size_t buf_size = temp_file_pattern.length() + 1;
@@ -2238,16 +2311,6 @@
continue;
}
- // Skip cached processes.
- if (IsCached(pid)) {
- // For consistency, the header and footer to this message match those
- // dumped by debuggerd in the success case.
- dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
- dprintf(fd, "Dump skipped for cached process.\n");
- dprintf(fd, "---- end %d ----", pid);
- continue;
- }
-
const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
std::string exe;
if (!android::base::Readlink(link_name, &exe)) {
@@ -2276,16 +2339,31 @@
break;
}
- const uint64_t start = Nanotime();
- const int ret = dump_backtrace_to_file_timeout(
- pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
+ timespec start_timespec;
+ clock_gettime(CLOCK_REALTIME, &start_timespec);
+ if (IsCached(pid)) {
+ DumpPidHeader(fd, pid, start_timespec);
+ dprintf(fd, "Process is cached, skipping backtrace due to high chance of timeout.\n");
+ DumpPidFooter(fd, pid);
+ continue;
+ }
- if (ret == -1) {
- // For consistency, the header and footer to this message match those
- // dumped by debuggerd in the success case.
- dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
- dprintf(fd, "Dump failed, likely due to a timeout.\n");
- dprintf(fd, "---- end %d ----", pid);
+ const uint64_t start = Nanotime();
+ if (!DumpBacktrace(fd, pid, is_java_process)) {
+ if (IsCached(pid)) {
+ DumpPidHeader(fd, pid, start_timespec);
+ dprintf(fd, "Backtrace failed, but process has become cached.\n");
+ DumpPidFooter(fd, pid);
+ continue;
+ }
+
+ DumpPidHeader(fd, pid, start_timespec);
+ dprintf(fd, "Backtrace gathering failed, likely due to a timeout.\n");
+ DumpPidFooter(fd, pid);
+
+ dprintf(fd, "\n[dump %s stack %d: %.3fs elapsed]\n",
+ is_java_process ? "dalvik" : "native", pid,
+ (float)(Nanotime() - start) / NANOS_PER_SEC);
timeout_failures++;
continue;
}
diff --git a/cmds/installd/file_parsing.h b/cmds/installd/file_parsing.h
index 88801ca..0ec5abb 100644
--- a/cmds/installd/file_parsing.h
+++ b/cmds/installd/file_parsing.h
@@ -51,7 +51,7 @@
}
template<typename Func>
-bool ParseFile(std::string_view str_file, Func parse) {
+bool ParseFile(const std::string& str_file, Func parse) {
std::ifstream ifs(str_file);
if (!ifs.is_open()) {
return false;
diff --git a/cmds/installd/otapreopt_script.sh b/cmds/installd/otapreopt_script.sh
index ae7d8e0..2d889fd 100644
--- a/cmds/installd/otapreopt_script.sh
+++ b/cmds/installd/otapreopt_script.sh
@@ -50,7 +50,27 @@
exit 1
fi
-if pm art on-ota-staged --slot "$TARGET_SLOT_SUFFIX"; then
+# A source that infinitely emits arbitrary lines.
+# When connected to STDIN of another process, this source keeps STDIN open until
+# the consumer process closes STDIN or this script dies.
+function infinite_source {
+ while echo .; do
+ sleep 1
+ done
+}
+
+# Delegate to Pre-reboot Dexopt, a feature of ART Service.
+# ART Service decides what to do with this request:
+# - If Pre-reboot Dexopt is disabled or unsupported, the command returns
+# non-zero. This is always the case if the current system is Android 14 or
+# earlier.
+# - If Pre-reboot Dexopt is enabled in synchronous mode, the command blocks
+# until Pre-reboot Dexopt finishes, and returns zero no matter it succeeds or
+# not. This is the default behavior if the current system is Android 15.
+# - If Pre-reboot Dexopt is enabled in asynchronous mode, the command schedules
+# an asynchronous job and returns 0 immediately. The job will then run by the
+# job scheduler when the device is idle and charging.
+if infinite_source | pm art on-ota-staged --slot "$TARGET_SLOT_SUFFIX"; then
# Handled by Pre-reboot Dexopt.
exit 0
fi
diff --git a/include/binder/Common.h b/include/binder/Common.h
new file mode 120000
index 0000000..940f89d
--- /dev/null
+++ b/include/binder/Common.h
@@ -0,0 +1 @@
+../../libs/binder/include/binder/Common.h
\ No newline at end of file
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 090e35b..cb1d114 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -28,6 +28,7 @@
recovery_available: true,
host_supported: true,
native_bridge_supported: true,
+ cmake_snapshot_supported: true,
header_libs: [
"libbinder_headers_platform_shared",
@@ -83,6 +84,124 @@
},
}
+cc_cmake_snapshot {
+ name: "binder_sdk",
+ modules: [
+ "libbinder_sdk",
+ "libbinder_sdk_single_threaded",
+ "libbinder_ndk_sdk",
+ "binderRpcTestNoKernel",
+ ],
+ prebuilts: [
+ // to enable arm64 host support, build with musl - e.g. on aosp_cf_arm64_phone
+ "aidl",
+ "libc++",
+ ],
+ include_sources: true,
+ cflags: [
+ "-DNDEBUG",
+ "-DBINDER_ENABLE_LIBLOG_ASSERT",
+ "-DBINDER_DISABLE_NATIVE_HANDLE",
+ "-DBINDER_DISABLE_BLOB",
+ "-DBINDER_NO_LIBBASE",
+ "-DBINDER_NO_KERNEL_IPC_TESTING",
+
+ // from Soong's global.go commonGlobalCflags and noOverrideGlobalCflags
+ "-Wno-c99-designator",
+ "-Wno-missing-field-initializers",
+
+ // warnings that only pop up on gcc
+ "-Wno-unknown-pragmas", // "pragma clang"
+ "-Wno-attributes", // attributes on compound-statements
+ "-Wno-psabi", // reminders about old ABI changes
+ ],
+ cflags_ignored: [
+ // gcc requires all header constexprs to be used in all dependent compilatinon units
+ "-Wunused-const-variable",
+ ],
+ library_mapping: [
+ {
+ android_name: "libssl",
+ mapped_name: "ssl",
+ package_pregenerated: "external/boringssl",
+ },
+ {
+ android_name: "libcrypto",
+ mapped_name: "crypto",
+ package_pregenerated: "external/boringssl",
+ },
+ {
+ android_name: "libgtest",
+ mapped_name: "GTest::gtest",
+ package_system: "GTest",
+ },
+ {
+ android_name: "libgtest_main",
+ mapped_name: "GTest::gtest",
+ package_system: "GTest",
+ },
+
+ // use libbinder_sdk and friends instead of full Android's libbinder
+ {
+ android_name: "libbinder_rpc_no_kernel",
+ mapped_name: "android::libbinder_sdk",
+ },
+ {
+ android_name: "libbinder_rpc_single_threaded_no_kernel",
+ mapped_name: "android::libbinder_sdk_single_threaded",
+ },
+ {
+ android_name: "libbinder_headers",
+ mapped_name: "android::libbinder_headers_base",
+ },
+ {
+ android_name: "libbinder",
+ mapped_name: "android::libbinder_sdk",
+ },
+ {
+ android_name: "libbinder_ndk",
+ mapped_name: "android::libbinder_ndk_sdk",
+ },
+ {
+ android_name: "liblog",
+ mapped_name: "android::liblog_stub",
+ },
+
+ // explicitly included by Binder tests, but not needed outside of Android
+ {
+ android_name: "libbase",
+ },
+ {
+ android_name: "libcutils",
+ },
+ {
+ android_name: "libutils",
+ },
+
+ // disable tests that don't work outside of Android yet
+ {
+ android_name: "binder_rpc_test_service",
+ },
+ {
+ android_name: "binder_rpc_test_service_single_threaded",
+ },
+
+ // trusty mocks are artificially triggered and not needed outside of Android build
+ {
+ android_name: "libbinder_on_trusty_mock",
+ },
+ {
+ android_name: "libbinder_ndk_on_trusty_mock",
+ },
+ {
+ android_name: "binderRpcTestService_on_trusty_mock",
+ },
+ {
+ android_name: "binderRpcTest_on_trusty_mock",
+ },
+ ],
+}
+
// These interfaces are android-specific implementation unrelated to binder
// transport itself and should be moved to AIDL or in domain-specific libs.
//
@@ -126,6 +245,9 @@
header_libs: [
"libbinder_headers_base",
],
+ export_header_lib_headers: [
+ "libbinder_headers_base",
+ ],
cflags: [
"-Wextra",
@@ -369,6 +491,7 @@
double_loadable: true,
// TODO(b/153609531): remove when no longer needed.
native_bridge_supported: true,
+ cmake_snapshot_supported: false,
// libbinder does not offer a stable wire protocol.
// if a second copy of it is installed, then it may break after security
@@ -408,16 +531,8 @@
afdo: true,
}
-cc_library_host_shared {
- name: "libbinder_sdk",
-
- defaults: [
- "libbinder_common_defaults",
- ],
-
- shared_libs: [
- "libutils_binder_sdk",
- ],
+cc_defaults {
+ name: "binder_sdk_defaults",
cflags: [
"-DBINDER_ENABLE_LIBLOG_ASSERT",
@@ -429,6 +544,21 @@
header_libs: [
"liblog_stub",
],
+}
+
+cc_defaults {
+ name: "libbinder_sdk_defaults",
+
+ cmake_snapshot_supported: true,
+
+ defaults: [
+ "libbinder_common_defaults",
+ "binder_sdk_defaults",
+ ],
+
+ shared_libs: [
+ "libutils_binder_sdk",
+ ],
srcs: [
"OS_non_android_linux.cpp",
@@ -446,6 +576,19 @@
},
}
+cc_library_host_shared {
+ name: "libbinder_sdk",
+ defaults: ["libbinder_sdk_defaults"],
+}
+
+cc_library_host_shared {
+ name: "libbinder_sdk_single_threaded",
+ defaults: ["libbinder_sdk_defaults"],
+ cflags: [
+ "-DBINDER_RPC_SINGLE_THREADED",
+ ],
+}
+
cc_library {
name: "libbinder_rpc_no_kernel",
vendor_available: true,
@@ -535,6 +678,7 @@
defaults: ["libbinder_tls_shared_deps"],
vendor_available: true,
host_supported: true,
+ cmake_snapshot_supported: true,
header_libs: [
"libbinder_headers",
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 7a855e1..6594aa6 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -15,7 +15,6 @@
*/
#define LOG_TAG "BpBinder"
-#define ATRACE_TAG ATRACE_TAG_AIDL
//#define LOG_NDEBUG 0
#include <binder/BpBinder.h>
@@ -24,15 +23,10 @@
#include <binder/IResultReceiver.h>
#include <binder/RpcSession.h>
#include <binder/Stability.h>
+#include <binder/Trace.h>
#include <stdio.h>
-#ifndef __TRUSTY__
-#include <cutils/trace.h>
-#else
-#define ATRACE_INT(...)
-#endif
-
#include "BuildFlags.h"
#include "file.h"
@@ -216,7 +210,7 @@
sTrackingMap[trackedUid]++;
}
uint32_t numProxies = sBinderProxyCount.fetch_add(1, std::memory_order_relaxed);
- ATRACE_INT("binder_proxies", numProxies);
+ binder::os::trace_int(ATRACE_TAG_AIDL, "binder_proxies", numProxies);
uint32_t numLastWarned = sBinderProxyCountWarned.load(std::memory_order_relaxed);
uint32_t numNextWarn = numLastWarned + kBinderProxyCountWarnInterval;
if (numProxies >= numNextWarn) {
@@ -640,8 +634,8 @@
}
}
}
- [[maybe_unused]] uint32_t numProxies = --sBinderProxyCount;
- ATRACE_INT("binder_proxies", numProxies);
+ uint32_t numProxies = --sBinderProxyCount;
+ binder::os::trace_int(ATRACE_TAG_AIDL, "binder_proxies", numProxies);
if (ipc) {
ipc->expungeHandle(binderHandle(), this);
ipc->decWeakHandle(binderHandle());
diff --git a/libs/binder/BufferedTextOutput.h b/libs/binder/BufferedTextOutput.h
index 57e03cb..1c074e6 100644
--- a/libs/binder/BufferedTextOutput.h
+++ b/libs/binder/BufferedTextOutput.h
@@ -24,8 +24,7 @@
// ---------------------------------------------------------------------------
namespace android {
-class BufferedTextOutput : public TextOutput
-{
+class LIBBINDER_INTERNAL_EXPORTED BufferedTextOutput : public TextOutput {
public:
//** Flags for constructor */
enum {
diff --git a/libs/binder/Debug.h b/libs/binder/Debug.h
index 262dfba..c3d03f8 100644
--- a/libs/binder/Debug.h
+++ b/libs/binder/Debug.h
@@ -20,6 +20,8 @@
#include <sys/types.h>
#include <string>
+#include <binder/Common.h>
+
namespace android {
// ---------------------------------------------------------------------------
@@ -35,7 +37,8 @@
size_t alignment=0, bool cArrayStyle=false,
debugPrintFunc func = nullptr, void* cookie = nullptr);
-extern "C" ssize_t getBinderKernelReferences(size_t count, uintptr_t* buf);
+// Used by libmemunreachable.
+extern "C" LIBBINDER_EXPORTED ssize_t getBinderKernelReferences(size_t count, uintptr_t* buf);
// ---------------------------------------------------------------------------
} // namespace android
diff --git a/libs/binder/FdTrigger.h b/libs/binder/FdTrigger.h
index e4a0283..78cdaaa 100644
--- a/libs/binder/FdTrigger.h
+++ b/libs/binder/FdTrigger.h
@@ -25,7 +25,7 @@
namespace android {
/** This is not a pipe. */
-class FdTrigger {
+class LIBBINDER_INTERNAL_EXPORTED FdTrigger {
public:
/** Returns nullptr for error case */
static std::unique_ptr<FdTrigger> make();
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index ef96f80..fbc8125 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -1027,6 +1027,7 @@
goto finish;
case BR_FROZEN_REPLY:
+ ALOGW("Transaction failed because process frozen.");
err = FAILED_TRANSACTION;
goto finish;
@@ -1578,8 +1579,8 @@
}
#endif
- ALOGE_IF(ee.command != BR_OK, "Binder transaction failure: %d/%d/%d",
- ee.id, ee.command, ee.param);
+ ALOGE_IF(ee.command != BR_OK, "Binder transaction failure. id: %d, BR_*: %d, error: %d (%s)",
+ ee.id, ee.command, ee.param, strerror(-ee.param));
}
void IPCThreadState::freeBuffer(const uint8_t* data, size_t /*dataSize*/,
diff --git a/libs/binder/OS.h b/libs/binder/OS.h
index 0035aeb..04869a1 100644
--- a/libs/binder/OS.h
+++ b/libs/binder/OS.h
@@ -24,8 +24,9 @@
namespace android::binder::os {
-void trace_begin(uint64_t tag, const char* name);
-void trace_end(uint64_t tag);
+LIBBINDER_EXPORTED void trace_begin(uint64_t tag, const char* name);
+LIBBINDER_EXPORTED void trace_end(uint64_t tag);
+LIBBINDER_EXPORTED void trace_int(uint64_t tag, const char* name, int32_t value);
status_t setNonBlocking(borrowed_fd fd);
@@ -35,11 +36,13 @@
std::unique_ptr<RpcTransportCtxFactory> makeDefaultRpcTransportCtxFactory();
-ssize_t sendMessageOnSocket(const RpcTransportFd& socket, iovec* iovs, int niovs,
- const std::vector<std::variant<unique_fd, borrowed_fd>>* ancillaryFds);
+LIBBINDER_INTERNAL_EXPORTED ssize_t
+sendMessageOnSocket(const RpcTransportFd& socket, iovec* iovs, int niovs,
+ const std::vector<std::variant<unique_fd, borrowed_fd>>* ancillaryFds);
-ssize_t receiveMessageFromSocket(const RpcTransportFd& socket, iovec* iovs, int niovs,
- std::vector<std::variant<unique_fd, borrowed_fd>>* ancillaryFds);
+LIBBINDER_INTERNAL_EXPORTED ssize_t
+receiveMessageFromSocket(const RpcTransportFd& socket, iovec* iovs, int niovs,
+ std::vector<std::variant<unique_fd, borrowed_fd>>* ancillaryFds);
uint64_t GetThreadId();
diff --git a/libs/binder/OS_android.cpp b/libs/binder/OS_android.cpp
index 1eace85..893ee15 100644
--- a/libs/binder/OS_android.cpp
+++ b/libs/binder/OS_android.cpp
@@ -44,6 +44,10 @@
atrace_end(tag);
}
+void trace_int(uint64_t tag, const char* name, int32_t value) {
+ atrace_int(tag, name, value);
+}
+
} // namespace os
// Legacy trace symbol. To be removed once all of downstream rebuilds.
diff --git a/libs/binder/OS_non_android_linux.cpp b/libs/binder/OS_non_android_linux.cpp
index b525d1a..0c64eb6 100644
--- a/libs/binder/OS_non_android_linux.cpp
+++ b/libs/binder/OS_non_android_linux.cpp
@@ -21,6 +21,8 @@
#include <syscall.h>
#include <cstdarg>
+#include <binder/Common.h>
+
#ifdef __ANDROID__
#error "This module is not intended for Android, just bare Linux"
#endif
@@ -37,6 +39,8 @@
void trace_end(uint64_t) {}
+void trace_int(uint64_t, const char*, int32_t) {}
+
uint64_t GetThreadId() {
return syscall(__NR_gettid);
}
@@ -47,7 +51,8 @@
} // namespace android::binder::os
-int __android_log_print(int /*prio*/, const char* /*tag*/, const char* fmt, ...) {
+LIBBINDER_EXPORTED int __android_log_print(int /*prio*/, const char* /*tag*/, const char* fmt,
+ ...) {
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp
index 1504715..5b157cc 100644
--- a/libs/binder/PersistableBundle.cpp
+++ b/libs/binder/PersistableBundle.cpp
@@ -82,13 +82,12 @@
} \
}
-#define RETURN_IF_ENTRY_ERASED(map, key) \
- { \
- size_t num_erased = (map).erase(key); \
- if (num_erased) { \
- ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
- return num_erased; \
- } \
+#define RETURN_IF_ENTRY_ERASED(map, key) \
+ { \
+ size_t num_erased = (map).erase(key); \
+ if (num_erased) { \
+ return num_erased; \
+ } \
}
status_t PersistableBundle::writeToParcel(Parcel* parcel) const {
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index fb2781b..8485ecd 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -516,22 +516,23 @@
return mDriverName;
}
-static unique_fd open_driver(const char* driver) {
+static unique_fd open_driver(const char* driver, String8* error) {
auto fd = unique_fd(open(driver, O_RDWR | O_CLOEXEC));
if (!fd.ok()) {
- PLOGE("Opening '%s' failed", driver);
+ error->appendFormat("%d (%s) Opening '%s' failed", errno, strerror(errno), driver);
return {};
}
int vers = 0;
int result = ioctl(fd.get(), BINDER_VERSION, &vers);
if (result == -1) {
- PLOGE("Binder ioctl to obtain version failed");
+ error->appendFormat("%d (%s) Binder ioctl to obtain version failed", errno,
+ strerror(errno));
return {};
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
- ALOGE("Binder driver protocol(%d) does not match user space protocol(%d)! "
- "ioctl() return value: %d",
- vers, BINDER_CURRENT_PROTOCOL_VERSION, result);
+ error->appendFormat("Binder driver protocol(%d) does not match user space protocol(%d)! "
+ "ioctl() return value: %d",
+ vers, BINDER_CURRENT_PROTOCOL_VERSION, result);
return {};
}
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
@@ -565,7 +566,8 @@
mThreadPoolStarted(false),
mThreadPoolSeq(1),
mCallRestriction(CallRestriction::NONE) {
- unique_fd opened = open_driver(driver);
+ String8 error;
+ unique_fd opened = open_driver(driver, &error);
if (opened.ok()) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
@@ -580,8 +582,9 @@
}
#ifdef __ANDROID__
- LOG_ALWAYS_FATAL_IF(!opened.ok(), "Binder driver '%s' could not be opened. Terminating.",
- driver);
+ LOG_ALWAYS_FATAL_IF(!opened.ok(),
+ "Binder driver '%s' could not be opened. Error: %s. Terminating.",
+ error.c_str(), driver);
#endif
if (opened.ok()) {
diff --git a/libs/binder/RpcState.h b/libs/binder/RpcState.h
index 8b84602..94013cc 100644
--- a/libs/binder/RpcState.h
+++ b/libs/binder/RpcState.h
@@ -149,8 +149,8 @@
*/
[[nodiscard]] status_t sendObituaries(const sp<RpcSession>& session);
- size_t countBinders();
- void dump();
+ LIBBINDER_INTERNAL_EXPORTED size_t countBinders();
+ LIBBINDER_INTERNAL_EXPORTED void dump();
/**
* Called when reading or writing data to a session fails to clean up
diff --git a/libs/binder/Utils.h b/libs/binder/Utils.h
index eec09eb..df8a4ce 100644
--- a/libs/binder/Utils.h
+++ b/libs/binder/Utils.h
@@ -21,6 +21,7 @@
#include <cstdint>
#include <optional>
+#include <binder/Common.h>
#include <log/log.h>
#include <utils/Errors.h>
@@ -111,6 +112,6 @@
//
// Hex values are printed in order, e.g. 0xDEAD will result in 'adde' because
// Android is little-endian.
-std::string HexString(const void* bytes, size_t len);
+LIBBINDER_INTERNAL_EXPORTED std::string HexString(const void* bytes, size_t len);
} // namespace android
diff --git a/libs/binder/UtilsHost.h b/libs/binder/UtilsHost.h
index d6fe9fa..03af1e7 100644
--- a/libs/binder/UtilsHost.h
+++ b/libs/binder/UtilsHost.h
@@ -24,6 +24,7 @@
#include <vector>
#include <android-base/macros.h>
+#include <binder/Common.h>
#include <binder/unique_fd.h>
#include <utils/Errors.h>
@@ -40,7 +41,7 @@
namespace android {
-struct CommandResult {
+struct LIBBINDER_EXPORTED CommandResult {
std::optional<int32_t> exitCode;
std::optional<int32_t> signal;
std::optional<pid_t> pid;
@@ -72,7 +73,7 @@
void operator=(const CommandResult&) = delete;
};
-std::ostream& operator<<(std::ostream& os, const CommandResult& res);
+LIBBINDER_EXPORTED std::ostream& operator<<(std::ostream& os, const CommandResult& res);
// Execute a command using tokens specified in @a argStringVec.
//
@@ -96,6 +97,7 @@
//
// If the parent process has encountered any errors for system calls, return ExecuteError with
// the proper errno set.
-std::optional<CommandResult> execute(std::vector<std::string> argStringVec,
- const std::function<bool(const CommandResult&)>& end);
+LIBBINDER_EXPORTED std::optional<CommandResult> execute(
+ std::vector<std::string> argStringVec,
+ const std::function<bool(const CommandResult&)>& end);
} // namespace android
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 7a65ff4..135be89 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -18,6 +18,7 @@
#include <atomic>
#include <stdint.h>
+#include <binder/Common.h>
#include <binder/IBinder.h>
// ---------------------------------------------------------------------------
@@ -27,50 +28,47 @@
class Stability;
}
-class BBinder : public IBinder
-{
+class BBinder : public IBinder {
public:
- BBinder();
+ LIBBINDER_EXPORTED BBinder();
- virtual const String16& getInterfaceDescriptor() const;
- virtual bool isBinderAlive() const;
- virtual status_t pingBinder();
- virtual status_t dump(int fd, const Vector<String16>& args);
+ LIBBINDER_EXPORTED virtual const String16& getInterfaceDescriptor() const;
+ LIBBINDER_EXPORTED virtual bool isBinderAlive() const;
+ LIBBINDER_EXPORTED virtual status_t pingBinder();
+ LIBBINDER_EXPORTED virtual status_t dump(int fd, const Vector<String16>& args);
// NOLINTNEXTLINE(google-default-arguments)
- virtual status_t transact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0) final;
+ LIBBINDER_EXPORTED virtual status_t transact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags = 0) final;
// NOLINTNEXTLINE(google-default-arguments)
- virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
- void* cookie = nullptr,
- uint32_t flags = 0);
+ LIBBINDER_EXPORTED virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
+ void* cookie = nullptr, uint32_t flags = 0);
// NOLINTNEXTLINE(google-default-arguments)
- virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
- void* cookie = nullptr,
- uint32_t flags = 0,
- wp<DeathRecipient>* outRecipient = nullptr);
+ LIBBINDER_EXPORTED virtual status_t unlinkToDeath(const wp<DeathRecipient>& recipient,
+ void* cookie = nullptr, uint32_t flags = 0,
+ wp<DeathRecipient>* outRecipient = nullptr);
- virtual void* attachObject(const void* objectID, void* object, void* cleanupCookie,
- object_cleanup_func func) final;
- virtual void* findObject(const void* objectID) const final;
- virtual void* detachObject(const void* objectID) final;
- void withLock(const std::function<void()>& doWithLock);
- sp<IBinder> lookupOrCreateWeak(const void* objectID, IBinder::object_make_func make,
- const void* makeArgs);
+ LIBBINDER_EXPORTED virtual void* attachObject(const void* objectID, void* object,
+ void* cleanupCookie,
+ object_cleanup_func func) final;
+ LIBBINDER_EXPORTED virtual void* findObject(const void* objectID) const final;
+ LIBBINDER_EXPORTED virtual void* detachObject(const void* objectID) final;
+ LIBBINDER_EXPORTED void withLock(const std::function<void()>& doWithLock);
+ LIBBINDER_EXPORTED sp<IBinder> lookupOrCreateWeak(const void* objectID,
+ IBinder::object_make_func make,
+ const void* makeArgs);
- virtual BBinder* localBinder();
+ LIBBINDER_EXPORTED virtual BBinder* localBinder();
- bool isRequestingSid();
+ LIBBINDER_EXPORTED bool isRequestingSid();
// This must be called before the object is sent to another process. Not thread safe.
- void setRequestingSid(bool requestSid);
+ LIBBINDER_EXPORTED void setRequestingSid(bool requestSid);
- sp<IBinder> getExtension();
+ LIBBINDER_EXPORTED sp<IBinder> getExtension();
// This must be called before the object is sent to another process. Not thread safe.
- void setExtension(const sp<IBinder>& extension);
+ LIBBINDER_EXPORTED void setExtension(const sp<IBinder>& extension);
// This must be called before the object is sent to another process. Not thread safe.
//
@@ -84,35 +82,33 @@
// Appropriate values are:
// SCHED_NORMAL: -20 <= priority <= 19
// SCHED_RR/SCHED_FIFO: 1 <= priority <= 99
- void setMinSchedulerPolicy(int policy, int priority);
- int getMinSchedulerPolicy();
- int getMinSchedulerPriority();
+ LIBBINDER_EXPORTED void setMinSchedulerPolicy(int policy, int priority);
+ LIBBINDER_EXPORTED int getMinSchedulerPolicy();
+ LIBBINDER_EXPORTED int getMinSchedulerPriority();
// Whether realtime scheduling policies are inherited.
- bool isInheritRt();
+ LIBBINDER_EXPORTED bool isInheritRt();
// This must be called before the object is sent to another process. Not thread safe.
- void setInheritRt(bool inheritRt);
+ LIBBINDER_EXPORTED void setInheritRt(bool inheritRt);
- pid_t getDebugPid();
+ LIBBINDER_EXPORTED pid_t getDebugPid();
// Whether this binder has been sent to another process.
- bool wasParceled();
+ LIBBINDER_EXPORTED bool wasParceled();
// Consider this binder as parceled (setup/init-related calls should no
// longer by called. This is automatically set by when this binder is sent
// to another process.
- void setParceled();
+ LIBBINDER_EXPORTED void setParceled();
- [[nodiscard]] status_t setRpcClientDebug(binder::unique_fd clientFd,
- const sp<IBinder>& keepAliveBinder);
+ [[nodiscard]] LIBBINDER_EXPORTED status_t setRpcClientDebug(binder::unique_fd clientFd,
+ const sp<IBinder>& keepAliveBinder);
protected:
- virtual ~BBinder();
+ LIBBINDER_EXPORTED virtual ~BBinder();
// NOLINTNEXTLINE(google-default-arguments)
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
+ LIBBINDER_EXPORTED virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags = 0);
private:
BBinder(const BBinder& o);
@@ -142,17 +138,18 @@
// ---------------------------------------------------------------------------
-class BpRefBase : public virtual RefBase
-{
+class BpRefBase : public virtual RefBase {
protected:
- explicit BpRefBase(const sp<IBinder>& o);
- virtual ~BpRefBase();
- virtual void onFirstRef();
- virtual void onLastStrongRef(const void* id);
- virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
+ LIBBINDER_EXPORTED explicit BpRefBase(const sp<IBinder>& o);
+ LIBBINDER_EXPORTED virtual ~BpRefBase();
+ LIBBINDER_EXPORTED virtual void onFirstRef();
+ LIBBINDER_EXPORTED virtual void onLastStrongRef(const void* id);
+ LIBBINDER_EXPORTED virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
- inline IBinder* remote() const { return mRemote; }
- inline sp<IBinder> remoteStrong() const { return sp<IBinder>::fromExisting(mRemote); }
+ LIBBINDER_EXPORTED inline IBinder* remote() const { return mRemote; }
+ LIBBINDER_EXPORTED inline sp<IBinder> remoteStrong() const {
+ return sp<IBinder>::fromExisting(mRemote);
+ }
private:
BpRefBase(const BpRefBase& o);
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 9f03907..8ac30ba 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -16,6 +16,7 @@
#pragma once
+#include <binder/Common.h>
#include <binder/IBinder.h>
#include <binder/RpcThreads.h>
#include <binder/unique_fd.h>
@@ -38,67 +39,64 @@
using binder_proxy_limit_callback = std::function<void(int)>;
using binder_proxy_warning_callback = std::function<void(int)>;
-class BpBinder : public IBinder
-{
+class BpBinder : public IBinder {
public:
/**
* Return value:
* true - this is associated with a socket RpcSession
* false - (usual) binder over e.g. /dev/binder
*/
- bool isRpcBinder() const;
+ LIBBINDER_EXPORTED bool isRpcBinder() const;
- virtual const String16& getInterfaceDescriptor() const;
- virtual bool isBinderAlive() const;
- virtual status_t pingBinder();
- virtual status_t dump(int fd, const Vector<String16>& args);
+ LIBBINDER_EXPORTED virtual const String16& getInterfaceDescriptor() const;
+ LIBBINDER_EXPORTED virtual bool isBinderAlive() const;
+ LIBBINDER_EXPORTED virtual status_t pingBinder();
+ LIBBINDER_EXPORTED virtual status_t dump(int fd, const Vector<String16>& args);
// NOLINTNEXTLINE(google-default-arguments)
- virtual status_t transact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0) final;
+ LIBBINDER_EXPORTED virtual status_t transact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags = 0) final;
// NOLINTNEXTLINE(google-default-arguments)
- virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
- void* cookie = nullptr,
- uint32_t flags = 0);
+ LIBBINDER_EXPORTED virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
+ void* cookie = nullptr, uint32_t flags = 0);
// NOLINTNEXTLINE(google-default-arguments)
- virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
- void* cookie = nullptr,
- uint32_t flags = 0,
- wp<DeathRecipient>* outRecipient = nullptr);
+ LIBBINDER_EXPORTED virtual status_t unlinkToDeath(const wp<DeathRecipient>& recipient,
+ void* cookie = nullptr, uint32_t flags = 0,
+ wp<DeathRecipient>* outRecipient = nullptr);
- virtual void* attachObject(const void* objectID, void* object, void* cleanupCookie,
- object_cleanup_func func) final;
- virtual void* findObject(const void* objectID) const final;
- virtual void* detachObject(const void* objectID) final;
- void withLock(const std::function<void()>& doWithLock);
- sp<IBinder> lookupOrCreateWeak(const void* objectID, IBinder::object_make_func make,
- const void* makeArgs);
+ LIBBINDER_EXPORTED virtual void* attachObject(const void* objectID, void* object,
+ void* cleanupCookie,
+ object_cleanup_func func) final;
+ LIBBINDER_EXPORTED virtual void* findObject(const void* objectID) const final;
+ LIBBINDER_EXPORTED virtual void* detachObject(const void* objectID) final;
+ LIBBINDER_EXPORTED void withLock(const std::function<void()>& doWithLock);
+ LIBBINDER_EXPORTED sp<IBinder> lookupOrCreateWeak(const void* objectID,
+ IBinder::object_make_func make,
+ const void* makeArgs);
- virtual BpBinder* remoteBinder();
+ LIBBINDER_EXPORTED virtual BpBinder* remoteBinder();
- void sendObituary();
+ LIBBINDER_EXPORTED void sendObituary();
- static uint32_t getBinderProxyCount(uint32_t uid);
- static void getCountByUid(Vector<uint32_t>& uids, Vector<uint32_t>& counts);
- static void enableCountByUid();
- static void disableCountByUid();
- static void setCountByUidEnabled(bool enable);
- static void setBinderProxyCountEventCallback(binder_proxy_limit_callback cbl,
- binder_proxy_warning_callback cbw);
- static void setBinderProxyCountWatermarks(int high, int low, int warning);
- static uint32_t getBinderProxyCount();
+ LIBBINDER_EXPORTED static uint32_t getBinderProxyCount(uint32_t uid);
+ LIBBINDER_EXPORTED static void getCountByUid(Vector<uint32_t>& uids, Vector<uint32_t>& counts);
+ LIBBINDER_EXPORTED static void enableCountByUid();
+ LIBBINDER_EXPORTED static void disableCountByUid();
+ LIBBINDER_EXPORTED static void setCountByUidEnabled(bool enable);
+ LIBBINDER_EXPORTED static void setBinderProxyCountEventCallback(
+ binder_proxy_limit_callback cbl, binder_proxy_warning_callback cbw);
+ LIBBINDER_EXPORTED static void setBinderProxyCountWatermarks(int high, int low, int warning);
+ LIBBINDER_EXPORTED static uint32_t getBinderProxyCount();
- std::optional<int32_t> getDebugBinderHandle() const;
+ LIBBINDER_EXPORTED std::optional<int32_t> getDebugBinderHandle() const;
// Start recording transactions to the unique_fd.
// See RecordedTransaction.h for more details.
- status_t startRecordingBinder(const binder::unique_fd& fd);
+ LIBBINDER_EXPORTED status_t startRecordingBinder(const binder::unique_fd& fd);
// Stop the current recording.
- status_t stopRecordingBinder();
+ LIBBINDER_EXPORTED status_t stopRecordingBinder();
class ObjectManager {
public:
@@ -150,7 +148,9 @@
const BpBinder* mBinder;
};
- const PrivateAccessor getPrivateAccessor() const { return PrivateAccessor(this); }
+ LIBBINDER_EXPORTED const PrivateAccessor getPrivateAccessor() const {
+ return PrivateAccessor(this);
+ }
private:
friend PrivateAccessor;
diff --git a/libs/binder/include/binder/Common.h b/libs/binder/include/binder/Common.h
new file mode 100644
index 0000000..ed10154
--- /dev/null
+++ b/libs/binder/include/binder/Common.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 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
+
+// libbinder is built with symbol hidden by default. To add a new symbol to the
+// ABI, you must annotate it with this LIBBINDER_EXPORTED macro. When not
+// building libbinder (e.g. when another binary includes a libbinder header),
+// this macro is a no-op.
+//
+// Examples:
+//
+// // Export a function.
+// LIBBINDER_EXPORTED void someFunction();
+//
+// // Export a subset of the symbols for a class.
+// class SomeClassA {
+// public:
+// LIBBINDER_EXPORTED SomeClassA();
+//
+// LIBBINDER_EXPORTED SomeMethod();
+// }
+//
+// // Export all the symbols for a class, even private symbols.
+// class LIBBINDER_EXPORTED SomeClassB {};
+//
+// For a more detailed explanation of this strategy, see
+// https://www.gnu.org/software/gnulib/manual/html_node/Exported-Symbols-of-Shared-Libraries.html
+#if BUILDING_LIBBINDER
+#define LIBBINDER_EXPORTED __attribute__((__visibility__("default")))
+#else
+#define LIBBINDER_EXPORTED
+#endif
+
+// For stuff that is exported but probably shouldn't be. It behaves the exact
+// same way as LIBBINDER_EXPORTED, only exists to help track what we want
+// eventually remove.
+//
+// Needed, at least in part, because the test binaries are using internal
+// headers and accessing these symbols directly.
+#define LIBBINDER_INTERNAL_EXPORTED LIBBINDER_EXPORTED
diff --git a/libs/binder/include/binder/Delegate.h b/libs/binder/include/binder/Delegate.h
index ad5a6a3..7aaa7a0 100644
--- a/libs/binder/include/binder/Delegate.h
+++ b/libs/binder/include/binder/Delegate.h
@@ -16,6 +16,7 @@
#pragma once
+#include <binder/Common.h>
#include <binder/IBinder.h>
#if !defined(__BIONIC__) && defined(BINDER_ENABLE_LIBLOG_ASSERT)
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index dad9a17..17248ce 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -16,6 +16,7 @@
#pragma once
+#include <binder/Common.h>
#include <binder/unique_fd.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
@@ -48,8 +49,7 @@
* (method calls, property get and set) is down through a low-level
* protocol implemented on top of the transact() API.
*/
-class [[clang::lto_visibility_public]] IBinder : public virtual RefBase
-{
+class [[clang::lto_visibility_public]] LIBBINDER_EXPORTED IBinder : public virtual RefBase {
public:
enum {
FIRST_CALL_TRANSACTION = 0x00000001,
diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
index ac845bc..30e005c 100644
--- a/libs/binder/include/binder/IInterface.h
+++ b/libs/binder/include/binder/IInterface.h
@@ -17,6 +17,7 @@
#pragma once
#include <binder/Binder.h>
+#include <binder/Common.h>
#include <assert.h>
@@ -24,8 +25,7 @@
// ----------------------------------------------------------------------
-class IInterface : public virtual RefBase
-{
+class LIBBINDER_EXPORTED IInterface : public virtual RefBase {
public:
IInterface();
static sp<IBinder> asBinder(const IInterface*);
@@ -66,9 +66,8 @@
// ----------------------------------------------------------------------
-template<typename INTERFACE>
-class BnInterface : public INTERFACE, public BBinder
-{
+template <typename INTERFACE>
+class LIBBINDER_EXPORTED BnInterface : public INTERFACE, public BBinder {
public:
virtual sp<IInterface> queryLocalInterface(const String16& _descriptor);
virtual const String16& getInterfaceDescriptor() const;
@@ -80,9 +79,8 @@
// ----------------------------------------------------------------------
-template<typename INTERFACE>
-class BpInterface : public INTERFACE, public BpRefBase
-{
+template <typename INTERFACE>
+class LIBBINDER_EXPORTED BpInterface : public INTERFACE, public BpRefBase {
public:
explicit BpInterface(const sp<IBinder>& remote);
typedef INTERFACE BaseInterface;
diff --git a/libs/binder/include/binder/IMemory.h b/libs/binder/include/binder/IMemory.h
index d8b7ec1..12c5c61 100644
--- a/libs/binder/include/binder/IMemory.h
+++ b/libs/binder/include/binder/IMemory.h
@@ -22,14 +22,14 @@
#include <utils/RefBase.h>
#include <utils/Errors.h>
+#include <binder/Common.h>
#include <binder/IInterface.h>
namespace android {
// ----------------------------------------------------------------------------
-class IMemoryHeap : public IInterface
-{
+class LIBBINDER_EXPORTED IMemoryHeap : public IInterface {
public:
DECLARE_META_INTERFACE(MemoryHeap)
@@ -50,8 +50,7 @@
size_t virtualSize() const { return getSize(); }
};
-class BnMemoryHeap : public BnInterface<IMemoryHeap>
-{
+class LIBBINDER_EXPORTED BnMemoryHeap : public BnInterface<IMemoryHeap> {
public:
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t onTransact(
@@ -67,8 +66,7 @@
// ----------------------------------------------------------------------------
-class IMemory : public IInterface
-{
+class LIBBINDER_EXPORTED IMemory : public IInterface {
public:
DECLARE_META_INTERFACE(Memory)
@@ -105,8 +103,7 @@
void* fastPointer(const sp<IBinder>& heap, ssize_t offset) const;
};
-class BnMemory : public BnInterface<IMemory>
-{
+class LIBBINDER_EXPORTED BnMemory : public BnInterface<IMemory> {
public:
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t onTransact(
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index dc5b1a1..09ab442 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -16,9 +16,10 @@
#pragma once
-#include <utils/Errors.h>
+#include <binder/Common.h>
#include <binder/Parcel.h>
#include <binder/ProcessState.h>
+#include <utils/Errors.h>
#include <utils/Vector.h>
#if defined(_WIN32)
@@ -32,13 +33,12 @@
* Kernel binder thread state. All operations here refer to kernel binder. This
* object is allocated per-thread.
*/
-class IPCThreadState
-{
+class IPCThreadState {
public:
using CallRestriction = ProcessState::CallRestriction;
- static IPCThreadState* self();
- static IPCThreadState* selfOrNull(); // self(), but won't instantiate
+ LIBBINDER_EXPORTED static IPCThreadState* self();
+ LIBBINDER_EXPORTED static IPCThreadState* selfOrNull(); // self(), but won't instantiate
// Freeze or unfreeze the binder interface to a specific process. When freezing, this method
// will block up to timeout_ms to process pending transactions directed to pid. Unfreeze
@@ -52,182 +52,175 @@
// binder transactions to be processed.
//
// returns: 0 in case of success, a value < 0 in case of error
- static status_t freeze(pid_t pid, bool enabled, uint32_t timeout_ms);
+ LIBBINDER_EXPORTED static status_t freeze(pid_t pid, bool enabled, uint32_t timeout_ms);
// Provide information about the state of a frozen process
- static status_t getProcessFreezeInfo(pid_t pid, uint32_t *sync_received,
- uint32_t *async_received);
+ LIBBINDER_EXPORTED static status_t getProcessFreezeInfo(pid_t pid, uint32_t* sync_received,
+ uint32_t* async_received);
- status_t clearLastError();
+ LIBBINDER_EXPORTED status_t clearLastError();
- /**
- * Returns the PID of the process which has made the current binder
- * call. If not in a binder call, this will return getpid.
- *
- * Warning: oneway transactions do not receive PID. Even if you expect
- * a transaction to be synchronous, a misbehaving client could send it
- * as an asynchronous call and result in a 0 PID here. Additionally, if
- * there is a race and the calling process dies, the PID may still be
- * 0 for a synchronous call.
- */
- [[nodiscard]] pid_t getCallingPid() const;
+ /**
+ * Returns the PID of the process which has made the current binder
+ * call. If not in a binder call, this will return getpid.
+ *
+ * Warning: oneway transactions do not receive PID. Even if you expect
+ * a transaction to be synchronous, a misbehaving client could send it
+ * as an asynchronous call and result in a 0 PID here. Additionally, if
+ * there is a race and the calling process dies, the PID may still be
+ * 0 for a synchronous call.
+ */
+ [[nodiscard]] LIBBINDER_EXPORTED pid_t getCallingPid() const;
- /**
- * Returns the SELinux security identifier of the process which has
- * made the current binder call. If not in a binder call this will
- * return nullptr. If this isn't requested with
- * Binder::setRequestingSid, it will also return nullptr.
- *
- * This can't be restored once it's cleared, and it does not return the
- * context of the current process when not in a binder call.
- */
- [[nodiscard]] const char* getCallingSid() const;
+ /**
+ * Returns the SELinux security identifier of the process which has
+ * made the current binder call. If not in a binder call this will
+ * return nullptr. If this isn't requested with
+ * Binder::setRequestingSid, it will also return nullptr.
+ *
+ * This can't be restored once it's cleared, and it does not return the
+ * context of the current process when not in a binder call.
+ */
+ [[nodiscard]] LIBBINDER_EXPORTED const char* getCallingSid() const;
- /**
- * Returns the UID of the process which has made the current binder
- * call. If not in a binder call, this will return 0.
- */
- [[nodiscard]] uid_t getCallingUid() const;
+ /**
+ * Returns the UID of the process which has made the current binder
+ * call. If not in a binder call, this will return 0.
+ */
+ [[nodiscard]] LIBBINDER_EXPORTED uid_t getCallingUid() const;
- /**
- * Make it an abort to rely on getCalling* for a section of
- * execution.
- *
- * Usage:
- * IPCThreadState::SpGuard guard {
- * .address = __builtin_frame_address(0),
- * .context = "...",
- * };
- * const auto* orig = pushGetCallingSpGuard(&guard);
- * {
- * // will abort if you call getCalling*, unless you are
- * // serving a nested binder transaction
- * }
- * restoreCallingSpGuard(orig);
- */
- struct SpGuard {
- const void* address;
- const char* context;
- };
- const SpGuard* pushGetCallingSpGuard(const SpGuard* guard);
- void restoreGetCallingSpGuard(const SpGuard* guard);
- /**
- * Used internally by getCalling*. Can also be used to assert that
- * you are in a binder context (getCalling* is valid). This is
- * intentionally not exposed as a boolean API since code should be
- * written to know its environment.
- */
- void checkContextIsBinderForUse(const char* use) const;
+ /**
+ * Make it an abort to rely on getCalling* for a section of
+ * execution.
+ *
+ * Usage:
+ * IPCThreadState::SpGuard guard {
+ * .address = __builtin_frame_address(0),
+ * .context = "...",
+ * };
+ * const auto* orig = pushGetCallingSpGuard(&guard);
+ * {
+ * // will abort if you call getCalling*, unless you are
+ * // serving a nested binder transaction
+ * }
+ * restoreCallingSpGuard(orig);
+ */
+ struct SpGuard {
+ const void* address;
+ const char* context;
+ };
+ LIBBINDER_EXPORTED const SpGuard* pushGetCallingSpGuard(const SpGuard* guard);
+ LIBBINDER_EXPORTED void restoreGetCallingSpGuard(const SpGuard* guard);
+ /**
+ * Used internally by getCalling*. Can also be used to assert that
+ * you are in a binder context (getCalling* is valid). This is
+ * intentionally not exposed as a boolean API since code should be
+ * written to know its environment.
+ */
+ LIBBINDER_EXPORTED void checkContextIsBinderForUse(const char* use) const;
- void setStrictModePolicy(int32_t policy);
- int32_t getStrictModePolicy() const;
+ LIBBINDER_EXPORTED void setStrictModePolicy(int32_t policy);
+ LIBBINDER_EXPORTED int32_t getStrictModePolicy() const;
- // See Binder#setCallingWorkSourceUid in Binder.java.
- int64_t setCallingWorkSourceUid(uid_t uid);
- // Internal only. Use setCallingWorkSourceUid(uid) instead.
- int64_t setCallingWorkSourceUidWithoutPropagation(uid_t uid);
- // See Binder#getCallingWorkSourceUid in Binder.java.
- uid_t getCallingWorkSourceUid() const;
- // See Binder#clearCallingWorkSource in Binder.java.
- int64_t clearCallingWorkSource();
- // See Binder#restoreCallingWorkSource in Binder.java.
- void restoreCallingWorkSource(int64_t token);
- void clearPropagateWorkSource();
- bool shouldPropagateWorkSource() const;
+ // See Binder#setCallingWorkSourceUid in Binder.java.
+ LIBBINDER_EXPORTED int64_t setCallingWorkSourceUid(uid_t uid);
+ // Internal only. Use setCallingWorkSourceUid(uid) instead.
+ LIBBINDER_EXPORTED int64_t setCallingWorkSourceUidWithoutPropagation(uid_t uid);
+ // See Binder#getCallingWorkSourceUid in Binder.java.
+ LIBBINDER_EXPORTED uid_t getCallingWorkSourceUid() const;
+ // See Binder#clearCallingWorkSource in Binder.java.
+ LIBBINDER_EXPORTED int64_t clearCallingWorkSource();
+ // See Binder#restoreCallingWorkSource in Binder.java.
+ LIBBINDER_EXPORTED void restoreCallingWorkSource(int64_t token);
+ LIBBINDER_EXPORTED void clearPropagateWorkSource();
+ LIBBINDER_EXPORTED bool shouldPropagateWorkSource() const;
- void setLastTransactionBinderFlags(int32_t flags);
- int32_t getLastTransactionBinderFlags() const;
+ LIBBINDER_EXPORTED void setLastTransactionBinderFlags(int32_t flags);
+ LIBBINDER_EXPORTED int32_t getLastTransactionBinderFlags() const;
- void setCallRestriction(CallRestriction restriction);
- CallRestriction getCallRestriction() const;
+ LIBBINDER_EXPORTED void setCallRestriction(CallRestriction restriction);
+ LIBBINDER_EXPORTED CallRestriction getCallRestriction() const;
- int64_t clearCallingIdentity();
- // Restores PID/UID (not SID)
- void restoreCallingIdentity(int64_t token);
- bool hasExplicitIdentity();
+ LIBBINDER_EXPORTED int64_t clearCallingIdentity();
+ // Restores PID/UID (not SID)
+ LIBBINDER_EXPORTED void restoreCallingIdentity(int64_t token);
+ LIBBINDER_EXPORTED bool hasExplicitIdentity();
- // For main functions - dangerous for libraries to use
- status_t setupPolling(int* fd);
- status_t handlePolledCommands();
- void flushCommands();
- bool flushIfNeeded();
+ // For main functions - dangerous for libraries to use
+ LIBBINDER_EXPORTED status_t setupPolling(int* fd);
+ LIBBINDER_EXPORTED status_t handlePolledCommands();
+ LIBBINDER_EXPORTED void flushCommands();
+ LIBBINDER_EXPORTED bool flushIfNeeded();
- // Adds the current thread into the binder threadpool.
- //
- // This is in addition to any threads which are started
- // with startThreadPool. Libraries should not call this
- // function, as they may be loaded into processes which
- // try to configure the threadpool differently.
- void joinThreadPool(bool isMain = true);
-
- // Stop the local process.
- void stopProcess(bool immediate = true);
-
- status_t transact(int32_t handle,
- uint32_t code, const Parcel& data,
+ // Adds the current thread into the binder threadpool.
+ //
+ // This is in addition to any threads which are started
+ // with startThreadPool. Libraries should not call this
+ // function, as they may be loaded into processes which
+ // try to configure the threadpool differently.
+ LIBBINDER_EXPORTED void joinThreadPool(bool isMain = true);
+
+ // Stop the local process.
+ LIBBINDER_EXPORTED void stopProcess(bool immediate = true);
+
+ LIBBINDER_EXPORTED status_t transact(int32_t handle, uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags);
- void incStrongHandle(int32_t handle, BpBinder *proxy);
- void decStrongHandle(int32_t handle);
- void incWeakHandle(int32_t handle, BpBinder *proxy);
- void decWeakHandle(int32_t handle);
- status_t attemptIncStrongHandle(int32_t handle);
- static void expungeHandle(int32_t handle, IBinder* binder);
- status_t requestDeathNotification( int32_t handle,
- BpBinder* proxy);
- status_t clearDeathNotification( int32_t handle,
- BpBinder* proxy);
+ LIBBINDER_EXPORTED void incStrongHandle(int32_t handle, BpBinder* proxy);
+ LIBBINDER_EXPORTED void decStrongHandle(int32_t handle);
+ LIBBINDER_EXPORTED void incWeakHandle(int32_t handle, BpBinder* proxy);
+ LIBBINDER_EXPORTED void decWeakHandle(int32_t handle);
+ LIBBINDER_EXPORTED status_t attemptIncStrongHandle(int32_t handle);
+ LIBBINDER_EXPORTED static void expungeHandle(int32_t handle, IBinder* binder);
+ LIBBINDER_EXPORTED status_t requestDeathNotification(int32_t handle, BpBinder* proxy);
+ LIBBINDER_EXPORTED status_t clearDeathNotification(int32_t handle, BpBinder* proxy);
- static void shutdown();
+ LIBBINDER_EXPORTED static void shutdown();
// Call this to disable switching threads to background scheduling when
// receiving incoming IPC calls. This is specifically here for the
// Android system process, since it expects to have background apps calling
// in to it but doesn't want to acquire locks in its services while in
// the background.
- static void disableBackgroundScheduling(bool disable);
- bool backgroundSchedulingDisabled();
+ LIBBINDER_EXPORTED static void disableBackgroundScheduling(bool disable);
+ LIBBINDER_EXPORTED bool backgroundSchedulingDisabled();
- // Call blocks until the number of executing binder threads is less than
- // the maximum number of binder threads threads allowed for this process.
- void blockUntilThreadAvailable();
+ // Call blocks until the number of executing binder threads is less than
+ // the maximum number of binder threads threads allowed for this process.
+ LIBBINDER_EXPORTED void blockUntilThreadAvailable();
- // Service manager registration
- void setTheContextObject(const sp<BBinder>& obj);
+ // Service manager registration
+ LIBBINDER_EXPORTED void setTheContextObject(const sp<BBinder>& obj);
- // WARNING: DO NOT USE THIS API
- //
- // Returns a pointer to the stack from the last time a transaction
- // was initiated by the kernel. Used to compare when making nested
- // calls between multiple different transports.
- const void* getServingStackPointer() const;
+ // WARNING: DO NOT USE THIS API
+ //
+ // Returns a pointer to the stack from the last time a transaction
+ // was initiated by the kernel. Used to compare when making nested
+ // calls between multiple different transports.
+ LIBBINDER_EXPORTED const void* getServingStackPointer() const;
- // The work source represents the UID of the process we should attribute the transaction
- // to. We use -1 to specify that the work source was not set using #setWorkSource.
- //
- // This constant needs to be kept in sync with Binder.UNSET_WORKSOURCE from the Java
- // side.
- static const int32_t kUnsetWorkSource = -1;
+ // The work source represents the UID of the process we should attribute the transaction
+ // to. We use -1 to specify that the work source was not set using #setWorkSource.
+ //
+ // This constant needs to be kept in sync with Binder.UNSET_WORKSOURCE from the Java
+ // side.
+ LIBBINDER_EXPORTED static const int32_t kUnsetWorkSource = -1;
+
private:
- IPCThreadState();
- ~IPCThreadState();
+ IPCThreadState();
+ ~IPCThreadState();
- status_t sendReply(const Parcel& reply, uint32_t flags);
- status_t waitForResponse(Parcel *reply,
- status_t *acquireResult=nullptr);
- status_t talkWithDriver(bool doReceive=true);
- status_t writeTransactionData(int32_t cmd,
- uint32_t binderFlags,
- int32_t handle,
- uint32_t code,
- const Parcel& data,
- status_t* statusBuffer);
- status_t getAndExecuteCommand();
- status_t executeCommand(int32_t command);
- void processPendingDerefs();
- void processPostWriteDerefs();
+ status_t sendReply(const Parcel& reply, uint32_t flags);
+ status_t waitForResponse(Parcel* reply, status_t* acquireResult = nullptr);
+ status_t talkWithDriver(bool doReceive = true);
+ status_t writeTransactionData(int32_t cmd, uint32_t binderFlags, int32_t handle, uint32_t code,
+ const Parcel& data, status_t* statusBuffer);
+ status_t getAndExecuteCommand();
+ status_t executeCommand(int32_t command);
+ void processPendingDerefs();
+ void processPostWriteDerefs();
- void clearCaller();
+ void clearCaller();
static void threadDestructor(void *st);
static void freeBuffer(const uint8_t* data, size_t dataSize, const binder_size_t* objects,
diff --git a/libs/binder/include/binder/IPermissionController.h b/libs/binder/include/binder/IPermissionController.h
index a4f93d9..2bf9e71 100644
--- a/libs/binder/include/binder/IPermissionController.h
+++ b/libs/binder/include/binder/IPermissionController.h
@@ -18,6 +18,7 @@
#ifndef __ANDROID_VNDK__
+#include <binder/Common.h>
#include <binder/IInterface.h>
#include <stdlib.h>
@@ -25,8 +26,7 @@
// ----------------------------------------------------------------------
-class IPermissionController : public IInterface
-{
+class LIBBINDER_EXPORTED IPermissionController : public IInterface {
public:
DECLARE_META_INTERFACE(PermissionController)
@@ -51,8 +51,7 @@
// ----------------------------------------------------------------------
-class BnPermissionController : public BnInterface<IPermissionController>
-{
+class LIBBINDER_EXPORTED BnPermissionController : public BnInterface<IPermissionController> {
public:
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t onTransact( uint32_t code,
diff --git a/libs/binder/include/binder/IResultReceiver.h b/libs/binder/include/binder/IResultReceiver.h
index 5434445..b72cf11 100644
--- a/libs/binder/include/binder/IResultReceiver.h
+++ b/libs/binder/include/binder/IResultReceiver.h
@@ -16,14 +16,14 @@
#pragma once
+#include <binder/Common.h>
#include <binder/IInterface.h>
namespace android {
// ----------------------------------------------------------------------
-class IResultReceiver : public IInterface
-{
+class LIBBINDER_EXPORTED IResultReceiver : public IInterface {
public:
DECLARE_META_INTERFACE(ResultReceiver)
@@ -36,8 +36,7 @@
// ----------------------------------------------------------------------
-class BnResultReceiver : public BnInterface<IResultReceiver>
-{
+class LIBBINDER_EXPORTED BnResultReceiver : public BnInterface<IResultReceiver> {
public:
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t onTransact( uint32_t code,
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 486bdfb..5fb7307 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -15,6 +15,7 @@
*/
#pragma once
+#include <binder/Common.h>
#include <binder/IInterface.h>
#include <utils/Vector.h>
#include <utils/String16.h>
@@ -29,8 +30,7 @@
*
* IInterface is only for legacy ABI compatibility
*/
-class IServiceManager : public IInterface
-{
+class LIBBINDER_EXPORTED IServiceManager : public IInterface {
public:
// for ABI compatibility
virtual const String16& getInterfaceDescriptor() const;
@@ -149,7 +149,7 @@
virtual std::vector<ServiceDebugInfo> getServiceDebugInfo() = 0;
};
-sp<IServiceManager> defaultServiceManager();
+LIBBINDER_EXPORTED sp<IServiceManager> defaultServiceManager();
/**
* Directly set the default service manager. Only used for testing.
@@ -157,7 +157,7 @@
* *before* any call to defaultServiceManager(); if the latter is
* called first, setDefaultServiceManager() will abort.
*/
-void setDefaultServiceManager(const sp<IServiceManager>& sm);
+LIBBINDER_EXPORTED void setDefaultServiceManager(const sp<IServiceManager>& sm);
template<typename INTERFACE>
sp<INTERFACE> waitForService(const String16& name) {
@@ -207,13 +207,14 @@
return NAME_NOT_FOUND;
}
-void* openDeclaredPassthroughHal(const String16& interface, const String16& instance, int flag);
+LIBBINDER_EXPORTED void* openDeclaredPassthroughHal(const String16& interface,
+ const String16& instance, int flag);
-bool checkCallingPermission(const String16& permission);
-bool checkCallingPermission(const String16& permission,
- int32_t* outPid, int32_t* outUid);
-bool checkPermission(const String16& permission, pid_t pid, uid_t uid,
- bool logPermissionFailure = true);
+LIBBINDER_EXPORTED bool checkCallingPermission(const String16& permission);
+LIBBINDER_EXPORTED bool checkCallingPermission(const String16& permission, int32_t* outPid,
+ int32_t* outUid);
+LIBBINDER_EXPORTED bool checkPermission(const String16& permission, pid_t pid, uid_t uid,
+ bool logPermissionFailure = true);
#ifndef __ANDROID__
// Create an IServiceManager that delegates the service manager on the device via adb.
@@ -233,7 +234,7 @@
struct RpcDelegateServiceManagerOptions {
std::optional<size_t> maxOutgoingConnections;
};
-sp<IServiceManager> createRpcDelegateServiceManager(
+LIBBINDER_EXPORTED sp<IServiceManager> createRpcDelegateServiceManager(
const RpcDelegateServiceManagerOptions& options);
#endif
diff --git a/libs/binder/include/binder/IShellCallback.h b/libs/binder/include/binder/IShellCallback.h
index 6d3fe4a..4324afc 100644
--- a/libs/binder/include/binder/IShellCallback.h
+++ b/libs/binder/include/binder/IShellCallback.h
@@ -16,14 +16,14 @@
#pragma once
+#include <binder/Common.h>
#include <binder/IInterface.h>
namespace android {
// ----------------------------------------------------------------------
-class IShellCallback : public IInterface
-{
+class LIBBINDER_EXPORTED IShellCallback : public IInterface {
public:
DECLARE_META_INTERFACE(ShellCallback)
@@ -37,8 +37,7 @@
// ----------------------------------------------------------------------
-class BnShellCallback : public BnInterface<IShellCallback>
-{
+class LIBBINDER_EXPORTED BnShellCallback : public BnInterface<IShellCallback> {
public:
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t onTransact( uint32_t code,
diff --git a/libs/binder/include/binder/LazyServiceRegistrar.h b/libs/binder/include/binder/LazyServiceRegistrar.h
index bda3d19..3436b11 100644
--- a/libs/binder/include/binder/LazyServiceRegistrar.h
+++ b/libs/binder/include/binder/LazyServiceRegistrar.h
@@ -18,6 +18,7 @@
#include <functional>
+#include <binder/Common.h>
#include <binder/IServiceManager.h>
#include <binder/Status.h>
#include <utils/StrongPointer.h>
@@ -42,70 +43,71 @@
* For more information on init .rc configuration, see system/core/init/README.md
**/
class LazyServiceRegistrar {
- public:
- static LazyServiceRegistrar& getInstance();
- status_t registerService(const sp<IBinder>& service,
- const std::string& name = "default",
- bool allowIsolated = false,
- int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
- /**
- * Force the service to persist, even when it has 0 clients.
- * If setting this flag from the server side, make sure to do so before calling
- * registerService, or there may be a race with the default dynamic shutdown.
- *
- * This should only be used if it is every eventually set to false. If a
- * service needs to persist but doesn't need to dynamically shut down,
- * prefer to control it with another mechanism such as ctl.start.
- */
- void forcePersist(bool persist);
+public:
+ LIBBINDER_EXPORTED static LazyServiceRegistrar& getInstance();
+ LIBBINDER_EXPORTED status_t
+ registerService(const sp<IBinder>& service, const std::string& name = "default",
+ bool allowIsolated = false,
+ int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
+ /**
+ * Force the service to persist, even when it has 0 clients.
+ * If setting this flag from the server side, make sure to do so before calling
+ * registerService, or there may be a race with the default dynamic shutdown.
+ *
+ * This should only be used if it is every eventually set to false. If a
+ * service needs to persist but doesn't need to dynamically shut down,
+ * prefer to control it with another mechanism such as ctl.start.
+ */
+ LIBBINDER_EXPORTED void forcePersist(bool persist);
- /**
- * 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.
- *
- * 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.
- *
- * This method should be called before 'registerService' to avoid races.
- */
- void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback);
+ /**
+ * 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.
+ *
+ * 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.
+ *
+ * This method should be called before 'registerService' to avoid races.
+ */
+ LIBBINDER_EXPORTED void setActiveServicesCallback(
+ const std::function<bool(bool)>& activeServicesCallback);
- /**
- * Try to unregister all services previously registered with 'registerService'.
- * Returns 'true' if successful. This should only be called within the callback registered by
- * setActiveServicesCallback.
- */
- bool tryUnregister();
+ /**
+ * Try to unregister all services previously registered with 'registerService'.
+ * Returns 'true' if successful. This should only be called within the callback registered by
+ * setActiveServicesCallback.
+ */
+ LIBBINDER_EXPORTED bool tryUnregister();
- /**
- * 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 reRegister();
+ /**
+ * 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).
+ */
+ LIBBINDER_EXPORTED void reRegister();
- /**
- * Create a second instance of lazy service registrar.
- *
- * WARNING: dangerous! DO NOT USE THIS - LazyServiceRegistrar
- * should be single-instanced, so that the service will only
- * shut down when all services are unused. A separate instance
- * is only used to test race conditions.
- */
- static LazyServiceRegistrar createExtraTestInstance();
+ /**
+ * Create a second instance of lazy service registrar.
+ *
+ * WARNING: dangerous! DO NOT USE THIS - LazyServiceRegistrar
+ * should be single-instanced, so that the service will only
+ * shut down when all services are unused. A separate instance
+ * is only used to test race conditions.
+ */
+ LIBBINDER_EXPORTED static LazyServiceRegistrar createExtraTestInstance();
- private:
- std::shared_ptr<internal::ClientCounterCallback> mClientCC;
- LazyServiceRegistrar();
+private:
+ std::shared_ptr<internal::ClientCounterCallback> mClientCC;
+ LazyServiceRegistrar();
};
} // namespace binder
diff --git a/libs/binder/include/binder/MemoryBase.h b/libs/binder/include/binder/MemoryBase.h
index 61a029c..04cd1a4 100644
--- a/libs/binder/include/binder/MemoryBase.h
+++ b/libs/binder/include/binder/MemoryBase.h
@@ -19,6 +19,7 @@
#include <stdlib.h>
#include <stdint.h>
+#include <binder/Common.h>
#include <binder/IMemory.h>
@@ -26,8 +27,7 @@
// ---------------------------------------------------------------------------
-class MemoryBase : public BnMemory
-{
+class LIBBINDER_EXPORTED MemoryBase : public BnMemory {
public:
MemoryBase(const sp<IMemoryHeap>& heap, ssize_t offset, size_t size);
virtual ~MemoryBase();
diff --git a/libs/binder/include/binder/MemoryDealer.h b/libs/binder/include/binder/MemoryDealer.h
index 3f7dd11..b979da5 100644
--- a/libs/binder/include/binder/MemoryDealer.h
+++ b/libs/binder/include/binder/MemoryDealer.h
@@ -19,6 +19,7 @@
#include <stdint.h>
#include <sys/types.h>
+#include <binder/Common.h>
#include <binder/IMemory.h>
#include <binder/MemoryHeapBase.h>
@@ -29,33 +30,32 @@
// ----------------------------------------------------------------------------
-class MemoryDealer : public RefBase
-{
+class MemoryDealer : public RefBase {
public:
- explicit MemoryDealer(size_t size, const char* name = nullptr,
- uint32_t flags = 0 /* or bits such as MemoryHeapBase::READ_ONLY */ );
+ LIBBINDER_EXPORTED explicit MemoryDealer(
+ size_t size, const char* name = nullptr,
+ uint32_t flags = 0 /* or bits such as MemoryHeapBase::READ_ONLY */);
- virtual sp<IMemory> allocate(size_t size);
- virtual void dump(const char* what) const;
+ LIBBINDER_EXPORTED virtual sp<IMemory> allocate(size_t size);
+ LIBBINDER_EXPORTED virtual void dump(const char* what) const;
// allocations are aligned to some value. return that value so clients can account for it.
- static size_t getAllocationAlignment();
+ LIBBINDER_EXPORTED static size_t getAllocationAlignment();
sp<IMemoryHeap> getMemoryHeap() const { return heap(); }
protected:
- virtual ~MemoryDealer();
+ LIBBINDER_EXPORTED virtual ~MemoryDealer();
private:
friend class Allocation;
virtual void deallocate(size_t offset);
- const sp<IMemoryHeap>& heap() const;
+ LIBBINDER_EXPORTED const sp<IMemoryHeap>& heap() const;
SimpleBestFitAllocator* allocator() const;
sp<IMemoryHeap> mHeap;
SimpleBestFitAllocator* mAllocator;
};
-
// ----------------------------------------------------------------------------
} // namespace android
diff --git a/libs/binder/include/binder/MemoryHeapBase.h b/libs/binder/include/binder/MemoryHeapBase.h
index c7177bd..ff2d09f 100644
--- a/libs/binder/include/binder/MemoryHeapBase.h
+++ b/libs/binder/include/binder/MemoryHeapBase.h
@@ -19,6 +19,7 @@
#include <stdlib.h>
#include <stdint.h>
+#include <binder/Common.h>
#include <binder/IMemory.h>
@@ -26,8 +27,7 @@
// ---------------------------------------------------------------------------
-class MemoryHeapBase : public BnMemoryHeap
-{
+class MemoryHeapBase : public BnMemoryHeap {
public:
static constexpr auto MEMFD_ALLOW_SEALING_FLAG = 0x00000800;
enum {
@@ -56,42 +56,44 @@
* maps the memory referenced by fd. but DOESN'T take ownership
* of the filedescriptor (it makes a copy with dup()
*/
- MemoryHeapBase(int fd, size_t size, uint32_t flags = 0, off_t offset = 0);
+ LIBBINDER_EXPORTED MemoryHeapBase(int fd, size_t size, uint32_t flags = 0, off_t offset = 0);
/*
* maps memory from the given device
*/
- explicit MemoryHeapBase(const char* device, size_t size = 0, uint32_t flags = 0);
+ LIBBINDER_EXPORTED explicit MemoryHeapBase(const char* device, size_t size = 0,
+ uint32_t flags = 0);
/*
* maps memory from ashmem, with the given name for debugging
* if the READ_ONLY flag is set, the memory will be writeable by the calling process,
* but not by others. this is NOT the case with the other ctors.
*/
- explicit MemoryHeapBase(size_t size, uint32_t flags = 0, char const* name = nullptr);
+ LIBBINDER_EXPORTED explicit MemoryHeapBase(size_t size, uint32_t flags = 0,
+ char const* name = nullptr);
- virtual ~MemoryHeapBase();
+ LIBBINDER_EXPORTED virtual ~MemoryHeapBase();
/* implement IMemoryHeap interface */
- int getHeapID() const override;
+ LIBBINDER_EXPORTED int getHeapID() const override;
/* virtual address of the heap. returns MAP_FAILED in case of error */
- void* getBase() const override;
+ LIBBINDER_EXPORTED void* getBase() const override;
- size_t getSize() const override;
- uint32_t getFlags() const override;
- off_t getOffset() const override;
+ LIBBINDER_EXPORTED size_t getSize() const override;
+ LIBBINDER_EXPORTED uint32_t getFlags() const override;
+ LIBBINDER_EXPORTED off_t getOffset() const override;
- const char* getDevice() const;
+ LIBBINDER_EXPORTED const char* getDevice() const;
/* this closes this heap -- use carefully */
- void dispose();
+ LIBBINDER_EXPORTED void dispose();
protected:
- MemoryHeapBase();
+ LIBBINDER_EXPORTED MemoryHeapBase();
// init() takes ownership of fd
- status_t init(int fd, void *base, size_t size,
- int flags = 0, const char* device = nullptr);
+ LIBBINDER_EXPORTED status_t init(int fd, void* base, size_t size, int flags = 0,
+ const char* device = nullptr);
private:
status_t mapfd(int fd, bool writeableByCaller, size_t size, off_t offset = 0);
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index eb73037..5cc0830 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -34,6 +34,7 @@
#include <utils/String16.h>
#include <utils/Vector.h>
+#include <binder/Common.h>
#include <binder/IInterface.h>
#include <binder/Parcelable.h>
@@ -68,73 +69,74 @@
class ReadableBlob;
class WritableBlob;
- Parcel();
- ~Parcel();
-
- const uint8_t* data() const;
- size_t dataSize() const;
- size_t dataAvail() const;
- size_t dataPosition() const;
- size_t dataCapacity() const;
- size_t dataBufferSize() const;
+ LIBBINDER_EXPORTED Parcel();
+ LIBBINDER_EXPORTED ~Parcel();
- status_t setDataSize(size_t size);
+ LIBBINDER_EXPORTED const uint8_t* data() const;
+ LIBBINDER_EXPORTED size_t dataSize() const;
+ LIBBINDER_EXPORTED size_t dataAvail() const;
+ LIBBINDER_EXPORTED size_t dataPosition() const;
+ LIBBINDER_EXPORTED size_t dataCapacity() const;
+ LIBBINDER_EXPORTED size_t dataBufferSize() const;
+
+ LIBBINDER_EXPORTED status_t setDataSize(size_t size);
// this must only be used to set a data position that was previously returned from
// dataPosition(). If writes are made, the exact same types of writes must be made (e.g.
// auto i = p.dataPosition(); p.writeInt32(0); p.setDataPosition(i); p.writeInt32(1);).
// Writing over objects, such as file descriptors and binders, is not supported.
- void setDataPosition(size_t pos) const;
- status_t setDataCapacity(size_t size);
+ LIBBINDER_EXPORTED void setDataPosition(size_t pos) const;
+ LIBBINDER_EXPORTED status_t setDataCapacity(size_t size);
- status_t setData(const uint8_t* buffer, size_t len);
+ LIBBINDER_EXPORTED status_t setData(const uint8_t* buffer, size_t len);
- status_t appendFrom(const Parcel *parcel,
- size_t start, size_t len);
+ LIBBINDER_EXPORTED status_t appendFrom(const Parcel* parcel, size_t start, size_t len);
- int compareData(const Parcel& other);
- status_t compareDataInRange(size_t thisOffset, const Parcel& other, size_t otherOffset,
- size_t length, int* result) const;
+ LIBBINDER_EXPORTED int compareData(const Parcel& other);
+ LIBBINDER_EXPORTED status_t compareDataInRange(size_t thisOffset, const Parcel& other,
+ size_t otherOffset, size_t length,
+ int* result) const;
- bool allowFds() const;
- bool pushAllowFds(bool allowFds);
- void restoreAllowFds(bool lastValue);
+ LIBBINDER_EXPORTED bool allowFds() const;
+ LIBBINDER_EXPORTED bool pushAllowFds(bool allowFds);
+ LIBBINDER_EXPORTED void restoreAllowFds(bool lastValue);
- bool hasFileDescriptors() const;
- status_t hasBinders(bool* result) const;
- status_t hasFileDescriptorsInRange(size_t offset, size_t length, bool* result) const;
- status_t hasBindersInRange(size_t offset, size_t length, bool* result) const;
+ LIBBINDER_EXPORTED bool hasFileDescriptors() const;
+ LIBBINDER_EXPORTED status_t hasBinders(bool* result) const;
+ LIBBINDER_EXPORTED status_t hasFileDescriptorsInRange(size_t offset, size_t length,
+ bool* result) const;
+ LIBBINDER_EXPORTED status_t hasBindersInRange(size_t offset, size_t length, bool* result) const;
// returns all binder objects in the Parcel
- std::vector<sp<IBinder>> debugReadAllStrongBinders() const;
+ LIBBINDER_EXPORTED std::vector<sp<IBinder>> debugReadAllStrongBinders() const;
// returns all file descriptors in the Parcel
// does not dup
- std::vector<int> debugReadAllFileDescriptors() const;
+ LIBBINDER_EXPORTED std::vector<int> debugReadAllFileDescriptors() const;
// Zeros data when reallocating. Other mitigations may be added
// in the future.
//
// WARNING: some read methods may make additional copies of data.
// In order to verify this, heap dumps should be used.
- void markSensitive() const;
+ LIBBINDER_EXPORTED void markSensitive() const;
// 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);
+ LIBBINDER_EXPORTED 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<RpcSession>& session);
+ LIBBINDER_EXPORTED void markForRpc(const sp<RpcSession>& session);
// Whether this Parcel is written for RPC transactions (after calls to
// markForBinder or markForRpc).
- bool isForRpc() const;
+ LIBBINDER_EXPORTED bool isForRpc() const;
// Writes the IPC/RPC header.
- status_t writeInterfaceToken(const String16& interface);
- status_t writeInterfaceToken(const char16_t* str, size_t len);
+ LIBBINDER_EXPORTED status_t writeInterfaceToken(const String16& interface);
+ LIBBINDER_EXPORTED status_t writeInterfaceToken(const char16_t* str, size_t len);
// Parses the RPC header, returning true if the interface name
// in the header matches the expected interface from the caller.
@@ -143,101 +145,116 @@
// propagating the StrictMode policy mask, populating the current
// IPCThreadState, which as an optimization may optionally be
// passed in.
- bool enforceInterface(const String16& interface,
- IPCThreadState* threadState = nullptr) const;
- bool enforceInterface(const char16_t* interface,
- size_t len,
- IPCThreadState* threadState = nullptr) const;
- bool checkInterface(IBinder*) const;
+ LIBBINDER_EXPORTED bool enforceInterface(const String16& interface,
+ IPCThreadState* threadState = nullptr) const;
+ LIBBINDER_EXPORTED bool enforceInterface(const char16_t* interface, size_t len,
+ IPCThreadState* threadState = nullptr) const;
+ LIBBINDER_EXPORTED bool checkInterface(IBinder*) const;
// Verify there are no bytes left to be read on the Parcel.
// Returns Status(EX_BAD_PARCELABLE) when the Parcel is not consumed.
- binder::Status enforceNoDataAvail() const;
+ LIBBINDER_EXPORTED binder::Status enforceNoDataAvail() const;
// This Api is used by fuzzers to skip dataAvail checks.
- void setEnforceNoDataAvail(bool enforceNoDataAvail);
+ LIBBINDER_EXPORTED void setEnforceNoDataAvail(bool enforceNoDataAvail);
// When fuzzing, we want to remove certain ABI checks that cause significant
// lost coverage, and we also want to avoid logs that cost too much to write.
- void setServiceFuzzing();
- bool isServiceFuzzing() const;
+ LIBBINDER_EXPORTED void setServiceFuzzing();
+ LIBBINDER_EXPORTED bool isServiceFuzzing() const;
- void freeData();
+ LIBBINDER_EXPORTED void freeData();
- size_t objectsCount() const;
-
- status_t errorCheck() const;
- void setError(status_t err);
-
- status_t write(const void* data, size_t len);
- void* writeInplace(size_t len);
- status_t writeUnpadded(const void* data, size_t len);
- status_t writeInt32(int32_t val);
- status_t writeUint32(uint32_t val);
- status_t writeInt64(int64_t val);
- status_t writeUint64(uint64_t val);
- status_t writeFloat(float val);
- status_t writeDouble(double val);
- status_t writeCString(const char* str);
- status_t writeString8(const String8& str);
- status_t writeString8(const char* str, size_t len);
- status_t writeString16(const String16& str);
- status_t writeString16(const std::optional<String16>& str);
- status_t writeString16(const std::unique_ptr<String16>& str) __attribute__((deprecated("use std::optional version instead")));
- status_t writeString16(const char16_t* str, size_t len);
- status_t writeStrongBinder(const sp<IBinder>& val);
- status_t writeInt32Array(size_t len, const int32_t *val);
- status_t writeByteArray(size_t len, const uint8_t *val);
- status_t writeBool(bool val);
- status_t writeChar(char16_t val);
- status_t writeByte(int8_t val);
+ LIBBINDER_EXPORTED size_t objectsCount() const;
+
+ LIBBINDER_EXPORTED status_t errorCheck() const;
+ LIBBINDER_EXPORTED void setError(status_t err);
+
+ LIBBINDER_EXPORTED status_t write(const void* data, size_t len);
+ LIBBINDER_EXPORTED void* writeInplace(size_t len);
+ LIBBINDER_EXPORTED status_t writeUnpadded(const void* data, size_t len);
+ LIBBINDER_EXPORTED status_t writeInt32(int32_t val);
+ LIBBINDER_EXPORTED status_t writeUint32(uint32_t val);
+ LIBBINDER_EXPORTED status_t writeInt64(int64_t val);
+ LIBBINDER_EXPORTED status_t writeUint64(uint64_t val);
+ LIBBINDER_EXPORTED status_t writeFloat(float val);
+ LIBBINDER_EXPORTED status_t writeDouble(double val);
+ LIBBINDER_EXPORTED status_t writeCString(const char* str);
+ LIBBINDER_EXPORTED status_t writeString8(const String8& str);
+ LIBBINDER_EXPORTED status_t writeString8(const char* str, size_t len);
+ LIBBINDER_EXPORTED status_t writeString16(const String16& str);
+ LIBBINDER_EXPORTED status_t writeString16(const std::optional<String16>& str);
+ LIBBINDER_EXPORTED status_t writeString16(const std::unique_ptr<String16>& str)
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t writeString16(const char16_t* str, size_t len);
+ LIBBINDER_EXPORTED status_t writeStrongBinder(const sp<IBinder>& val);
+ LIBBINDER_EXPORTED status_t writeInt32Array(size_t len, const int32_t* val);
+ LIBBINDER_EXPORTED status_t writeByteArray(size_t len, const uint8_t* val);
+ LIBBINDER_EXPORTED status_t writeBool(bool val);
+ LIBBINDER_EXPORTED status_t writeChar(char16_t val);
+ LIBBINDER_EXPORTED status_t writeByte(int8_t val);
// Take a UTF8 encoded string, convert to UTF16, write it to the parcel.
- status_t writeUtf8AsUtf16(const std::string& str);
- status_t writeUtf8AsUtf16(const std::optional<std::string>& str);
- status_t writeUtf8AsUtf16(const std::unique_ptr<std::string>& str) __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t writeUtf8AsUtf16(const std::string& str);
+ LIBBINDER_EXPORTED status_t writeUtf8AsUtf16(const std::optional<std::string>& str);
+ LIBBINDER_EXPORTED status_t writeUtf8AsUtf16(const std::unique_ptr<std::string>& str)
+ __attribute__((deprecated("use std::optional version instead")));
- status_t writeByteVector(const std::optional<std::vector<int8_t>>& val);
- status_t writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val) __attribute__((deprecated("use std::optional version instead")));
- status_t writeByteVector(const std::vector<int8_t>& val);
- status_t writeByteVector(const std::optional<std::vector<uint8_t>>& val);
- status_t writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val) __attribute__((deprecated("use std::optional version instead")));
- status_t writeByteVector(const std::vector<uint8_t>& val);
- status_t writeInt32Vector(const std::optional<std::vector<int32_t>>& val);
- status_t writeInt32Vector(const std::unique_ptr<std::vector<int32_t>>& val) __attribute__((deprecated("use std::optional version instead")));
- status_t writeInt32Vector(const std::vector<int32_t>& val);
- status_t writeInt64Vector(const std::optional<std::vector<int64_t>>& val);
- status_t writeInt64Vector(const std::unique_ptr<std::vector<int64_t>>& val) __attribute__((deprecated("use std::optional version instead")));
- status_t writeInt64Vector(const std::vector<int64_t>& val);
- status_t writeUint64Vector(const std::optional<std::vector<uint64_t>>& val);
- status_t writeUint64Vector(const std::unique_ptr<std::vector<uint64_t>>& val) __attribute__((deprecated("use std::optional version instead")));
- status_t writeUint64Vector(const std::vector<uint64_t>& val);
- status_t writeFloatVector(const std::optional<std::vector<float>>& val);
- status_t writeFloatVector(const std::unique_ptr<std::vector<float>>& val) __attribute__((deprecated("use std::optional version instead")));
- status_t writeFloatVector(const std::vector<float>& val);
- status_t writeDoubleVector(const std::optional<std::vector<double>>& val);
- status_t writeDoubleVector(const std::unique_ptr<std::vector<double>>& val) __attribute__((deprecated("use std::optional version instead")));
- status_t writeDoubleVector(const std::vector<double>& val);
- status_t writeBoolVector(const std::optional<std::vector<bool>>& val);
- status_t writeBoolVector(const std::unique_ptr<std::vector<bool>>& val) __attribute__((deprecated("use std::optional version instead")));
- status_t writeBoolVector(const std::vector<bool>& val);
- status_t writeCharVector(const std::optional<std::vector<char16_t>>& val);
- status_t writeCharVector(const std::unique_ptr<std::vector<char16_t>>& val) __attribute__((deprecated("use std::optional version instead")));
- status_t writeCharVector(const std::vector<char16_t>& val);
- status_t writeString16Vector(
- const std::optional<std::vector<std::optional<String16>>>& val);
- status_t writeString16Vector(
- const std::unique_ptr<std::vector<std::unique_ptr<String16>>>& val) __attribute__((deprecated("use std::optional version instead")));
- status_t writeString16Vector(const std::vector<String16>& val);
- status_t writeUtf8VectorAsUtf16Vector(
- const std::optional<std::vector<std::optional<std::string>>>& val);
- status_t writeUtf8VectorAsUtf16Vector(
- const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& val) __attribute__((deprecated("use std::optional version instead")));
- status_t writeUtf8VectorAsUtf16Vector(const std::vector<std::string>& val);
+ LIBBINDER_EXPORTED status_t writeByteVector(const std::optional<std::vector<int8_t>>& val);
+ LIBBINDER_EXPORTED status_t writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val)
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t writeByteVector(const std::vector<int8_t>& val);
+ LIBBINDER_EXPORTED status_t writeByteVector(const std::optional<std::vector<uint8_t>>& val);
+ LIBBINDER_EXPORTED status_t writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val)
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t writeByteVector(const std::vector<uint8_t>& val);
+ LIBBINDER_EXPORTED status_t writeInt32Vector(const std::optional<std::vector<int32_t>>& val);
+ LIBBINDER_EXPORTED status_t writeInt32Vector(const std::unique_ptr<std::vector<int32_t>>& val)
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t writeInt32Vector(const std::vector<int32_t>& val);
+ LIBBINDER_EXPORTED status_t writeInt64Vector(const std::optional<std::vector<int64_t>>& val);
+ LIBBINDER_EXPORTED status_t writeInt64Vector(const std::unique_ptr<std::vector<int64_t>>& val)
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t writeInt64Vector(const std::vector<int64_t>& val);
+ LIBBINDER_EXPORTED status_t writeUint64Vector(const std::optional<std::vector<uint64_t>>& val);
+ LIBBINDER_EXPORTED status_t writeUint64Vector(const std::unique_ptr<std::vector<uint64_t>>& val)
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t writeUint64Vector(const std::vector<uint64_t>& val);
+ LIBBINDER_EXPORTED status_t writeFloatVector(const std::optional<std::vector<float>>& val);
+ LIBBINDER_EXPORTED status_t writeFloatVector(const std::unique_ptr<std::vector<float>>& val)
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t writeFloatVector(const std::vector<float>& val);
+ LIBBINDER_EXPORTED status_t writeDoubleVector(const std::optional<std::vector<double>>& val);
+ LIBBINDER_EXPORTED status_t writeDoubleVector(const std::unique_ptr<std::vector<double>>& val)
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t writeDoubleVector(const std::vector<double>& val);
+ LIBBINDER_EXPORTED status_t writeBoolVector(const std::optional<std::vector<bool>>& val);
+ LIBBINDER_EXPORTED status_t writeBoolVector(const std::unique_ptr<std::vector<bool>>& val)
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t writeBoolVector(const std::vector<bool>& val);
+ LIBBINDER_EXPORTED status_t writeCharVector(const std::optional<std::vector<char16_t>>& val);
+ LIBBINDER_EXPORTED status_t writeCharVector(const std::unique_ptr<std::vector<char16_t>>& val)
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t writeCharVector(const std::vector<char16_t>& val);
+ LIBBINDER_EXPORTED status_t
+ writeString16Vector(const std::optional<std::vector<std::optional<String16>>>& val);
+ LIBBINDER_EXPORTED status_t
+ writeString16Vector(const std::unique_ptr<std::vector<std::unique_ptr<String16>>>& val)
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t writeString16Vector(const std::vector<String16>& val);
+ LIBBINDER_EXPORTED status_t
+ writeUtf8VectorAsUtf16Vector(const std::optional<std::vector<std::optional<std::string>>>& val);
+ LIBBINDER_EXPORTED status_t writeUtf8VectorAsUtf16Vector(
+ const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& val)
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t writeUtf8VectorAsUtf16Vector(const std::vector<std::string>& val);
- status_t writeStrongBinderVector(const std::optional<std::vector<sp<IBinder>>>& val);
- status_t writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val) __attribute__((deprecated("use std::optional version instead")));
- status_t writeStrongBinderVector(const std::vector<sp<IBinder>>& val);
+ LIBBINDER_EXPORTED status_t
+ writeStrongBinderVector(const std::optional<std::vector<sp<IBinder>>>& val);
+ LIBBINDER_EXPORTED status_t
+ writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val)
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t writeStrongBinderVector(const std::vector<sp<IBinder>>& val);
// Write an IInterface or a vector of IInterface's
template <typename T,
@@ -315,7 +332,7 @@
return writeData(parcelable);
}
- status_t writeParcelable(const Parcelable& parcelable);
+ LIBBINDER_EXPORTED status_t writeParcelable(const Parcelable& parcelable);
template<typename T>
status_t write(const Flattenable<T>& val);
@@ -335,40 +352,41 @@
// descriptors are dup'ed, so it is safe to delete the native_handle
// when this function returns).
// Doesn't take ownership of the native_handle.
- status_t writeNativeHandle(const native_handle* handle);
+ LIBBINDER_EXPORTED status_t writeNativeHandle(const native_handle* handle);
#endif
// Place a file descriptor into the parcel. The given fd must remain
// valid for the lifetime of the parcel.
// The Parcel does not take ownership of the given fd unless you ask it to.
- status_t writeFileDescriptor(int fd, bool takeOwnership = false);
+ LIBBINDER_EXPORTED status_t writeFileDescriptor(int fd, bool takeOwnership = false);
// Place a file descriptor into the parcel. A dup of the fd is made, which
// will be closed once the parcel is destroyed.
- status_t writeDupFileDescriptor(int fd);
+ LIBBINDER_EXPORTED status_t writeDupFileDescriptor(int fd);
// Place a Java "parcel file descriptor" into the parcel. The given fd must remain
// valid for the lifetime of the parcel.
// The Parcel does not take ownership of the given fd unless you ask it to.
- status_t writeParcelFileDescriptor(int fd, bool takeOwnership = false);
+ LIBBINDER_EXPORTED status_t writeParcelFileDescriptor(int fd, bool takeOwnership = false);
// Place a Java "parcel file descriptor" into the parcel. A dup of the fd is made, which will
// be closed once the parcel is destroyed.
- status_t writeDupParcelFileDescriptor(int fd);
+ LIBBINDER_EXPORTED status_t writeDupParcelFileDescriptor(int fd);
// Place a file descriptor into the parcel. This will not affect the
// semantics of the smart file descriptor. A new descriptor will be
// created, and will be closed when the parcel is destroyed.
- status_t writeUniqueFileDescriptor(const binder::unique_fd& fd);
+ LIBBINDER_EXPORTED status_t writeUniqueFileDescriptor(const binder::unique_fd& fd);
// Place a vector of file desciptors into the parcel. Each descriptor is
// dup'd as in writeDupFileDescriptor
- status_t writeUniqueFileDescriptorVector(
- const std::optional<std::vector<binder::unique_fd>>& val);
- status_t writeUniqueFileDescriptorVector(
- const std::unique_ptr<std::vector<binder::unique_fd>>& val)
+ LIBBINDER_EXPORTED status_t
+ writeUniqueFileDescriptorVector(const std::optional<std::vector<binder::unique_fd>>& val);
+ LIBBINDER_EXPORTED status_t
+ writeUniqueFileDescriptorVector(const std::unique_ptr<std::vector<binder::unique_fd>>& val)
__attribute__((deprecated("use std::optional version instead")));
- status_t writeUniqueFileDescriptorVector(const std::vector<binder::unique_fd>& val);
+ LIBBINDER_EXPORTED status_t
+ writeUniqueFileDescriptorVector(const std::vector<binder::unique_fd>& val);
// Writes a blob to the parcel.
// If the blob is small, then it is stored in-place, otherwise it is
@@ -376,58 +394,60 @@
// immutable blobs if possible since they may be subsequently transferred between
// processes without further copying whereas mutable blobs always need to be copied.
// The caller should call release() on the blob after writing its contents.
- status_t writeBlob(size_t len, bool mutableCopy, WritableBlob* outBlob);
+ LIBBINDER_EXPORTED status_t writeBlob(size_t len, bool mutableCopy, WritableBlob* outBlob);
// Write an existing immutable blob file descriptor to the parcel.
// This allows the client to send the same blob to multiple processes
// as long as it keeps a dup of the blob file descriptor handy for later.
- status_t writeDupImmutableBlobFileDescriptor(int fd);
+ LIBBINDER_EXPORTED status_t writeDupImmutableBlobFileDescriptor(int fd);
- status_t writeObject(const flat_binder_object& val, bool nullMetaData);
+ LIBBINDER_EXPORTED status_t writeObject(const flat_binder_object& val, bool nullMetaData);
// Like Parcel.java's writeNoException(). Just writes a zero int32.
// Currently the native implementation doesn't do any of the StrictMode
// stack gathering and serialization that the Java implementation does.
- status_t writeNoException();
-
- status_t read(void* outData, size_t len) const;
- const void* readInplace(size_t len) const;
- int32_t readInt32() const;
- status_t readInt32(int32_t *pArg) const;
- uint32_t readUint32() const;
- status_t readUint32(uint32_t *pArg) const;
- int64_t readInt64() const;
- status_t readInt64(int64_t *pArg) const;
- uint64_t readUint64() const;
- status_t readUint64(uint64_t *pArg) const;
- float readFloat() const;
- status_t readFloat(float *pArg) const;
- double readDouble() const;
- status_t readDouble(double *pArg) const;
- bool readBool() const;
- status_t readBool(bool *pArg) const;
- char16_t readChar() const;
- status_t readChar(char16_t *pArg) const;
- int8_t readByte() const;
- status_t readByte(int8_t *pArg) const;
+ LIBBINDER_EXPORTED status_t writeNoException();
+
+ LIBBINDER_EXPORTED status_t read(void* outData, size_t len) const;
+ LIBBINDER_EXPORTED const void* readInplace(size_t len) const;
+ LIBBINDER_EXPORTED int32_t readInt32() const;
+ LIBBINDER_EXPORTED status_t readInt32(int32_t* pArg) const;
+ LIBBINDER_EXPORTED uint32_t readUint32() const;
+ LIBBINDER_EXPORTED status_t readUint32(uint32_t* pArg) const;
+ LIBBINDER_EXPORTED int64_t readInt64() const;
+ LIBBINDER_EXPORTED status_t readInt64(int64_t* pArg) const;
+ LIBBINDER_EXPORTED uint64_t readUint64() const;
+ LIBBINDER_EXPORTED status_t readUint64(uint64_t* pArg) const;
+ LIBBINDER_EXPORTED float readFloat() const;
+ LIBBINDER_EXPORTED status_t readFloat(float* pArg) const;
+ LIBBINDER_EXPORTED double readDouble() const;
+ LIBBINDER_EXPORTED status_t readDouble(double* pArg) const;
+ LIBBINDER_EXPORTED bool readBool() const;
+ LIBBINDER_EXPORTED status_t readBool(bool* pArg) const;
+ LIBBINDER_EXPORTED char16_t readChar() const;
+ LIBBINDER_EXPORTED status_t readChar(char16_t* pArg) const;
+ LIBBINDER_EXPORTED int8_t readByte() const;
+ LIBBINDER_EXPORTED status_t readByte(int8_t* pArg) const;
// Read a UTF16 encoded string, convert to UTF8
- status_t readUtf8FromUtf16(std::string* str) const;
- status_t readUtf8FromUtf16(std::optional<std::string>* str) const;
- status_t readUtf8FromUtf16(std::unique_ptr<std::string>* str) const __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t readUtf8FromUtf16(std::string* str) const;
+ LIBBINDER_EXPORTED status_t readUtf8FromUtf16(std::optional<std::string>* str) const;
+ LIBBINDER_EXPORTED status_t readUtf8FromUtf16(std::unique_ptr<std::string>* str) const
+ __attribute__((deprecated("use std::optional version instead")));
- const char* readCString() const;
- String8 readString8() const;
- status_t readString8(String8* pArg) const;
- const char* readString8Inplace(size_t* outLen) const;
- String16 readString16() const;
- status_t readString16(String16* pArg) const;
- status_t readString16(std::optional<String16>* pArg) const;
- status_t readString16(std::unique_ptr<String16>* pArg) const __attribute__((deprecated("use std::optional version instead")));
- const char16_t* readString16Inplace(size_t* outLen) const;
- sp<IBinder> readStrongBinder() const;
- status_t readStrongBinder(sp<IBinder>* val) const;
- status_t readNullableStrongBinder(sp<IBinder>* val) const;
+ LIBBINDER_EXPORTED const char* readCString() const;
+ LIBBINDER_EXPORTED String8 readString8() const;
+ LIBBINDER_EXPORTED status_t readString8(String8* pArg) const;
+ LIBBINDER_EXPORTED const char* readString8Inplace(size_t* outLen) const;
+ LIBBINDER_EXPORTED String16 readString16() const;
+ LIBBINDER_EXPORTED status_t readString16(String16* pArg) const;
+ LIBBINDER_EXPORTED status_t readString16(std::optional<String16>* pArg) const;
+ LIBBINDER_EXPORTED status_t readString16(std::unique_ptr<String16>* pArg) const
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED const char16_t* readString16Inplace(size_t* outLen) const;
+ LIBBINDER_EXPORTED sp<IBinder> readStrongBinder() const;
+ LIBBINDER_EXPORTED status_t readStrongBinder(sp<IBinder>* val) const;
+ LIBBINDER_EXPORTED status_t readNullableStrongBinder(sp<IBinder>* val) const;
// Read an Enum vector with underlying type int8_t.
// Does not use padding; each byte is contiguous.
@@ -466,7 +486,7 @@
status_t readParcelableVector(std::vector<T>* val) const
{ return readData(val); }
- status_t readParcelable(Parcelable* parcelable) const;
+ LIBBINDER_EXPORTED status_t readParcelable(Parcelable* parcelable) const;
template<typename T>
status_t readParcelable(std::optional<T>* parcelable) const
@@ -484,9 +504,12 @@
template<typename T>
status_t readNullableStrongBinder(sp<T>* val) const;
- status_t readStrongBinderVector(std::optional<std::vector<sp<IBinder>>>* val) const;
- status_t readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const __attribute__((deprecated("use std::optional version instead")));
- status_t readStrongBinderVector(std::vector<sp<IBinder>>* val) const;
+ LIBBINDER_EXPORTED status_t
+ readStrongBinderVector(std::optional<std::vector<sp<IBinder>>>* val) const;
+ LIBBINDER_EXPORTED status_t
+ readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t readStrongBinderVector(std::vector<sp<IBinder>>* val) const;
template <typename T,
std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true>
status_t readStrongBinderVector(std::vector<sp<T>>* val) const {
@@ -498,43 +521,54 @@
return readData(val);
}
- status_t readByteVector(std::optional<std::vector<int8_t>>* val) const;
- status_t readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
- status_t readByteVector(std::vector<int8_t>* val) const;
- status_t readByteVector(std::optional<std::vector<uint8_t>>* val) const;
- status_t readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
- status_t readByteVector(std::vector<uint8_t>* val) const;
- status_t readInt32Vector(std::optional<std::vector<int32_t>>* val) const;
- status_t readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
- status_t readInt32Vector(std::vector<int32_t>* val) const;
- status_t readInt64Vector(std::optional<std::vector<int64_t>>* val) const;
- status_t readInt64Vector(std::unique_ptr<std::vector<int64_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
- status_t readInt64Vector(std::vector<int64_t>* val) const;
- status_t readUint64Vector(std::optional<std::vector<uint64_t>>* val) const;
- status_t readUint64Vector(std::unique_ptr<std::vector<uint64_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
- status_t readUint64Vector(std::vector<uint64_t>* val) const;
- status_t readFloatVector(std::optional<std::vector<float>>* val) const;
- status_t readFloatVector(std::unique_ptr<std::vector<float>>* val) const __attribute__((deprecated("use std::optional version instead")));
- status_t readFloatVector(std::vector<float>* val) const;
- status_t readDoubleVector(std::optional<std::vector<double>>* val) const;
- status_t readDoubleVector(std::unique_ptr<std::vector<double>>* val) const __attribute__((deprecated("use std::optional version instead")));
- status_t readDoubleVector(std::vector<double>* val) const;
- status_t readBoolVector(std::optional<std::vector<bool>>* val) const;
- status_t readBoolVector(std::unique_ptr<std::vector<bool>>* val) const __attribute__((deprecated("use std::optional version instead")));
- status_t readBoolVector(std::vector<bool>* val) const;
- status_t readCharVector(std::optional<std::vector<char16_t>>* val) const;
- status_t readCharVector(std::unique_ptr<std::vector<char16_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
- status_t readCharVector(std::vector<char16_t>* val) const;
- status_t readString16Vector(
- std::optional<std::vector<std::optional<String16>>>* val) const;
- status_t readString16Vector(
- std::unique_ptr<std::vector<std::unique_ptr<String16>>>* val) const __attribute__((deprecated("use std::optional version instead")));
- status_t readString16Vector(std::vector<String16>* val) const;
- status_t readUtf8VectorFromUtf16Vector(
- std::optional<std::vector<std::optional<std::string>>>* val) const;
- status_t readUtf8VectorFromUtf16Vector(
- std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const __attribute__((deprecated("use std::optional version instead")));
- status_t readUtf8VectorFromUtf16Vector(std::vector<std::string>* val) const;
+ LIBBINDER_EXPORTED status_t readByteVector(std::optional<std::vector<int8_t>>* val) const;
+ LIBBINDER_EXPORTED status_t readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t readByteVector(std::vector<int8_t>* val) const;
+ LIBBINDER_EXPORTED status_t readByteVector(std::optional<std::vector<uint8_t>>* val) const;
+ LIBBINDER_EXPORTED status_t readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t readByteVector(std::vector<uint8_t>* val) const;
+ LIBBINDER_EXPORTED status_t readInt32Vector(std::optional<std::vector<int32_t>>* val) const;
+ LIBBINDER_EXPORTED status_t readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t readInt32Vector(std::vector<int32_t>* val) const;
+ LIBBINDER_EXPORTED status_t readInt64Vector(std::optional<std::vector<int64_t>>* val) const;
+ LIBBINDER_EXPORTED status_t readInt64Vector(std::unique_ptr<std::vector<int64_t>>* val) const
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t readInt64Vector(std::vector<int64_t>* val) const;
+ LIBBINDER_EXPORTED status_t readUint64Vector(std::optional<std::vector<uint64_t>>* val) const;
+ LIBBINDER_EXPORTED status_t readUint64Vector(std::unique_ptr<std::vector<uint64_t>>* val) const
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t readUint64Vector(std::vector<uint64_t>* val) const;
+ LIBBINDER_EXPORTED status_t readFloatVector(std::optional<std::vector<float>>* val) const;
+ LIBBINDER_EXPORTED status_t readFloatVector(std::unique_ptr<std::vector<float>>* val) const
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t readFloatVector(std::vector<float>* val) const;
+ LIBBINDER_EXPORTED status_t readDoubleVector(std::optional<std::vector<double>>* val) const;
+ LIBBINDER_EXPORTED status_t readDoubleVector(std::unique_ptr<std::vector<double>>* val) const
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t readDoubleVector(std::vector<double>* val) const;
+ LIBBINDER_EXPORTED status_t readBoolVector(std::optional<std::vector<bool>>* val) const;
+ LIBBINDER_EXPORTED status_t readBoolVector(std::unique_ptr<std::vector<bool>>* val) const
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t readBoolVector(std::vector<bool>* val) const;
+ LIBBINDER_EXPORTED status_t readCharVector(std::optional<std::vector<char16_t>>* val) const;
+ LIBBINDER_EXPORTED status_t readCharVector(std::unique_ptr<std::vector<char16_t>>* val) const
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t readCharVector(std::vector<char16_t>* val) const;
+ LIBBINDER_EXPORTED status_t
+ readString16Vector(std::optional<std::vector<std::optional<String16>>>* val) const;
+ LIBBINDER_EXPORTED status_t
+ readString16Vector(std::unique_ptr<std::vector<std::unique_ptr<String16>>>* val) const
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t readString16Vector(std::vector<String16>* val) const;
+ LIBBINDER_EXPORTED status_t readUtf8VectorFromUtf16Vector(
+ std::optional<std::vector<std::optional<std::string>>>* val) const;
+ LIBBINDER_EXPORTED status_t readUtf8VectorFromUtf16Vector(
+ std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t readUtf8VectorFromUtf16Vector(std::vector<std::string>* val) const;
template <typename T, size_t N>
status_t readFixedArray(std::array<T, N>* val) const {
@@ -564,56 +598,58 @@
// code on exceptions, but also deals with skipping over rich
// response headers. Callers should use this to read & parse the
// response headers rather than doing it by hand.
- int32_t readExceptionCode() const;
+ LIBBINDER_EXPORTED int32_t readExceptionCode() const;
#ifndef BINDER_DISABLE_NATIVE_HANDLE
// Retrieve native_handle from the parcel. This returns a copy of the
// parcel's native_handle (the caller takes ownership). The caller
// must free the native_handle with native_handle_close() and
// native_handle_delete().
- native_handle* readNativeHandle() const;
+ LIBBINDER_EXPORTED native_handle* readNativeHandle() const;
#endif
// Retrieve a file descriptor from the parcel. This returns the raw fd
// in the parcel, which you do not own -- use dup() to get your own copy.
- int readFileDescriptor() const;
+ LIBBINDER_EXPORTED int readFileDescriptor() const;
// Retrieve a Java "parcel file descriptor" from the parcel. This returns the raw fd
// in the parcel, which you do not own -- use dup() to get your own copy.
- int readParcelFileDescriptor() const;
+ LIBBINDER_EXPORTED int readParcelFileDescriptor() const;
// Retrieve a smart file descriptor from the parcel.
- status_t readUniqueFileDescriptor(binder::unique_fd* val) const;
+ LIBBINDER_EXPORTED status_t readUniqueFileDescriptor(binder::unique_fd* val) const;
// Retrieve a Java "parcel file descriptor" from the parcel.
- status_t readUniqueParcelFileDescriptor(binder::unique_fd* val) const;
+ LIBBINDER_EXPORTED status_t readUniqueParcelFileDescriptor(binder::unique_fd* val) const;
// Retrieve a vector of smart file descriptors from the parcel.
- status_t readUniqueFileDescriptorVector(
- std::optional<std::vector<binder::unique_fd>>* val) const;
- status_t readUniqueFileDescriptorVector(std::unique_ptr<std::vector<binder::unique_fd>>* val)
- const __attribute__((deprecated("use std::optional version instead")));
- status_t readUniqueFileDescriptorVector(std::vector<binder::unique_fd>* val) const;
+ LIBBINDER_EXPORTED status_t
+ readUniqueFileDescriptorVector(std::optional<std::vector<binder::unique_fd>>* val) const;
+ LIBBINDER_EXPORTED status_t
+ readUniqueFileDescriptorVector(std::unique_ptr<std::vector<binder::unique_fd>>* val) const
+ __attribute__((deprecated("use std::optional version instead")));
+ LIBBINDER_EXPORTED status_t
+ readUniqueFileDescriptorVector(std::vector<binder::unique_fd>* val) const;
// Reads a blob from the parcel.
// The caller should call release() on the blob after reading its contents.
- status_t readBlob(size_t len, ReadableBlob* outBlob) const;
+ LIBBINDER_EXPORTED status_t readBlob(size_t len, ReadableBlob* outBlob) const;
- const flat_binder_object* readObject(bool nullMetaData) const;
+ LIBBINDER_EXPORTED const flat_binder_object* readObject(bool nullMetaData) const;
// Explicitly close all file descriptors in the parcel.
- void closeFileDescriptors();
+ LIBBINDER_EXPORTED void closeFileDescriptors();
// Debugging: get metrics on current allocations.
- static size_t getGlobalAllocSize();
- static size_t getGlobalAllocCount();
+ LIBBINDER_EXPORTED static size_t getGlobalAllocSize();
+ LIBBINDER_EXPORTED static size_t getGlobalAllocCount();
- bool replaceCallingWorkSourceUid(uid_t uid);
+ LIBBINDER_EXPORTED bool replaceCallingWorkSourceUid(uid_t uid);
// Returns the work source provided by the caller. This can only be trusted for trusted calling
// uid.
- uid_t readCallingWorkSourceUid() const;
+ LIBBINDER_EXPORTED uid_t readCallingWorkSourceUid() const;
- void print(std::ostream& to, uint32_t flags = 0) const;
+ LIBBINDER_EXPORTED void print(std::ostream& to, uint32_t flags = 0) const;
private:
// `objects` and `objectsSize` always 0 for RPC Parcels.
@@ -660,7 +696,7 @@
status_t flattenBinder(const sp<IBinder>& binder);
status_t unflattenBinder(sp<IBinder>* out) const;
- status_t readOutVectorSizeWithCheck(size_t elmSize, int32_t* size) const;
+ LIBBINDER_EXPORTED status_t readOutVectorSizeWithCheck(size_t elmSize, int32_t* size) const;
template<class T>
status_t readAligned(T *pArg) const;
@@ -1356,14 +1392,14 @@
class Blob {
public:
- Blob();
- ~Blob();
+ LIBBINDER_EXPORTED Blob();
+ LIBBINDER_EXPORTED ~Blob();
- void clear();
- void release();
- inline size_t size() const { return mSize; }
- inline int fd() const { return mFd; }
- inline bool isMutable() const { return mMutable; }
+ LIBBINDER_EXPORTED void clear();
+ LIBBINDER_EXPORTED void release();
+ LIBBINDER_EXPORTED inline size_t size() const { return mSize; }
+ LIBBINDER_EXPORTED inline int fd() const { return mFd; }
+ LIBBINDER_EXPORTED inline bool isMutable() const { return mMutable; }
protected:
void init(int fd, void* data, size_t size, bool isMutable);
@@ -1381,7 +1417,7 @@
// FlattenableHelperInterface and FlattenableHelper avoid generating a vtable entry in objects
// following Flattenable template/protocol.
- class FlattenableHelperInterface {
+ class LIBBINDER_EXPORTED FlattenableHelperInterface {
protected:
~FlattenableHelperInterface() { }
public:
@@ -1420,21 +1456,21 @@
return const_cast<Flattenable<T>&>(val).unflatten(buffer, size, fds, count);
}
};
- status_t write(const FlattenableHelperInterface& val);
- status_t read(FlattenableHelperInterface& val) const;
+ LIBBINDER_EXPORTED status_t write(const FlattenableHelperInterface& val);
+ LIBBINDER_EXPORTED status_t read(FlattenableHelperInterface& val) const;
public:
class ReadableBlob : public Blob {
friend class Parcel;
public:
- inline const void* data() const { return mData; }
- inline void* mutableData() { return isMutable() ? mData : nullptr; }
+ LIBBINDER_EXPORTED inline const void* data() const { return mData; }
+ LIBBINDER_EXPORTED inline void* mutableData() { return isMutable() ? mData : nullptr; }
};
class WritableBlob : public Blob {
friend class Parcel;
public:
- inline void* data() { return mData; }
+ LIBBINDER_EXPORTED inline void* data() { return mData; }
};
/**
@@ -1444,12 +1480,12 @@
* is referenced by this Parcel, but which this parcel doesn't own (e.g.
* writeFileDescriptor is called without 'takeOwnership' true).
*/
- size_t getOpenAshmemSize() const;
+ LIBBINDER_EXPORTED size_t getOpenAshmemSize() const;
private:
// TODO(b/202029388): Remove 'getBlobAshmemSize' once no prebuilts reference
// this
- size_t getBlobAshmemSize() const;
+ LIBBINDER_EXPORTED size_t getBlobAshmemSize() const;
// Needed so that we can save object metadata to the disk
friend class android::binder::debug::RecordedTransaction;
diff --git a/libs/binder/include/binder/ParcelFileDescriptor.h b/libs/binder/include/binder/ParcelFileDescriptor.h
index c4ef354..50a1d39 100644
--- a/libs/binder/include/binder/ParcelFileDescriptor.h
+++ b/libs/binder/include/binder/ParcelFileDescriptor.h
@@ -16,6 +16,7 @@
#pragma once
+#include <binder/Common.h>
#include <binder/Parcel.h>
#include <binder/Parcelable.h>
#include <binder/unique_fd.h>
@@ -26,7 +27,7 @@
/*
* C++ implementation of the Java class android.os.ParcelFileDescriptor
*/
-class ParcelFileDescriptor : public android::Parcelable {
+class LIBBINDER_EXPORTED ParcelFileDescriptor : public android::Parcelable {
public:
ParcelFileDescriptor();
explicit ParcelFileDescriptor(binder::unique_fd fd);
diff --git a/libs/binder/include/binder/Parcelable.h b/libs/binder/include/binder/Parcelable.h
index 2c652be..0b707b3 100644
--- a/libs/binder/include/binder/Parcelable.h
+++ b/libs/binder/include/binder/Parcelable.h
@@ -21,6 +21,8 @@
#include <utils/Errors.h>
#include <utils/String16.h>
+#include <binder/Common.h>
+
namespace android {
class Parcel;
@@ -31,7 +33,7 @@
#endif
// Abstract interface of all parcelables.
-class Parcelable {
+class LIBBINDER_EXPORTED Parcelable {
public:
virtual ~Parcelable() = default;
diff --git a/libs/binder/include/binder/ParcelableHolder.h b/libs/binder/include/binder/ParcelableHolder.h
index 40fd30a..965d097 100644
--- a/libs/binder/include/binder/ParcelableHolder.h
+++ b/libs/binder/include/binder/ParcelableHolder.h
@@ -16,6 +16,7 @@
#pragma once
+#include <binder/Common.h>
#include <binder/Parcel.h>
#include <binder/Parcelable.h>
#include <utils/String16.h>
@@ -28,7 +29,7 @@
/*
* C++ implementation of the Java class android.os.ParcelableHolder
*/
-class ParcelableHolder : public android::Parcelable {
+class LIBBINDER_EXPORTED ParcelableHolder : public android::Parcelable {
public:
ParcelableHolder() = delete;
explicit ParcelableHolder(Stability stability) : mStability(stability){}
diff --git a/libs/binder/include/binder/PermissionCache.h b/libs/binder/include/binder/PermissionCache.h
index 21aa705..9c08016 100644
--- a/libs/binder/include/binder/PermissionCache.h
+++ b/libs/binder/include/binder/PermissionCache.h
@@ -24,6 +24,7 @@
#include <utils/String16.h>
#include <utils/Singleton.h>
#include <utils/SortedVector.h>
+#include <binder/Common.h>
namespace android {
// ---------------------------------------------------------------------------
@@ -64,17 +65,17 @@
void cache(const String16& permission, uid_t uid, bool granted);
public:
- PermissionCache();
+ LIBBINDER_EXPORTED PermissionCache();
- static bool checkCallingPermission(const String16& permission);
+ LIBBINDER_EXPORTED static bool checkCallingPermission(const String16& permission);
- static bool checkCallingPermission(const String16& permission,
- int32_t* outPid, int32_t* outUid);
+ LIBBINDER_EXPORTED static bool checkCallingPermission(const String16& permission,
+ int32_t* outPid, int32_t* outUid);
- static bool checkPermission(const String16& permission,
- pid_t pid, uid_t uid);
+ LIBBINDER_EXPORTED static bool checkPermission(const String16& permission, pid_t pid,
+ uid_t uid);
- static void purgeCache();
+ LIBBINDER_EXPORTED static void purgeCache();
};
// ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/PermissionController.h b/libs/binder/include/binder/PermissionController.h
index 6f9eb5e..0cf0b70 100644
--- a/libs/binder/include/binder/PermissionController.h
+++ b/libs/binder/include/binder/PermissionController.h
@@ -18,14 +18,14 @@
#ifndef __ANDROID_VNDK__
+#include <binder/Common.h>
#include <binder/IPermissionController.h>
#include <utils/Mutex.h>
// ---------------------------------------------------------------------------
namespace android {
-class PermissionController
-{
+class PermissionController {
public:
enum {
@@ -42,13 +42,13 @@
MODE_DEFAULT = 3,
};
- PermissionController();
+ LIBBINDER_EXPORTED PermissionController();
- bool checkPermission(const String16& permission, int32_t pid, int32_t uid);
- int32_t noteOp(const String16& op, int32_t uid, const String16& packageName);
- void getPackagesForUid(const uid_t uid, Vector<String16>& packages);
- bool isRuntimePermission(const String16& permission);
- int getPackageUid(const String16& package, int flags);
+ LIBBINDER_EXPORTED bool checkPermission(const String16& permission, int32_t pid, int32_t uid);
+ LIBBINDER_EXPORTED int32_t noteOp(const String16& op, int32_t uid, const String16& packageName);
+ LIBBINDER_EXPORTED void getPackagesForUid(const uid_t uid, Vector<String16>& packages);
+ LIBBINDER_EXPORTED bool isRuntimePermission(const String16& permission);
+ LIBBINDER_EXPORTED int getPackageUid(const String16& package, int flags);
private:
Mutex mLock;
diff --git a/libs/binder/include/binder/PersistableBundle.h b/libs/binder/include/binder/PersistableBundle.h
index 4517cf2..7c3b625 100644
--- a/libs/binder/include/binder/PersistableBundle.h
+++ b/libs/binder/include/binder/PersistableBundle.h
@@ -20,6 +20,7 @@
#include <set>
#include <vector>
+#include <binder/Common.h>
#include <binder/Parcelable.h>
#include <utils/String16.h>
#include <utils/StrongPointer.h>
@@ -32,7 +33,7 @@
* C++ implementation of PersistableBundle, a mapping from String values to
* various types that can be saved to persistent and later restored.
*/
-class PersistableBundle : public Parcelable {
+class LIBBINDER_EXPORTED PersistableBundle : public Parcelable {
public:
PersistableBundle() = default;
virtual ~PersistableBundle() = default;
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index 3672702..a466638 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -16,6 +16,7 @@
#pragma once
+#include <binder/Common.h>
#include <binder/IBinder.h>
#include <utils/String16.h>
#include <utils/String8.h>
@@ -35,10 +36,10 @@
*/
class ProcessState : public virtual RefBase {
public:
- static sp<ProcessState> self();
- static sp<ProcessState> selfOrNull();
+ LIBBINDER_EXPORTED static sp<ProcessState> self();
+ LIBBINDER_EXPORTED static sp<ProcessState> selfOrNull();
- static bool isVndservicemanagerEnabled();
+ LIBBINDER_EXPORTED static bool isVndservicemanagerEnabled();
/* initWithDriver() can be used to configure libbinder to use
* a different binder driver dev node. It must be called *before*
@@ -48,9 +49,9 @@
*
* If this is called with nullptr, the behavior is the same as selfOrNull.
*/
- static sp<ProcessState> initWithDriver(const char* driver);
+ LIBBINDER_EXPORTED static sp<ProcessState> initWithDriver(const char* driver);
- sp<IBinder> getContextObject(const sp<IBinder>& caller);
+ LIBBINDER_EXPORTED sp<IBinder> getContextObject(const sp<IBinder>& caller);
// This should be called before startThreadPool at the beginning
// of a program, and libraries should never call it because programs
@@ -60,7 +61,7 @@
// The 'maxThreads' value refers to the total number of threads
// that will be started by the kernel. This is in addition to any
// threads started by 'startThreadPool' or 'joinRpcThreadpool'.
- status_t setThreadPoolMaxThreadCount(size_t maxThreads);
+ LIBBINDER_EXPORTED status_t setThreadPoolMaxThreadCount(size_t maxThreads);
// Libraries should not call this, as processes should configure
// threadpools themselves. Should be called in the main function
@@ -72,27 +73,27 @@
// For instance, if setThreadPoolMaxCount(3) is called and
// startThreadpPool (+1 thread) and joinThreadPool (+1 thread)
// are all called, then up to 5 threads can be started.
- void startThreadPool();
+ LIBBINDER_EXPORTED void startThreadPool();
- [[nodiscard]] bool becomeContextManager();
+ [[nodiscard]] LIBBINDER_EXPORTED bool becomeContextManager();
- sp<IBinder> getStrongProxyForHandle(int32_t handle);
- void expungeHandle(int32_t handle, IBinder* binder);
+ LIBBINDER_EXPORTED sp<IBinder> getStrongProxyForHandle(int32_t handle);
+ LIBBINDER_EXPORTED void expungeHandle(int32_t handle, IBinder* binder);
// TODO: deprecate.
- void spawnPooledThread(bool isMain);
+ LIBBINDER_EXPORTED void spawnPooledThread(bool isMain);
- status_t enableOnewaySpamDetection(bool enable);
+ LIBBINDER_EXPORTED status_t enableOnewaySpamDetection(bool enable);
// Set the name of the current thread to look like a threadpool
// thread. Typically this is called before joinThreadPool.
//
// TODO: remove this API, and automatically set it intelligently.
- void giveThreadPoolName();
+ LIBBINDER_EXPORTED void giveThreadPoolName();
- String8 getDriverName();
+ LIBBINDER_EXPORTED String8 getDriverName();
- ssize_t getKernelReferences(size_t count, uintptr_t* buf);
+ LIBBINDER_EXPORTED ssize_t getKernelReferences(size_t count, uintptr_t* buf);
// Only usable by the context manager.
// This refcount includes:
@@ -100,7 +101,7 @@
// 2. Temporary strong references held by the kernel during a
// transaction on the node.
// It does NOT include local strong references to the node
- ssize_t getStrongRefCountForNode(const sp<BpBinder>& binder);
+ LIBBINDER_EXPORTED ssize_t getStrongRefCountForNode(const sp<BpBinder>& binder);
enum class CallRestriction {
// all calls okay
@@ -112,26 +113,26 @@
};
// Sets calling restrictions for all transactions in this process. This must be called
// before any threads are spawned.
- void setCallRestriction(CallRestriction restriction);
+ LIBBINDER_EXPORTED void setCallRestriction(CallRestriction restriction);
/**
* Get the max number of threads that have joined the thread pool.
* This includes kernel started threads, user joined threads and polling
* threads if used.
*/
- size_t getThreadPoolMaxTotalThreadCount() const;
+ LIBBINDER_EXPORTED size_t getThreadPoolMaxTotalThreadCount() const;
/**
* Check to see if the thread pool has started.
*/
- bool isThreadPoolStarted() const;
+ LIBBINDER_EXPORTED bool isThreadPoolStarted() const;
enum class DriverFeature {
ONEWAY_SPAM_DETECTION,
EXTENDED_ERROR,
};
// Determine whether a feature is supported by the binder driver.
- static bool isDriverFeatureEnabled(const DriverFeature feature);
+ LIBBINDER_EXPORTED static bool isDriverFeatureEnabled(const DriverFeature feature);
private:
static sp<ProcessState> init(const char* defaultDriver, bool requireDefault);
diff --git a/libs/binder/include/binder/RecordedTransaction.h b/libs/binder/include/binder/RecordedTransaction.h
index f0bee7f..ed75e43 100644
--- a/libs/binder/include/binder/RecordedTransaction.h
+++ b/libs/binder/include/binder/RecordedTransaction.h
@@ -16,6 +16,7 @@
#pragma once
+#include <binder/Common.h>
#include <binder/Parcel.h>
#include <binder/unique_fd.h>
#include <mutex>
@@ -32,25 +33,25 @@
public:
// Filled with the first transaction from fd.
- static std::optional<RecordedTransaction> fromFile(const binder::unique_fd& fd);
+ LIBBINDER_EXPORTED static std::optional<RecordedTransaction> fromFile(
+ const binder::unique_fd& fd);
// Filled with the arguments.
- static std::optional<RecordedTransaction> fromDetails(const String16& interfaceName,
- uint32_t code, uint32_t flags,
- timespec timestamp, const Parcel& data,
- const Parcel& reply, status_t err);
- RecordedTransaction(RecordedTransaction&& t) noexcept;
+ LIBBINDER_EXPORTED static std::optional<RecordedTransaction> fromDetails(
+ const String16& interfaceName, uint32_t code, uint32_t flags, timespec timestamp,
+ const Parcel& data, const Parcel& reply, status_t err);
+ LIBBINDER_EXPORTED RecordedTransaction(RecordedTransaction&& t) noexcept;
- [[nodiscard]] status_t dumpToFile(const binder::unique_fd& fd) const;
+ [[nodiscard]] LIBBINDER_EXPORTED status_t dumpToFile(const binder::unique_fd& fd) const;
- const std::string& getInterfaceName() const;
- uint32_t getCode() const;
- uint32_t getFlags() const;
- int32_t getReturnedStatus() const;
- timespec getTimestamp() const;
- uint32_t getVersion() const;
- const Parcel& getDataParcel() const;
- const Parcel& getReplyParcel() const;
- const std::vector<uint64_t>& getObjectOffsets() const;
+ LIBBINDER_EXPORTED const std::string& getInterfaceName() const;
+ LIBBINDER_EXPORTED uint32_t getCode() const;
+ LIBBINDER_EXPORTED uint32_t getFlags() const;
+ LIBBINDER_EXPORTED int32_t getReturnedStatus() const;
+ LIBBINDER_EXPORTED timespec getTimestamp() const;
+ LIBBINDER_EXPORTED uint32_t getVersion() const;
+ LIBBINDER_EXPORTED const Parcel& getDataParcel() const;
+ LIBBINDER_EXPORTED const Parcel& getReplyParcel() const;
+ LIBBINDER_EXPORTED const std::vector<uint64_t>& getObjectOffsets() const;
private:
RecordedTransaction() = default;
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index a07880d..abea0fb 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -15,6 +15,7 @@
*/
#pragma once
+#include <binder/Common.h>
#include <binder/IBinder.h>
#include <binder/RpcSession.h>
#include <binder/RpcThreads.h>
@@ -47,7 +48,7 @@
*/
class RpcServer final : public virtual RefBase, private RpcSession::EventListener {
public:
- static sp<RpcServer> make(
+ LIBBINDER_EXPORTED static sp<RpcServer> make(
std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory = nullptr);
/**
@@ -59,7 +60,8 @@
* to RpcSession::setupUnixDomainSocketBootstrapClient. Multiple client
* session can be created from the client end of the pair.
*/
- [[nodiscard]] status_t setupUnixDomainSocketBootstrapServer(binder::unique_fd serverFd);
+ [[nodiscard]] LIBBINDER_EXPORTED status_t
+ setupUnixDomainSocketBootstrapServer(binder::unique_fd serverFd);
/**
* This represents a session for responses, e.g.:
@@ -69,7 +71,7 @@
* process B makes binder b and sends it to A
* A uses this 'back session' to send things back to B
*/
- [[nodiscard]] status_t setupUnixDomainServer(const char* path);
+ [[nodiscard]] LIBBINDER_EXPORTED status_t setupUnixDomainServer(const char* path);
/**
* Sets up an RPC server with a raw socket file descriptor.
@@ -79,12 +81,13 @@
* This method is used in the libbinder_rpc_unstable API
* RunInitUnixDomainRpcServer().
*/
- [[nodiscard]] status_t setupRawSocketServer(binder::unique_fd socket_fd);
+ [[nodiscard]] LIBBINDER_EXPORTED status_t setupRawSocketServer(binder::unique_fd socket_fd);
/**
* Creates an RPC server binding to the given CID at the given port.
*/
- [[nodiscard]] status_t setupVsockServer(unsigned int bindCid, unsigned int port);
+ [[nodiscard]] LIBBINDER_EXPORTED status_t setupVsockServer(unsigned int bindCid,
+ unsigned int port);
/**
* Creates an RPC server at the current port using IPv4.
@@ -100,24 +103,25 @@
* "0.0.0.0" allows for connections on any IP address that the device may
* have
*/
- [[nodiscard]] status_t setupInetServer(const char* address, unsigned int port,
- unsigned int* assignedPort = nullptr);
+ [[nodiscard]] LIBBINDER_EXPORTED status_t setupInetServer(const char* address,
+ unsigned int port,
+ unsigned int* assignedPort = nullptr);
/**
* If setup*Server has been successful, return true. Otherwise return false.
*/
- [[nodiscard]] bool hasServer();
+ [[nodiscard]] LIBBINDER_EXPORTED bool hasServer();
/**
* If hasServer(), return the server FD. Otherwise return invalid FD.
*/
- [[nodiscard]] binder::unique_fd releaseServer();
+ [[nodiscard]] LIBBINDER_EXPORTED binder::unique_fd releaseServer();
/**
* Set up server using an external FD previously set up by releaseServer().
* Return false if there's already a server.
*/
- [[nodiscard]] status_t setupExternalServer(binder::unique_fd serverFd);
+ [[nodiscard]] LIBBINDER_EXPORTED status_t setupExternalServer(binder::unique_fd serverFd);
/**
* This must be called before adding a client session. This corresponds
@@ -130,15 +134,15 @@
* TODO(b/167966510): these are currently created per client, but these
* should be shared.
*/
- void setMaxThreads(size_t threads);
- size_t getMaxThreads();
+ LIBBINDER_EXPORTED void setMaxThreads(size_t threads);
+ LIBBINDER_EXPORTED size_t getMaxThreads();
/**
* By default, the latest protocol version which is supported by a client is
* used. However, this can be used in order to prevent newer protocol
* versions from ever being used. This is expected to be useful for testing.
*/
- [[nodiscard]] bool setProtocolVersion(uint32_t version);
+ [[nodiscard]] LIBBINDER_EXPORTED bool setProtocolVersion(uint32_t version);
/**
* Set the supported transports for sending and receiving file descriptors.
@@ -146,7 +150,7 @@
* Clients will propose a mode when connecting. If the mode is not in the
* provided list, the connection will be rejected.
*/
- void setSupportedFileDescriptorTransportModes(
+ LIBBINDER_EXPORTED void setSupportedFileDescriptorTransportModes(
const std::vector<RpcSession::FileDescriptorTransportMode>& modes);
/**
@@ -155,11 +159,11 @@
*
* Holds a strong reference to the root object.
*/
- void setRootObject(const sp<IBinder>& binder);
+ LIBBINDER_EXPORTED void setRootObject(const sp<IBinder>& binder);
/**
* Holds a weak reference to the root object.
*/
- void setRootObjectWeak(const wp<IBinder>& binder);
+ LIBBINDER_EXPORTED void setRootObjectWeak(const wp<IBinder>& binder);
/**
* Allows a root object to be created for each session.
*
@@ -174,9 +178,9 @@
* validate the size, then cast the type-erased pointer to a pointer to the actual type of the
* address, e.g., const void* to const sockaddr_vm*.
*/
- void setPerSessionRootObject(
+ LIBBINDER_EXPORTED void setPerSessionRootObject(
std::function<sp<IBinder>(wp<RpcSession> session, const void*, size_t)>&& object);
- sp<IBinder> getRootObject();
+ LIBBINDER_EXPORTED sp<IBinder> getRootObject();
/**
* Set optional filter of incoming connections based on the peer's address.
@@ -186,24 +190,25 @@
* See the description of setPerSessionRootObject() for details about
* the callable's arguments.
*/
- void setConnectionFilter(std::function<bool(const void*, size_t)>&& filter);
+ LIBBINDER_EXPORTED void setConnectionFilter(std::function<bool(const void*, size_t)>&& filter);
/**
* Set optional modifier of each newly created server socket.
*
* The only argument is a successfully created file descriptor, not bound to an address yet.
*/
- void setServerSocketModifier(std::function<void(binder::borrowed_fd)>&& modifier);
+ LIBBINDER_EXPORTED void setServerSocketModifier(
+ std::function<void(binder::borrowed_fd)>&& modifier);
/**
* See RpcTransportCtx::getCertificate
*/
- std::vector<uint8_t> getCertificate(RpcCertificateFormat);
+ LIBBINDER_EXPORTED std::vector<uint8_t> getCertificate(RpcCertificateFormat);
/**
* Runs join() in a background thread. Immediately returns.
*/
- void start();
+ LIBBINDER_EXPORTED void start();
/**
* You must have at least one client session before calling this.
@@ -216,7 +221,7 @@
* still occurring. To ensure that the service is fully shutdown, you might
* want to call shutdown after 'join' returns.
*/
- void join();
+ LIBBINDER_EXPORTED void join();
/**
* Shut down any existing join(). Return true if successfully shut down, false otherwise
@@ -225,20 +230,20 @@
*
* Warning: this will hang if it is called from its own thread.
*/
- [[nodiscard]] bool shutdown();
+ [[nodiscard]] LIBBINDER_EXPORTED bool shutdown();
/**
* For debugging!
*/
- std::vector<sp<RpcSession>> listSessions();
- size_t numUninitializedSessions();
+ LIBBINDER_EXPORTED std::vector<sp<RpcSession>> listSessions();
+ LIBBINDER_EXPORTED size_t numUninitializedSessions();
/**
* Whether any requests are currently being processed.
*/
- bool hasActiveRequests();
+ LIBBINDER_EXPORTED bool hasActiveRequests();
- ~RpcServer();
+ LIBBINDER_EXPORTED ~RpcServer();
private:
friend RpcServerTrusty;
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index 11fbde9..40102bb 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -15,6 +15,7 @@
*/
#pragma once
+#include <binder/Common.h>
#include <binder/IBinder.h>
#include <binder/RpcThreads.h>
#include <binder/RpcTransport.h>
@@ -57,12 +58,13 @@
class RpcSession final : public virtual RefBase {
public:
// Create an RpcSession with default configuration (raw sockets).
- static sp<RpcSession> make();
+ LIBBINDER_EXPORTED static sp<RpcSession> make();
// Create an RpcSession with the given configuration. |serverRpcCertificateFormat| and
// |serverCertificate| must have values or be nullopt simultaneously. If they have values, set
// server certificate.
- static sp<RpcSession> make(std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory);
+ LIBBINDER_EXPORTED static sp<RpcSession> make(
+ std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory);
/**
* Set the maximum number of incoming threads allowed to be made (for things like callbacks).
@@ -75,8 +77,8 @@
*
* TODO(b/189955605): start these lazily - currently all are started
*/
- void setMaxIncomingThreads(size_t threads);
- size_t getMaxIncomingThreads();
+ LIBBINDER_EXPORTED void setMaxIncomingThreads(size_t threads);
+ LIBBINDER_EXPORTED size_t getMaxIncomingThreads();
/**
* Set the maximum number of outgoing connections allowed to be made.
@@ -90,15 +92,15 @@
* created. This API is used to limit the amount of resources a server can request you
* create.
*/
- void setMaxOutgoingConnections(size_t connections);
- size_t getMaxOutgoingThreads();
+ LIBBINDER_EXPORTED void setMaxOutgoingConnections(size_t connections);
+ LIBBINDER_EXPORTED size_t getMaxOutgoingThreads();
/**
* By default, the minimum of the supported versions of the client and the
* server will be used. Usually, this API should only be used for debugging.
*/
- [[nodiscard]] bool setProtocolVersion(uint32_t version);
- std::optional<uint32_t> getProtocolVersion();
+ [[nodiscard]] LIBBINDER_EXPORTED bool setProtocolVersion(uint32_t version);
+ LIBBINDER_EXPORTED std::optional<uint32_t> getProtocolVersion();
enum class FileDescriptorTransportMode : uint8_t {
NONE = 0,
@@ -111,29 +113,30 @@
/**
* Set the transport for sending and receiving file descriptors.
*/
- void setFileDescriptorTransportMode(FileDescriptorTransportMode mode);
- FileDescriptorTransportMode getFileDescriptorTransportMode();
+ LIBBINDER_EXPORTED void setFileDescriptorTransportMode(FileDescriptorTransportMode mode);
+ LIBBINDER_EXPORTED FileDescriptorTransportMode getFileDescriptorTransportMode();
/**
* This should be called once per thread, matching 'join' in the remote
* process.
*/
- [[nodiscard]] status_t setupUnixDomainClient(const char* path);
+ [[nodiscard]] LIBBINDER_EXPORTED status_t setupUnixDomainClient(const char* path);
/**
* Connects to an RPC server over a nameless Unix domain socket pair.
*/
- [[nodiscard]] status_t setupUnixDomainSocketBootstrapClient(binder::unique_fd bootstrap);
+ [[nodiscard]] LIBBINDER_EXPORTED status_t
+ setupUnixDomainSocketBootstrapClient(binder::unique_fd bootstrap);
/**
- * Connects to an RPC server at the CVD & port.
+ * Connects to an RPC server at the CID & port.
*/
- [[nodiscard]] status_t setupVsockClient(unsigned int cvd, unsigned int port);
+ [[nodiscard]] LIBBINDER_EXPORTED status_t setupVsockClient(unsigned int cid, unsigned int port);
/**
* Connects to an RPC server at the given address and port.
*/
- [[nodiscard]] status_t setupInetClient(const char* addr, unsigned int port);
+ [[nodiscard]] LIBBINDER_EXPORTED status_t setupInetClient(const char* addr, unsigned int port);
/**
* Starts talking to an RPC server which has already been connected to. This
@@ -145,8 +148,8 @@
*
* For future compatibility, 'request' should not reference any stack data.
*/
- [[nodiscard]] status_t setupPreconnectedClient(binder::unique_fd fd,
- std::function<binder::unique_fd()>&& request);
+ [[nodiscard]] LIBBINDER_EXPORTED status_t
+ setupPreconnectedClient(binder::unique_fd fd, std::function<binder::unique_fd()>&& request);
/**
* For debugging!
@@ -155,24 +158,24 @@
* response will never be satisfied. All data sent here will be
* unceremoniously cast down the bottomless pit, /dev/null.
*/
- [[nodiscard]] status_t addNullDebuggingClient();
+ [[nodiscard]] LIBBINDER_EXPORTED status_t addNullDebuggingClient();
/**
* Query the other side of the session for the root object hosted by that
* process's RpcServer (if one exists)
*/
- sp<IBinder> getRootObject();
+ LIBBINDER_EXPORTED sp<IBinder> getRootObject();
/**
* Query the other side of the session for the maximum number of threads
* it supports (maximum number of concurrent non-nested synchronous transactions)
*/
- [[nodiscard]] status_t getRemoteMaxThreads(size_t* maxThreads);
+ [[nodiscard]] LIBBINDER_EXPORTED status_t getRemoteMaxThreads(size_t* maxThreads);
/**
* See RpcTransportCtx::getCertificate
*/
- std::vector<uint8_t> getCertificate(RpcCertificateFormat);
+ LIBBINDER_EXPORTED std::vector<uint8_t> getCertificate(RpcCertificateFormat);
/**
* Shuts down the service.
@@ -188,33 +191,34 @@
* complete before returning. This will hang if it is called from the
* session threadpool (when processing received calls).
*/
- [[nodiscard]] bool shutdownAndWait(bool wait);
+ [[nodiscard]] LIBBINDER_EXPORTED bool shutdownAndWait(bool wait);
- [[nodiscard]] status_t transact(const sp<IBinder>& binder, uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags);
+ [[nodiscard]] LIBBINDER_EXPORTED status_t transact(const sp<IBinder>& binder, uint32_t code,
+ const Parcel& data, Parcel* reply,
+ uint32_t flags);
/**
* Generally, you should not call this, unless you are testing error
* conditions, as this is called automatically by BpBinders when they are
* deleted (this is also why a raw pointer is used here)
*/
- [[nodiscard]] status_t sendDecStrong(const BpBinder* binder);
+ [[nodiscard]] LIBBINDER_EXPORTED status_t sendDecStrong(const BpBinder* binder);
/**
* Whether any requests are currently being processed.
*/
- bool hasActiveRequests();
+ LIBBINDER_EXPORTED bool hasActiveRequests();
- ~RpcSession();
+ LIBBINDER_EXPORTED ~RpcSession();
/**
* Server if this session is created as part of a server (symmetrical to
* client servers). Otherwise, nullptr.
*/
- sp<RpcServer> server();
+ LIBBINDER_EXPORTED sp<RpcServer> server();
// internal only
- const std::unique_ptr<RpcState>& state() { return mRpcBinderState; }
+ LIBBINDER_EXPORTED const std::unique_ptr<RpcState>& state() { return mRpcBinderState; }
private:
friend sp<RpcSession>;
diff --git a/libs/binder/include/binder/RpcThreads.h b/libs/binder/include/binder/RpcThreads.h
index d25f292..99fa6b8 100644
--- a/libs/binder/include/binder/RpcThreads.h
+++ b/libs/binder/include/binder/RpcThreads.h
@@ -22,27 +22,29 @@
#include <memory>
#include <thread>
+#include <binder/Common.h>
+
namespace android {
#ifdef BINDER_RPC_SINGLE_THREADED
-class RpcMutex {
+class LIBBINDER_EXPORTED RpcMutex {
public:
void lock() {}
void unlock() {}
};
-class RpcMutexUniqueLock {
+class LIBBINDER_EXPORTED RpcMutexUniqueLock {
public:
RpcMutexUniqueLock(RpcMutex&) {}
void unlock() {}
};
-class RpcMutexLockGuard {
+class LIBBINDER_EXPORTED RpcMutexLockGuard {
public:
RpcMutexLockGuard(RpcMutex&) {}
};
-class RpcConditionVariable {
+class LIBBINDER_EXPORTED RpcConditionVariable {
public:
void notify_one() {}
void notify_all() {}
@@ -65,7 +67,7 @@
}
};
-class RpcMaybeThread {
+class LIBBINDER_EXPORTED RpcMaybeThread {
public:
RpcMaybeThread() = default;
diff --git a/libs/binder/include/binder/RpcTransport.h b/libs/binder/include/binder/RpcTransport.h
index a50cdc1..843c4bf 100644
--- a/libs/binder/include/binder/RpcTransport.h
+++ b/libs/binder/include/binder/RpcTransport.h
@@ -27,6 +27,7 @@
#include <utils/Errors.h>
+#include <binder/Common.h>
#include <binder/Functional.h>
#include <binder/RpcCertificateFormat.h>
#include <binder/RpcThreads.h>
@@ -51,7 +52,7 @@
// Represents a socket connection.
// No thread-safety is guaranteed for these APIs.
-class RpcTransport {
+class LIBBINDER_EXPORTED RpcTransport {
public:
virtual ~RpcTransport() = default;
@@ -123,7 +124,7 @@
// Represents the context that generates the socket connection.
// All APIs are thread-safe. See RpcTransportCtxRaw and RpcTransportCtxTls for details.
-class RpcTransportCtx {
+class LIBBINDER_EXPORTED RpcTransportCtx {
public:
virtual ~RpcTransportCtx() = default;
@@ -154,7 +155,7 @@
// A factory class that generates RpcTransportCtx.
// All APIs are thread-safe.
-class RpcTransportCtxFactory {
+class LIBBINDER_EXPORTED RpcTransportCtxFactory {
public:
virtual ~RpcTransportCtxFactory() = default;
// Creates server context.
@@ -171,7 +172,7 @@
RpcTransportCtxFactory() = default;
};
-struct RpcTransportFd final {
+struct LIBBINDER_EXPORTED RpcTransportFd final {
private:
mutable bool isPolling{false};
diff --git a/libs/binder/include/binder/RpcTransportRaw.h b/libs/binder/include/binder/RpcTransportRaw.h
index 6fb1f92..bfa73ea 100644
--- a/libs/binder/include/binder/RpcTransportRaw.h
+++ b/libs/binder/include/binder/RpcTransportRaw.h
@@ -21,6 +21,7 @@
#include <memory>
+#include <binder/Common.h>
#include <binder/RpcTransport.h>
namespace android {
@@ -28,11 +29,11 @@
// RpcTransportCtxFactory with TLS disabled.
class RpcTransportCtxFactoryRaw : public RpcTransportCtxFactory {
public:
- static std::unique_ptr<RpcTransportCtxFactory> make();
+ LIBBINDER_EXPORTED static std::unique_ptr<RpcTransportCtxFactory> make();
- std::unique_ptr<RpcTransportCtx> newServerCtx() const override;
- std::unique_ptr<RpcTransportCtx> newClientCtx() const override;
- const char* toCString() const override;
+ LIBBINDER_EXPORTED std::unique_ptr<RpcTransportCtx> newServerCtx() const override;
+ LIBBINDER_EXPORTED std::unique_ptr<RpcTransportCtx> newClientCtx() const override;
+ LIBBINDER_EXPORTED const char* toCString() const override;
private:
RpcTransportCtxFactoryRaw() = default;
diff --git a/libs/binder/include/binder/SafeInterface.h b/libs/binder/include/binder/SafeInterface.h
index 96b9733..c671eed 100644
--- a/libs/binder/include/binder/SafeInterface.h
+++ b/libs/binder/include/binder/SafeInterface.h
@@ -16,6 +16,7 @@
#pragma once
+#include <binder/Common.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
@@ -34,7 +35,7 @@
namespace SafeInterface {
// ParcelHandler is responsible for writing/reading various types to/from a Parcel in a generic way
-class ParcelHandler {
+class LIBBINDER_EXPORTED ParcelHandler {
public:
explicit ParcelHandler(const char* logTag) : mLogTag(logTag) {}
@@ -243,7 +244,7 @@
} // namespace SafeInterface
template <typename Interface>
-class SafeBpInterface : public BpInterface<Interface> {
+class LIBBINDER_EXPORTED SafeBpInterface : public BpInterface<Interface> {
protected:
SafeBpInterface(const sp<IBinder>& impl, const char* logTag)
: BpInterface<Interface>(impl), mLogTag(logTag) {}
@@ -438,7 +439,7 @@
};
template <typename Interface>
-class SafeBnInterface : public BnInterface<Interface> {
+class LIBBINDER_EXPORTED SafeBnInterface : public BnInterface<Interface> {
public:
explicit SafeBnInterface(const char* logTag) : mLogTag(logTag) {}
diff --git a/libs/binder/include/binder/Stability.h b/libs/binder/include/binder/Stability.h
index ce4362f..cafb8aa 100644
--- a/libs/binder/include/binder/Stability.h
+++ b/libs/binder/include/binder/Stability.h
@@ -16,6 +16,7 @@
#pragma once
+#include <binder/Common.h>
#include <binder/IBinder.h>
#include <string>
@@ -54,7 +55,7 @@
// 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 the local partition.
- static void forceDowngradeToLocalStability(const sp<IBinder>& binder);
+ LIBBINDER_EXPORTED static void forceDowngradeToLocalStability(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
@@ -76,30 +77,30 @@
// 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 the vendor partition.
- static void forceDowngradeToVendorStability(const sp<IBinder>& binder);
+ LIBBINDER_EXPORTED static void forceDowngradeToVendorStability(const sp<IBinder>& binder);
// 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 the system partition.
- static void forceDowngradeToSystemStability(const sp<IBinder>& binder);
+ LIBBINDER_EXPORTED static void forceDowngradeToSystemStability(const sp<IBinder>& binder);
// 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
// is provided.
// E.g. stability is according to libbinder compilation unit
- static void markCompilationUnit(IBinder* binder);
+ LIBBINDER_EXPORTED static void markCompilationUnit(IBinder* binder);
// 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
// is provided.
// E.g. stability is according to libbinder_ndk or Java SDK AND the interface
// expressed here is guaranteed to be stable for multiple years (Stable AIDL)
- static void markVintf(IBinder* binder);
+ LIBBINDER_EXPORTED static void markVintf(IBinder* binder);
// WARNING: for debugging only
- static std::string debugToString(const sp<IBinder>& binder);
+ LIBBINDER_EXPORTED static std::string debugToString(const sp<IBinder>& binder);
// WARNING: This is only ever expected to be called by auto-generated code or tests.
// You likely want to change or modify the stability of the interface you are using.
@@ -109,11 +110,12 @@
// expressed here is guaranteed to be stable for multiple years (Stable AIDL)
// If this is called when __ANDROID_VNDK__ is not defined, then it is UB and will likely
// break the device during GSI or other tests.
- static void markVndk(IBinder* binder);
+ LIBBINDER_EXPORTED static void markVndk(IBinder* binder);
// Returns true if the binder needs to be declared in the VINTF manifest or
// else false if the binder is local to the current partition.
- static bool requiresVintfDeclaration(const sp<IBinder>& binder);
+ LIBBINDER_EXPORTED static bool requiresVintfDeclaration(const sp<IBinder>& binder);
+
private:
// Parcel needs to read/write stability level in an unstable format.
friend ::android::Parcel;
diff --git a/libs/binder/include/binder/Status.h b/libs/binder/include/binder/Status.h
index af34695..49ccf7c 100644
--- a/libs/binder/include/binder/Status.h
+++ b/libs/binder/include/binder/Status.h
@@ -21,6 +21,7 @@
#include <sstream> // historical
#include <ostream>
+#include <binder/Common.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <string>
@@ -51,7 +52,7 @@
// // exception during handling.
// }
//
-class Status final {
+class LIBBINDER_EXPORTED Status final {
public:
// Keep the exception codes in sync with android/os/Parcel.java.
enum Exception {
diff --git a/libs/binder/include/binder/TextOutput.h b/libs/binder/include/binder/TextOutput.h
index 50158c3..0527eeb 100644
--- a/libs/binder/include/binder/TextOutput.h
+++ b/libs/binder/include/binder/TextOutput.h
@@ -16,6 +16,7 @@
#pragma once
+#include <binder/Common.h>
#include <utils/Errors.h>
#include <utils/String8.h>
@@ -26,8 +27,7 @@
// ---------------------------------------------------------------------------
namespace android {
-class TextOutput
-{
+class LIBBINDER_EXPORTED TextOutput {
public:
TextOutput();
virtual ~TextOutput();
@@ -52,17 +52,17 @@
// DO NOT USE: prefer libutils/libbase logs, which don't require static data to
// be allocated.
// Text output stream for printing to the log (via utils/Log.h).
-extern TextOutput& alog;
+extern LIBBINDER_EXPORTED TextOutput& alog;
// DO NOT USE: prefer libutils/libbase logs, which don't require static data to
// be allocated.
// Text output stream for printing to stdout.
-extern TextOutput& aout;
+extern LIBBINDER_EXPORTED TextOutput& aout;
// DO NOT USE: prefer libutils/libbase logs, which don't require static data to
// be allocated.
// Text output stream for printing to stderr.
-extern TextOutput& aerr;
+extern LIBBINDER_EXPORTED TextOutput& aerr;
typedef TextOutput& (*TextOutputManipFunc)(TextOutput&);
@@ -80,10 +80,9 @@
return to;
}
-TextOutput& operator<<(TextOutput& to, TextOutputManipFunc func);
+LIBBINDER_EXPORTED TextOutput& operator<<(TextOutput& to, TextOutputManipFunc func);
-class TypeCode
-{
+class LIBBINDER_EXPORTED TypeCode {
public:
inline explicit TypeCode(uint32_t code);
inline ~TypeCode();
@@ -94,10 +93,9 @@
uint32_t mCode;
};
-std::ostream& operator<<(std::ostream& to, const TypeCode& val);
+LIBBINDER_EXPORTED std::ostream& operator<<(std::ostream& to, const TypeCode& val);
-class HexDump
-{
+class LIBBINDER_EXPORTED HexDump {
public:
HexDump(const void *buf, size_t size, size_t bytesPerLine=16);
inline ~HexDump();
@@ -123,7 +121,7 @@
bool mCArrayStyle;
};
-std::ostream& operator<<(std::ostream& to, const HexDump& val);
+LIBBINDER_EXPORTED std::ostream& operator<<(std::ostream& to, const HexDump& val);
inline TextOutput& operator<<(TextOutput& to,
decltype(std::endl<char,
std::char_traits<char>>)
diff --git a/libs/binder/include/binder/Trace.h b/libs/binder/include/binder/Trace.h
index 95318b2..2f450cb 100644
--- a/libs/binder/include/binder/Trace.h
+++ b/libs/binder/include/binder/Trace.h
@@ -22,6 +22,8 @@
#include <cutils/trace.h>
#endif
+#include <binder/Common.h>
+
#ifdef ATRACE_TAG_AIDL
#if ATRACE_TAG_AIDL != (1 << 24)
#error "Mismatched ATRACE_TAG_AIDL definitions"
@@ -39,9 +41,10 @@
// libcutils/libutils
void trace_begin(uint64_t tag, const char* name);
void trace_end(uint64_t tag);
+void trace_int(uint64_t tag, const char* name, int32_t value);
} // namespace os
-class ScopedTrace {
+class LIBBINDER_EXPORTED ScopedTrace {
public:
inline ScopedTrace(uint64_t tag, const char* name) : mTag(tag) { os::trace_begin(mTag, name); }
diff --git a/libs/binder/include/binder/unique_fd.h b/libs/binder/include/binder/unique_fd.h
index 439b8a2..3de4149 100644
--- a/libs/binder/include/binder/unique_fd.h
+++ b/libs/binder/include/binder/unique_fd.h
@@ -16,6 +16,8 @@
#pragma once
+#include <binder/Common.h>
+
#ifndef BINDER_NO_LIBBASE
#include <android-base/unique_fd.h>
@@ -43,7 +45,7 @@
//
// return 0; // Descriptor is closed for you.
//
-class unique_fd final {
+class LIBBINDER_EXPORTED unique_fd final {
public:
unique_fd() {}
@@ -99,7 +101,7 @@
// If you think of unique_fd as being like std::string in that represents
// ownership, borrowed_fd is like std::string_view (and int is like const
// char*).
-struct borrowed_fd {
+struct LIBBINDER_EXPORTED borrowed_fd {
/* implicit */ borrowed_fd(int fd) : fd_(fd) {} // NOLINT
/* implicit */ borrowed_fd(const unique_fd& ufd) : fd_(ufd.get()) {} // NOLINT
diff --git a/libs/binder/liblog_stub/Android.bp b/libs/binder/liblog_stub/Android.bp
index f2ca22f..2de6658 100644
--- a/libs/binder/liblog_stub/Android.bp
+++ b/libs/binder/liblog_stub/Android.bp
@@ -30,6 +30,7 @@
product_available: true,
recovery_available: true,
vendor_available: true,
+ cmake_snapshot_supported: true,
target: {
windows: {
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 9a2d14a..26c228d 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -32,17 +32,11 @@
],
}
-cc_library {
- name: "libbinder_ndk",
-
+cc_defaults {
+ name: "libbinder_ndk_common_defaults",
host_supported: true,
recovery_available: true,
- llndk: {
- symbol_file: "libbinder_ndk.map.txt",
- export_llndk_headers: ["libvendorsupport_llndk_headers"],
- },
-
export_include_dirs: [
"include_cpp",
"include_ndk",
@@ -50,7 +44,6 @@
],
cflags: [
- "-DBINDER_WITH_KERNEL_IPC",
"-Wall",
"-Wextra",
"-Wextra-semi",
@@ -59,14 +52,48 @@
srcs: [
"ibinder.cpp",
- "ibinder_jni.cpp",
"libbinder.cpp",
"parcel.cpp",
+ "stability.cpp",
+ "status.cpp",
+ ],
+}
+
+cc_library_host_shared {
+ name: "libbinder_ndk_sdk",
+
+ defaults: [
+ "libbinder_ndk_common_defaults",
+ "binder_sdk_defaults",
+ ],
+ cmake_snapshot_supported: true,
+
+ shared_libs: [
+ "libbinder_sdk",
+ "libutils_binder_sdk",
+ ],
+}
+
+cc_library {
+ name: "libbinder_ndk",
+
+ defaults: ["libbinder_ndk_common_defaults"],
+ cmake_snapshot_supported: false,
+
+ llndk: {
+ symbol_file: "libbinder_ndk.map.txt",
+ export_llndk_headers: ["libvendorsupport_llndk_headers"],
+ },
+
+ cflags: [
+ "-DBINDER_WITH_KERNEL_IPC",
+ ],
+
+ srcs: [
+ "ibinder_jni.cpp",
"parcel_jni.cpp",
"persistable_bundle.cpp",
"process.cpp",
- "stability.cpp",
- "status.cpp",
"service_manager.cpp",
],
@@ -195,6 +222,7 @@
host_supported: true,
// TODO(b/153609531): remove when no longer needed.
native_bridge_supported: true,
+ cmake_snapshot_supported: true,
target: {
darwin: {
enabled: false,
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index 725744c..2deb254 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -26,10 +26,7 @@
},
apex_available: [
"//apex_available:platform",
- "com.android.compos",
- "com.android.rkpd",
- "com.android.uwb",
- "com.android.virt",
+ "//apex_available:anyapex",
],
min_sdk_version: "Tiramisu",
}
@@ -67,9 +64,7 @@
},
apex_available: [
"//apex_available:platform",
- "com.android.compos",
- "com.android.uwb",
- "com.android.virt",
+ "//apex_available:anyapex",
],
min_sdk_version: "Tiramisu",
}
@@ -94,10 +89,7 @@
},
apex_available: [
"//apex_available:platform",
- "com.android.compos",
- "com.android.rkpd",
- "com.android.uwb",
- "com.android.virt",
+ "//apex_available:anyapex",
],
min_sdk_version: "Tiramisu",
lints: "none",
@@ -153,10 +145,7 @@
},
apex_available: [
"//apex_available:platform",
- "com.android.compos",
- "com.android.rkpd",
- "com.android.uwb",
- "com.android.virt",
+ "//apex_available:anyapex",
],
min_sdk_version: "Tiramisu",
}
diff --git a/libs/binder/rust/tests/Android.bp b/libs/binder/rust/tests/Android.bp
index 2d1175b..f5b0071 100644
--- a/libs/binder/rust/tests/Android.bp
+++ b/libs/binder/rust/tests/Android.bp
@@ -114,7 +114,6 @@
crate_name: "binder_rs_serialization_bindgen",
wrapper_src: "serialization.hpp",
source_stem: "bindings",
- cpp_std: "gnu++17",
bindgen_flags: [
"--allowlist-type", "Transaction",
"--allowlist-var", "TESTDATA_.*",
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index bd24a20..3fe55d6 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -25,6 +25,7 @@
cc_defaults {
name: "binder_test_defaults",
+ cmake_snapshot_supported: true,
cflags: [
"-Wall",
"-Werror",
@@ -62,6 +63,7 @@
"binderStatusUnitTest.cpp",
"binderMemoryHeapBaseUnitTest.cpp",
"binderRecordedTransactionTest.cpp",
+ "binderPersistableBundleTest.cpp",
],
shared_libs: [
"libbinder",
@@ -141,6 +143,7 @@
name: "binderRpcTestIface",
vendor_available: true,
host_supported: true,
+ cmake_snapshot_supported: true,
unstable: true,
srcs: [
"BinderRpcTestClientInfo.aidl",
@@ -222,6 +225,7 @@
cc_defaults {
name: "binderRpcTest_common_defaults",
host_supported: true,
+ cmake_snapshot_supported: true,
target: {
darwin: {
enabled: false,
@@ -381,6 +385,9 @@
static_libs: [
"libbinder_rpc_single_threaded_no_kernel",
],
+ shared_libs: [
+ "libbinder_ndk",
+ ],
}
cc_binary {
@@ -461,6 +468,20 @@
}
cc_test {
+ name: "binderRpcTestNoKernelAtAll",
+ defaults: [
+ "binderRpcTest_defaults",
+ "binderRpcTest_static_defaults",
+ ],
+ static_libs: [
+ "libbinder_rpc_no_kernel",
+ ],
+ cflags: [
+ "-DBINDER_NO_KERNEL_IPC_TESTING",
+ ],
+}
+
+cc_test {
name: "binderRpcTestSingleThreaded",
defaults: [
"binderRpcTest_defaults",
@@ -487,6 +508,9 @@
static_libs: [
"libbinder_rpc_single_threaded_no_kernel",
],
+ shared_libs: [
+ "libbinder_ndk",
+ ],
}
cc_test {
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 9788d9d..00406ed 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -38,6 +38,7 @@
#include <binder/IServiceManager.h>
#include <binder/RpcServer.h>
#include <binder/RpcSession.h>
+#include <binder/Status.h>
#include <binder/unique_fd.h>
#include <utils/Flattenable.h>
@@ -57,6 +58,7 @@
using namespace std::chrono_literals;
using android::base::testing::HasValue;
using android::base::testing::Ok;
+using android::binder::Status;
using android::binder::unique_fd;
using testing::ExplainMatchResult;
using testing::Matcher;
@@ -253,7 +255,7 @@
public:
virtual void SetUp() {
m_server = static_cast<BinderLibTestEnv *>(binder_env)->getServer();
- IPCThreadState::self()->restoreCallingWorkSource(0);
+ IPCThreadState::self()->restoreCallingWorkSource(0);
}
virtual void TearDown() {
}
@@ -461,6 +463,35 @@
EXPECT_EQ(NO_ERROR, sm->addService(String16("binderLibTest-manager"), binder));
}
+TEST_F(BinderLibTest, RegisterForNotificationsFailure) {
+ auto sm = defaultServiceManager();
+ using LocalRegistrationCallback = IServiceManager::LocalRegistrationCallback;
+ class LocalRegistrationCallbackImpl : public virtual LocalRegistrationCallback {
+ void onServiceRegistration(const String16&, const sp<IBinder>&) override {}
+ virtual ~LocalRegistrationCallbackImpl() {}
+ };
+ sp<LocalRegistrationCallback> cb = sp<LocalRegistrationCallbackImpl>::make();
+
+ EXPECT_EQ(BAD_VALUE, sm->registerForNotifications(String16("ValidName"), nullptr));
+ EXPECT_EQ(UNKNOWN_ERROR, sm->registerForNotifications(String16("InvalidName!$"), cb));
+}
+
+TEST_F(BinderLibTest, UnregisterForNotificationsFailure) {
+ auto sm = defaultServiceManager();
+ using LocalRegistrationCallback = IServiceManager::LocalRegistrationCallback;
+ class LocalRegistrationCallbackImpl : public virtual LocalRegistrationCallback {
+ void onServiceRegistration(const String16&, const sp<IBinder>&) override {}
+ virtual ~LocalRegistrationCallbackImpl() {}
+ };
+ sp<LocalRegistrationCallback> cb = sp<LocalRegistrationCallbackImpl>::make();
+
+ EXPECT_EQ(OK, sm->registerForNotifications(String16("ValidName"), cb));
+
+ EXPECT_EQ(BAD_VALUE, sm->unregisterForNotifications(String16("ValidName"), nullptr));
+ EXPECT_EQ(BAD_VALUE, sm->unregisterForNotifications(String16("AnotherValidName"), cb));
+ EXPECT_EQ(BAD_VALUE, sm->unregisterForNotifications(String16("InvalidName!!!"), cb));
+}
+
TEST_F(BinderLibTest, WasParceled) {
auto binder = sp<BBinder>::make();
EXPECT_FALSE(binder->wasParceled());
diff --git a/libs/binder/tests/binderPersistableBundleTest.cpp b/libs/binder/tests/binderPersistableBundleTest.cpp
new file mode 100644
index 0000000..392e018
--- /dev/null
+++ b/libs/binder/tests/binderPersistableBundleTest.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2024 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 <binder/PersistableBundle.h>
+#include <gtest/gtest.h>
+#include <numeric>
+
+using android::OK;
+using android::Parcel;
+using android::status_t;
+using android::String16;
+using android::String8;
+using android::os::PersistableBundle;
+
+namespace android {
+
+inline std::string to_string(String16 const& str) {
+ return String8{str}.c_str();
+}
+
+namespace os {
+
+template <typename T>
+inline std::ostream& operator<<(std::ostream& out, std::vector<T> const& vec) {
+ using std::to_string;
+ auto str =
+ std::accumulate(vec.begin(), vec.end(), std::string{},
+ [](std::string const& a, auto const& b) { return a + to_string(b); });
+ return out << str;
+}
+
+inline std::ostream& operator<<(std::ostream& out, PersistableBundle const& pb) {
+#define PRINT(TYPENAME, TYPE) \
+ for (auto const& key : pb.get##TYPENAME##Keys()) { \
+ TYPE val{}; \
+ pb.get##TYPENAME(key, &val); \
+ out << #TYPE " " << key << ": " << val << std::endl; \
+ }
+
+ out << "size: " << pb.size() << std::endl;
+ PRINT(Boolean, bool);
+ PRINT(Int, int);
+ PRINT(Long, int64_t);
+ PRINT(Double, double);
+ PRINT(String, String16);
+ PRINT(BooleanVector, std::vector<bool>);
+ PRINT(IntVector, std::vector<int32_t>);
+ PRINT(LongVector, std::vector<int64_t>);
+ PRINT(DoubleVector, std::vector<double>);
+ PRINT(StringVector, std::vector<String16>);
+ PRINT(PersistableBundle, PersistableBundle);
+
+#undef PRINT
+
+ return out;
+}
+
+} // namespace os
+} // namespace android
+
+static const String16 kKey{"key"};
+
+static PersistableBundle createSimplePersistableBundle() {
+ PersistableBundle pb{};
+ pb.putInt(kKey, 64);
+ return pb;
+}
+
+#define TEST_PUT_AND_GET(TYPENAME, TYPE, ...) \
+ TEST(PersistableBundle, PutAndGet##TYPENAME) { \
+ TYPE const expected{__VA_ARGS__}; \
+ PersistableBundle pb{}; \
+ \
+ pb.put##TYPENAME(kKey, expected); \
+ \
+ std::set<String16> expectedKeys{kKey}; \
+ EXPECT_EQ(pb.get##TYPENAME##Keys(), expectedKeys); \
+ \
+ TYPE val{}; \
+ EXPECT_TRUE(pb.get##TYPENAME(kKey, &val)); \
+ EXPECT_EQ(val, expected); \
+ }
+
+TEST_PUT_AND_GET(Boolean, bool, true);
+TEST_PUT_AND_GET(Int, int, 64);
+TEST_PUT_AND_GET(Long, int64_t, 42);
+TEST_PUT_AND_GET(Double, double, 42.64);
+TEST_PUT_AND_GET(String, String16, String16{"foo"});
+TEST_PUT_AND_GET(BooleanVector, std::vector<bool>, true, true);
+TEST_PUT_AND_GET(IntVector, std::vector<int32_t>, 1, 2);
+TEST_PUT_AND_GET(LongVector, std::vector<int64_t>, 1, 2);
+TEST_PUT_AND_GET(DoubleVector, std::vector<double>, 4.2, 5.9);
+TEST_PUT_AND_GET(StringVector, std::vector<String16>, String16{"foo"}, String16{"bar"});
+TEST_PUT_AND_GET(PersistableBundle, PersistableBundle, createSimplePersistableBundle());
+
+TEST(PersistableBundle, ParcelAndUnparcel) {
+ PersistableBundle expected = createSimplePersistableBundle();
+ PersistableBundle out{};
+
+ Parcel p{};
+ EXPECT_EQ(expected.writeToParcel(&p), 0);
+ p.setDataPosition(0);
+ EXPECT_EQ(out.readFromParcel(&p), 0);
+
+ EXPECT_EQ(expected, out);
+}
+
+TEST(PersistableBundle, OverwriteKey) {
+ PersistableBundle pb{};
+
+ pb.putInt(kKey, 64);
+ pb.putDouble(kKey, 0.5);
+
+ EXPECT_EQ(pb.getIntKeys().size(), 0);
+ EXPECT_EQ(pb.getDoubleKeys().size(), 1);
+
+ double out;
+ EXPECT_TRUE(pb.getDouble(kKey, &out));
+ EXPECT_EQ(out, 0.5);
+}
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index c044d39..19882ea 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -1278,7 +1278,7 @@
for (const auto& clientVersion : testVersions()) {
for (const auto& serverVersion : testVersions()) {
for (bool singleThreaded : {false, true}) {
- for (bool noKernel : {false, true}) {
+ for (bool noKernel : noKernelValues()) {
ret.push_back(BinderRpc::ParamType{
.type = type,
.security = security,
@@ -1299,7 +1299,7 @@
.clientVersion = RPC_WIRE_PROTOCOL_VERSION,
.serverVersion = RPC_WIRE_PROTOCOL_VERSION,
.singleThreaded = false,
- .noKernel = false,
+ .noKernel = !kEnableKernelIpcTesting,
});
}
}
diff --git a/libs/binder/tests/binderRpcTestCommon.h b/libs/binder/tests/binderRpcTestCommon.h
index acc0373..dc22647 100644
--- a/libs/binder/tests/binderRpcTestCommon.h
+++ b/libs/binder/tests/binderRpcTestCommon.h
@@ -64,6 +64,12 @@
namespace android {
+#ifdef BINDER_NO_KERNEL_IPC_TESTING
+constexpr bool kEnableKernelIpcTesting = false;
+#else
+constexpr bool kEnableKernelIpcTesting = true;
+#endif
+
constexpr char kLocalInetAddress[] = "127.0.0.1";
enum class RpcSecurity { RAW, TLS };
@@ -72,6 +78,14 @@
return {RpcSecurity::RAW, RpcSecurity::TLS};
}
+static inline std::vector<bool> noKernelValues() {
+ std::vector<bool> values = {true};
+ if (kEnableKernelIpcTesting) {
+ values.push_back(false);
+ }
+ return values;
+}
+
static inline bool hasExperimentalRpc() {
#ifdef BINDER_RPC_TO_TRUSTY_TEST
// Trusty services do not support the experimental version,
diff --git a/libs/binder/trusty/OS.cpp b/libs/binder/trusty/OS.cpp
index a8dabc3..157ab3c 100644
--- a/libs/binder/trusty/OS.cpp
+++ b/libs/binder/trusty/OS.cpp
@@ -21,6 +21,7 @@
#include <lib/rand/rand.h>
#endif
+#include <binder/Common.h>
#include <binder/RpcTransportTipcTrusty.h>
#include <log/log.h>
#include <trusty_log.h>
@@ -39,6 +40,8 @@
void trace_end(uint64_t) {}
+void trace_int(uint64_t, const char*, int32_t) {}
+
uint64_t GetThreadId() {
return 0;
}
@@ -92,7 +95,8 @@
} // namespace android::binder::os
-int __android_log_print(int prio [[maybe_unused]], const char* tag, const char* fmt, ...) {
+LIBBINDER_EXPORTED int __android_log_print(int prio [[maybe_unused]], const char* tag,
+ const char* fmt, ...) {
#ifdef TRUSTY_USERSPACE
#define trusty_tlog _tlog
#define trusty_vtlog _vtlog
diff --git a/libs/binder/trusty/include/binder/RpcTransportTipcTrusty.h b/libs/binder/trusty/include/binder/RpcTransportTipcTrusty.h
index 8eae8c2..91c6008 100644
--- a/libs/binder/trusty/include/binder/RpcTransportTipcTrusty.h
+++ b/libs/binder/trusty/include/binder/RpcTransportTipcTrusty.h
@@ -26,7 +26,7 @@
namespace android {
// RpcTransportCtxFactory with TLS disabled.
-class RpcTransportCtxFactoryTipcTrusty : public RpcTransportCtxFactory {
+class LIBBINDER_EXPORTED RpcTransportCtxFactoryTipcTrusty : public RpcTransportCtxFactory {
public:
static std::unique_ptr<RpcTransportCtxFactory> make();
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 6c45746..2547297 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -87,6 +87,7 @@
"android/gui/DropInputMode.aidl",
"android/gui/StalledTransactionInfo.aidl",
"android/**/TouchOcclusionMode.aidl",
+ "android/gui/TrustedOverlay.aidl",
],
}
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 0a28799..c82bde9 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -89,7 +89,7 @@
frameRateSelectionStrategy(ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_PROPAGATE),
fixedTransformHint(ui::Transform::ROT_INVALID),
autoRefresh(false),
- isTrustedOverlay(false),
+ trustedOverlay(gui::TrustedOverlay::UNSET),
bufferCrop(Rect::INVALID_RECT),
destinationFrame(Rect::INVALID_RECT),
dropInputMode(gui::DropInputMode::NONE) {
@@ -179,7 +179,7 @@
SAFE_PARCEL(output.write, stretchEffect);
SAFE_PARCEL(output.write, bufferCrop);
SAFE_PARCEL(output.write, destinationFrame);
- SAFE_PARCEL(output.writeBool, isTrustedOverlay);
+ SAFE_PARCEL(output.writeInt32, static_cast<uint32_t>(trustedOverlay));
SAFE_PARCEL(output.writeUint32, static_cast<uint32_t>(dropInputMode));
@@ -308,7 +308,9 @@
SAFE_PARCEL(input.read, stretchEffect);
SAFE_PARCEL(input.read, bufferCrop);
SAFE_PARCEL(input.read, destinationFrame);
- SAFE_PARCEL(input.readBool, &isTrustedOverlay);
+ uint32_t trustedOverlayInt;
+ SAFE_PARCEL(input.readUint32, &trustedOverlayInt);
+ trustedOverlay = static_cast<gui::TrustedOverlay>(trustedOverlayInt);
uint32_t mode;
SAFE_PARCEL(input.readUint32, &mode);
@@ -674,7 +676,7 @@
}
if (other.what & eTrustedOverlayChanged) {
what |= eTrustedOverlayChanged;
- isTrustedOverlay = other.isTrustedOverlay;
+ trustedOverlay = other.trustedOverlay;
}
if (other.what & eStretchChanged) {
what |= eStretchChanged;
@@ -779,7 +781,7 @@
CHECK_DIFF(diff, eFrameRateSelectionStrategyChanged, other, frameRateSelectionStrategy);
CHECK_DIFF(diff, eFixedTransformHintChanged, other, fixedTransformHint);
CHECK_DIFF(diff, eAutoRefreshChanged, other, autoRefresh);
- CHECK_DIFF(diff, eTrustedOverlayChanged, other, isTrustedOverlay);
+ CHECK_DIFF(diff, eTrustedOverlayChanged, other, trustedOverlay);
CHECK_DIFF(diff, eStretchChanged, other, stretchEffect);
CHECK_DIFF(diff, eBufferCropChanged, other, bufferCrop);
CHECK_DIFF(diff, eDestinationFrameChanged, other, destinationFrame);
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 0a85cf8..b420aab 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -2179,6 +2179,13 @@
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTrustedOverlay(
const sp<SurfaceControl>& sc, bool isTrustedOverlay) {
+ return setTrustedOverlay(sc,
+ isTrustedOverlay ? gui::TrustedOverlay::ENABLED
+ : gui::TrustedOverlay::UNSET);
+}
+
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTrustedOverlay(
+ const sp<SurfaceControl>& sc, gui::TrustedOverlay trustedOverlay) {
layer_state_t* s = getLayerState(sc);
if (!s) {
mStatus = BAD_INDEX;
@@ -2186,7 +2193,7 @@
}
s->what |= layer_state_t::eTrustedOverlayChanged;
- s->isTrustedOverlay = isTrustedOverlay;
+ s->trustedOverlay = trustedOverlay;
return *this;
}
@@ -3118,6 +3125,10 @@
->removeWindowInfosListener(windowInfosListener,
ComposerServiceAIDL::getComposerService());
}
+
+void SurfaceComposerClient::notifyShutdown() {
+ ComposerServiceAIDL::getComposerService()->notifyShutdown();
+}
// ----------------------------------------------------------------------------
status_t ScreenshotClient::captureDisplay(const DisplayCaptureArgs& captureArgs,
diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
index 11ccc9c..6d018ea 100644
--- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
+++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
@@ -573,4 +573,11 @@
@nullable StalledTransactionInfo getStalledTransactionInfo(int pid);
SchedulingPolicy getSchedulingPolicy();
+
+ /**
+ * Notifies the SurfaceFlinger that the ShutdownThread is running. When it is called,
+ * transaction traces will be captured and writted into a file.
+ * This method should not block the ShutdownThread therefore it's handled asynchronously.
+ */
+ oneway void notifyShutdown();
}
diff --git a/libs/gui/android/gui/TrustedOverlay.aidl b/libs/gui/android/gui/TrustedOverlay.aidl
new file mode 100644
index 0000000..06fb5f0
--- /dev/null
+++ b/libs/gui/android/gui/TrustedOverlay.aidl
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2024, 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 android.gui;
+
+
+/**
+ * Trusted overlay state prevents layers from being considered as obscuring for
+ * input occlusion detection purposes.
+ *
+ * @hide
+ */
+@Backing(type="int")
+enum TrustedOverlay {
+ /**
+ * The default, layer will inherit the state from its parents. If the parent state is also
+ * unset, the layer will be considered as untrusted.
+ */
+ UNSET,
+
+ /**
+ * Treats this layer and all its children as an untrusted overlay. This will override any
+ * state set by its parent layers.
+ */
+ DISABLED,
+
+ /**
+ * Treats this layer and all its children as a trusted overlay unless the child layer
+ * explicitly disables its trusted state.
+ */
+ ENABLED
+}
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index ca7acf9..82889ef 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -30,6 +30,7 @@
#include <android/gui/DropInputMode.h>
#include <android/gui/FocusRequest.h>
+#include <android/gui/TrustedOverlay.h>
#include <ftl/flags.h>
#include <gui/DisplayCaptureArgs.h>
@@ -385,7 +386,7 @@
// An inherited state that indicates that this surface control and its children
// should be trusted for input occlusion detection purposes
- bool isTrustedOverlay;
+ gui::TrustedOverlay trustedOverlay;
// Stretch effect to be applied to this layer
StretchEffect stretchEffect;
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index e2307ed..9712907 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -719,6 +719,8 @@
// Sets that this surface control and its children are trusted overlays for input
Transaction& setTrustedOverlay(const sp<SurfaceControl>& sc, bool isTrustedOverlay);
+ Transaction& setTrustedOverlay(const sp<SurfaceControl>& sc,
+ gui::TrustedOverlay trustedOverlay);
// Queues up transactions using this token in SurfaceFlinger. By default, all transactions
// from a client are placed on the same queue. This can be used to prevent multiple
@@ -824,6 +826,8 @@
nullptr);
status_t removeWindowInfosListener(const sp<gui::WindowInfosListener>& windowInfosListener);
+ static void notifyShutdown();
+
protected:
ReleaseCallbackThread mReleaseCallbackThread;
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 6c6a849..43cd0f8 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -985,6 +985,8 @@
return binder::Status::ok();
}
+ binder::Status notifyShutdown() override { return binder::Status::ok(); }
+
protected:
IBinder* onAsBinder() override { return nullptr; }
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 4123ffc..d782f42 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -81,10 +81,6 @@
visibility: ["//frameworks/native/services/inputflinger"],
wrapper_src: "InputWrapper.hpp",
- include_dirs: [
- "frameworks/native/include",
- ],
-
source_stem: "bindings",
bindgen_flags: [
diff --git a/libs/input/InputConsumer.cpp b/libs/input/InputConsumer.cpp
index abc0392..fcf490d 100644
--- a/libs/input/InputConsumer.cpp
+++ b/libs/input/InputConsumer.cpp
@@ -181,7 +181,8 @@
}
bool shouldResampleTool(ToolType toolType) {
- return toolType == ToolType::FINGER || toolType == ToolType::UNKNOWN;
+ return toolType == ToolType::FINGER || toolType == ToolType::MOUSE ||
+ toolType == ToolType::STYLUS || toolType == ToolType::UNKNOWN;
}
} // namespace
@@ -592,6 +593,11 @@
ALOGD_IF(debugResampling(), "Not resampled, missing id %d", id);
return;
}
+ if (!shouldResampleTool(event->getToolType(i))) {
+ ALOGD_IF(debugResampling(),
+ "Not resampled, containing unsupported tool type at pointer %d", id);
+ return;
+ }
}
// Find the data to use for resampling.
@@ -639,10 +645,18 @@
}
if (current->eventTime == sampleTime) {
- // Prevents having 2 events with identical times and coordinates.
+ ALOGD_IF(debugResampling(), "Not resampled, 2 events with identical times.");
return;
}
+ for (size_t i = 0; i < pointerCount; i++) {
+ uint32_t id = event->getPointerId(i);
+ if (!other->idBits.hasBit(id)) {
+ ALOGD_IF(debugResampling(), "Not resampled, the other doesn't have pointer id %d.", id);
+ return;
+ }
+ }
+
// Resample touch coordinates.
History oldLastResample;
oldLastResample.initializeFrom(touchState.lastResample);
@@ -670,22 +684,16 @@
const PointerCoords& currentCoords = current->getPointerById(id);
resampledCoords = currentCoords;
resampledCoords.isResampled = true;
- if (other->idBits.hasBit(id) && shouldResampleTool(event->getToolType(i))) {
- const PointerCoords& otherCoords = other->getPointerById(id);
- resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_X,
- lerp(currentCoords.getX(), otherCoords.getX(), alpha));
- resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_Y,
- lerp(currentCoords.getY(), otherCoords.getY(), alpha));
- ALOGD_IF(debugResampling(),
- "[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f), "
- "other (%0.3f, %0.3f), alpha %0.3f",
- id, resampledCoords.getX(), resampledCoords.getY(), currentCoords.getX(),
- currentCoords.getY(), otherCoords.getX(), otherCoords.getY(), alpha);
- } else {
- ALOGD_IF(debugResampling(), "[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f)", id,
- resampledCoords.getX(), resampledCoords.getY(), currentCoords.getX(),
- currentCoords.getY());
- }
+ const PointerCoords& otherCoords = other->getPointerById(id);
+ resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_X,
+ lerp(currentCoords.getX(), otherCoords.getX(), alpha));
+ resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_Y,
+ lerp(currentCoords.getY(), otherCoords.getY(), alpha));
+ ALOGD_IF(debugResampling(),
+ "[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f), "
+ "other (%0.3f, %0.3f), alpha %0.3f",
+ id, resampledCoords.getX(), resampledCoords.getY(), currentCoords.getX(),
+ currentCoords.getY(), otherCoords.getX(), otherCoords.getY(), alpha);
}
event->addSample(sampleTime, touchState.lastResample.pointers);
diff --git a/libs/input/tests/TouchResampling_test.cpp b/libs/input/tests/TouchResampling_test.cpp
index 2dc9fdb..8d8b530 100644
--- a/libs/input/tests/TouchResampling_test.cpp
+++ b/libs/input/tests/TouchResampling_test.cpp
@@ -297,10 +297,9 @@
}
/**
- * Stylus pointer coordinates are not resampled, but an event is still generated for the batch with
- * a resampled timestamp and should be marked as such.
+ * Stylus pointer coordinates are resampled.
*/
-TEST_F(TouchResamplingTest, StylusCoordinatesNotResampledFor) {
+TEST_F(TouchResamplingTest, StylusEventIsResampled) {
std::chrono::nanoseconds frameTime;
std::vector<InputEventEntry> entries, expectedEntries;
@@ -330,15 +329,91 @@
// id x y
{10ms, {{0, 20, 30, .toolType = ToolType::STYLUS}}, AMOTION_EVENT_ACTION_MOVE},
{20ms, {{0, 30, 30, .toolType = ToolType::STYLUS}}, AMOTION_EVENT_ACTION_MOVE},
- // A resampled event is generated, but the stylus coordinates are not resampled.
{25ms,
- {{0, 30, 30, .toolType = ToolType::STYLUS, .isResampled = true}},
+ {{0, 35, 30, .toolType = ToolType::STYLUS, .isResampled = true}},
AMOTION_EVENT_ACTION_MOVE},
};
consumeInputEventEntries(expectedEntries, frameTime);
}
/**
+ * Mouse pointer coordinates are resampled.
+ */
+TEST_F(TouchResamplingTest, MouseEventIsResampled) {
+ std::chrono::nanoseconds frameTime;
+ std::vector<InputEventEntry> entries, expectedEntries;
+
+ // Initial ACTION_DOWN should be separate, because the first consume event will only return
+ // InputEvent with a single action.
+ entries = {
+ // id x y
+ {0ms, {{0, 10, 20, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_DOWN},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 5ms;
+ expectedEntries = {
+ // id x y
+ {0ms, {{0, 10, 20, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_DOWN},
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+
+ // Two ACTION_MOVE events 10 ms apart that move in X direction and stay still in Y
+ entries = {
+ // id x y
+ {10ms, {{0, 20, 30, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_MOVE},
+ {20ms, {{0, 30, 30, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_MOVE},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 35ms;
+ expectedEntries = {
+ // id x y
+ {10ms, {{0, 20, 30, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_MOVE},
+ {20ms, {{0, 30, 30, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_MOVE},
+ {25ms,
+ {{0, 35, 30, .toolType = ToolType::MOUSE, .isResampled = true}},
+ AMOTION_EVENT_ACTION_MOVE},
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+}
+
+/**
+ * Motion events with palm tool type are not resampled.
+ */
+TEST_F(TouchResamplingTest, PalmEventIsNotResampled) {
+ std::chrono::nanoseconds frameTime;
+ std::vector<InputEventEntry> entries, expectedEntries;
+
+ // Initial ACTION_DOWN should be separate, because the first consume event will only return
+ // InputEvent with a single action.
+ entries = {
+ // id x y
+ {0ms, {{0, 10, 20, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_DOWN},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 5ms;
+ expectedEntries = {
+ // id x y
+ {0ms, {{0, 10, 20, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_DOWN},
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+
+ // Two ACTION_MOVE events 10 ms apart that move in X direction and stay still in Y
+ entries = {
+ // id x y
+ {10ms, {{0, 20, 30, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_MOVE},
+ {20ms, {{0, 30, 30, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_MOVE},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 35ms;
+ expectedEntries = {
+ // id x y
+ {10ms, {{0, 20, 30, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_MOVE},
+ {20ms, {{0, 30, 30, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_MOVE},
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+}
+
+/**
* Event should not be resampled when sample time is equal to event time.
*/
TEST_F(TouchResamplingTest, SampleTimeEqualsEventTime) {
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index c003111..4a04467 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -50,6 +50,7 @@
"libshaders",
"libtonemap",
"libsurfaceflinger_common",
+ "libsurfaceflingerflags",
],
local_include_dirs: ["include"],
export_include_dirs: ["include"],
@@ -102,6 +103,7 @@
"skia/filters/GaussianBlurFilter.cpp",
"skia/filters/KawaseBlurFilter.cpp",
"skia/filters/LinearEffect.cpp",
+ "skia/filters/MouriMap.cpp",
"skia/filters/StretchShaderFactory.cpp",
],
}
diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp
index 1c60563..bc3976d 100644
--- a/libs/renderengine/RenderEngine.cpp
+++ b/libs/renderengine/RenderEngine.cpp
@@ -22,24 +22,49 @@
#include "skia/SkiaGLRenderEngine.h"
#include "threaded/RenderEngineThreaded.h"
+#include <com_android_graphics_surfaceflinger_flags.h>
#include <cutils/properties.h>
#include <log/log.h>
+// TODO: b/341728634 - Clean up conditional compilation.
+#if COM_ANDROID_GRAPHICS_SURFACEFLINGER_FLAGS(GRAPHITE_RENDERENGINE) || \
+ COM_ANDROID_GRAPHICS_SURFACEFLINGER_FLAGS(FORCE_COMPILE_GRAPHITE_RENDERENGINE)
+#define COMPILE_GRAPHITE_RENDERENGINE 1
+#else
+#define COMPILE_GRAPHITE_RENDERENGINE 0
+#endif
+
namespace android {
namespace renderengine {
std::unique_ptr<RenderEngine> RenderEngine::create(const RenderEngineCreationArgs& args) {
threaded::CreateInstanceFactory createInstanceFactory;
+// TODO: b/341728634 - Clean up conditional compilation.
+#if COMPILE_GRAPHITE_RENDERENGINE
+ const RenderEngine::SkiaBackend actualSkiaBackend = args.skiaBackend;
+#else
+ if (args.skiaBackend == RenderEngine::SkiaBackend::GRAPHITE) {
+ ALOGE("RenderEngine with Graphite Skia backend was requested, but Graphite was not "
+ "included in the build. Falling back to Ganesh (%s)",
+ args.graphicsApi == RenderEngine::GraphicsApi::GL ? "GL" : "Vulkan");
+ }
+ const RenderEngine::SkiaBackend actualSkiaBackend = RenderEngine::SkiaBackend::GANESH;
+#endif
+
ALOGD("%sRenderEngine with %s Backend (%s)", args.threaded == Threaded::YES ? "Threaded " : "",
args.graphicsApi == GraphicsApi::GL ? "SkiaGL" : "SkiaVK",
- args.skiaBackend == SkiaBackend::GANESH ? "Ganesh" : "Graphite");
+ actualSkiaBackend == SkiaBackend::GANESH ? "Ganesh" : "Graphite");
- if (args.skiaBackend == SkiaBackend::GRAPHITE) {
+// TODO: b/341728634 - Clean up conditional compilation.
+#if COMPILE_GRAPHITE_RENDERENGINE
+ if (actualSkiaBackend == SkiaBackend::GRAPHITE) {
createInstanceFactory = [args]() {
return android::renderengine::skia::GraphiteVkRenderEngine::create(args);
};
- } else { // GANESH
+ } else
+#endif
+ { // GANESH
if (args.graphicsApi == GraphicsApi::VK) {
createInstanceFactory = [args]() {
return android::renderengine::skia::GaneshVkRenderEngine::create(args);
diff --git a/libs/renderengine/include/renderengine/DisplaySettings.h b/libs/renderengine/include/renderengine/DisplaySettings.h
index deb6253..b640983 100644
--- a/libs/renderengine/include/renderengine/DisplaySettings.h
+++ b/libs/renderengine/include/renderengine/DisplaySettings.h
@@ -86,6 +86,22 @@
// Configures the rendering intent of the output display. This is used for tonemapping.
aidl::android::hardware::graphics::composer3::RenderIntent renderIntent =
aidl::android::hardware::graphics::composer3::RenderIntent::TONE_MAP_COLORIMETRIC;
+
+ // Tonemapping strategy to use for each layer. This is only used for tonemapping HDR source
+ // content
+ enum class TonemapStrategy {
+ // Use a tonemapper defined by libtonemap. This may be OEM-defined as of Android 13, aka
+ // undefined.
+ // This is typically a global tonemapper, designed to match what is on screen.
+ Libtonemap,
+ // Use a local tonemapper. Because local tonemapping uses large intermediate allocations,
+ // this
+ // method is primarily recommended for infrequent rendering that does not need to exactly
+ // match
+ // pixels that are on-screen.
+ Local,
+ };
+ TonemapStrategy tonemapStrategy = TonemapStrategy::Libtonemap;
};
static inline bool operator==(const DisplaySettings& lhs, const DisplaySettings& rhs) {
diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp
index d344164..e62640e 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaRenderEngine.cpp
@@ -79,6 +79,7 @@
#include "filters/GaussianBlurFilter.h"
#include "filters/KawaseBlurFilter.h"
#include "filters/LinearEffect.h"
+#include "filters/MouriMap.h"
#include "log/log_main.h"
#include "skia/compat/SkiaBackendTexture.h"
#include "skia/debug/SkiaCapture.h"
@@ -509,9 +510,9 @@
// Determine later on if we need to leverage the stertch shader within
// surface flinger
const auto& stretchEffect = parameters.layer.stretchEffect;
+ const auto& targetBuffer = parameters.layer.source.buffer.buffer;
auto shader = parameters.shader;
if (stretchEffect.hasEffect()) {
- const auto targetBuffer = parameters.layer.source.buffer.buffer;
const auto graphicBuffer = targetBuffer ? targetBuffer->getBuffer() : nullptr;
if (graphicBuffer && parameters.shader) {
shader = mStretchShaderFactory.createSkShader(shader, stretchEffect);
@@ -519,6 +520,24 @@
}
if (parameters.requiresLinearEffect) {
+ const auto format = targetBuffer != nullptr
+ ? std::optional<ui::PixelFormat>(
+ static_cast<ui::PixelFormat>(targetBuffer->getPixelFormat()))
+ : std::nullopt;
+
+ if (parameters.display.tonemapStrategy == DisplaySettings::TonemapStrategy::Local) {
+ // TODO: Handle color matrix transforms in linear space.
+ SkImage* image = parameters.shader->isAImage((SkMatrix*)nullptr, (SkTileMode*)nullptr);
+ if (image) {
+ static MouriMap kMapper;
+ const float ratio = getHdrRenderType(parameters.layer.sourceDataspace, format) ==
+ HdrRenderType::GENERIC_HDR
+ ? 1.0f
+ : parameters.layerDimmingRatio;
+ return kMapper.mouriMap(getActiveContext(), parameters.shader, ratio);
+ }
+ }
+
auto effect =
shaders::LinearEffect{.inputDataspace = parameters.layer.sourceDataspace,
.outputDataspace = parameters.outputDataSpace,
@@ -712,8 +731,7 @@
[&](const auto& l) { return l.whitePointNits; });
// ...and compute the dimming ratio if dimming is requested
- const float displayDimmingRatio = display.targetLuminanceNits > 0.f &&
- maxLayerWhitePoint > 0.f && display.targetLuminanceNits > maxLayerWhitePoint
+ const float displayDimmingRatio = display.targetLuminanceNits > 0.f && maxLayerWhitePoint > 0.f
? maxLayerWhitePoint / display.targetLuminanceNits
: 1.f;
diff --git a/libs/renderengine/skia/VulkanInterface.cpp b/libs/renderengine/skia/VulkanInterface.cpp
index fc16c56..5e756b0 100644
--- a/libs/renderengine/skia/VulkanInterface.cpp
+++ b/libs/renderengine/skia/VulkanInterface.cpp
@@ -197,7 +197,9 @@
LOG_ALWAYS_FATAL("%s", crashMsg.str().c_str());
};
-static GrVkGetProc sGetProc = [](const char* proc_name, VkInstance instance, VkDevice device) {
+static skgpu::VulkanGetProc sGetProc = [](const char* proc_name,
+ VkInstance instance,
+ VkDevice device) {
if (device != VK_NULL_HANDLE) {
return vkGetDeviceProcAddr(device, proc_name);
}
@@ -604,7 +606,7 @@
mQueue = VK_NULL_HANDLE; // Implicitly destroyed by destroying mDevice.
mQueueIndex = 0;
mApiVersion = 0;
- mGrExtensions = GrVkExtensions();
+ mGrExtensions = skgpu::VulkanExtensions();
mGrGetProc = nullptr;
mIsProtected = false;
mIsRealtimePriority = false;
diff --git a/libs/renderengine/skia/VulkanInterface.h b/libs/renderengine/skia/VulkanInterface.h
index af0489a..f20b002 100644
--- a/libs/renderengine/skia/VulkanInterface.h
+++ b/libs/renderengine/skia/VulkanInterface.h
@@ -17,7 +17,8 @@
#pragma once
#include <include/gpu/vk/GrVkBackendContext.h>
-#include <include/gpu/vk/GrVkExtensions.h>
+#include <include/gpu/vk/VulkanExtensions.h>
+#include <include/gpu/vk/VulkanTypes.h>
#include <vulkan/vulkan.h>
@@ -85,12 +86,12 @@
VkQueue mQueue = VK_NULL_HANDLE;
int mQueueIndex = 0;
uint32_t mApiVersion = 0;
- GrVkExtensions mGrExtensions;
+ skgpu::VulkanExtensions mGrExtensions;
VkPhysicalDeviceFeatures2* mPhysicalDeviceFeatures2 = nullptr;
VkPhysicalDeviceSamplerYcbcrConversionFeatures* mSamplerYcbcrConversionFeatures = nullptr;
VkPhysicalDeviceProtectedMemoryFeatures* mProtectedMemoryFeatures = nullptr;
VkPhysicalDeviceFaultFeaturesEXT* mDeviceFaultFeatures = nullptr;
- GrVkGetProc mGrGetProc = nullptr;
+ skgpu::VulkanGetProc mGrGetProc = nullptr;
bool mIsProtected = false;
bool mIsRealtimePriority = false;
diff --git a/libs/renderengine/skia/filters/MouriMap.cpp b/libs/renderengine/skia/filters/MouriMap.cpp
new file mode 100644
index 0000000..7d8b8a5
--- /dev/null
+++ b/libs/renderengine/skia/filters/MouriMap.cpp
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2024 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 "MouriMap.h"
+#include <SkCanvas.h>
+#include <SkColorType.h>
+#include <SkPaint.h>
+#include <SkTileMode.h>
+
+namespace android {
+namespace renderengine {
+namespace skia {
+namespace {
+sk_sp<SkRuntimeEffect> makeEffect(const SkString& sksl) {
+ auto [effect, error] = SkRuntimeEffect::MakeForShader(sksl);
+ LOG_ALWAYS_FATAL_IF(!effect, "RuntimeShader error: %s", error.c_str());
+ return effect;
+}
+const SkString kCrosstalkAndChunk16x16(R"(
+ uniform shader bitmap;
+ uniform float hdrSdrRatio;
+ vec4 main(vec2 xy) {
+ float maximum = 0.0;
+ for (int y = 0; y < 16; y++) {
+ for (int x = 0; x < 16; x++) {
+ float3 linear = toLinearSrgb(bitmap.eval(xy * 16 + vec2(x, y)).rgb) * hdrSdrRatio;
+ float maxRGB = max(linear.r, max(linear.g, linear.b));
+ maximum = max(maximum, log2(max(maxRGB, 1.0)));
+ }
+ }
+ return float4(float3(maximum), 1.0);
+ }
+)");
+const SkString kChunk8x8(R"(
+ uniform shader bitmap;
+ vec4 main(vec2 xy) {
+ float maximum = 0.0;
+ for (int y = 0; y < 8; y++) {
+ for (int x = 0; x < 8; x++) {
+ maximum = max(maximum, bitmap.eval(xy * 8 + vec2(x, y)).r);
+ }
+ }
+ return float4(float3(maximum), 1.0);
+ }
+)");
+const SkString kBlur(R"(
+ uniform shader bitmap;
+ vec4 main(vec2 xy) {
+ float C[5];
+ C[0] = 1.0 / 16.0;
+ C[1] = 4.0 / 16.0;
+ C[2] = 6.0 / 16.0;
+ C[3] = 4.0 / 16.0;
+ C[4] = 1.0 / 16.0;
+ float result = 0.0;
+ for (int y = -2; y <= 2; y++) {
+ for (int x = -2; x <= 2; x++) {
+ result += C[y + 2] * C[x + 2] * bitmap.eval(xy + vec2(x, y)).r;
+ }
+ }
+ return float4(float3(exp2(result)), 1.0);
+ }
+)");
+const SkString kTonemap(R"(
+ uniform shader image;
+ uniform shader lux;
+ uniform float scaleFactor;
+ uniform float hdrSdrRatio;
+ vec4 main(vec2 xy) {
+ float localMax = lux.eval(xy * scaleFactor).r;
+ float4 rgba = image.eval(xy);
+ float3 linear = toLinearSrgb(rgba.rgb) * hdrSdrRatio;
+
+ if (localMax <= 1.0) {
+ return float4(fromLinearSrgb(linear), 1.0);
+ }
+
+ float maxRGB = max(linear.r, max(linear.g, linear.b));
+ localMax = max(localMax, maxRGB);
+ float gain = (1 + maxRGB / (localMax * localMax)) / (1 + maxRGB);
+ return float4(fromLinearSrgb(linear * gain), 1.0);
+ }
+)");
+
+// Draws the given runtime shader on a GPU surface and returns the result as an SkImage.
+sk_sp<SkImage> makeImage(SkSurface* surface, const SkRuntimeShaderBuilder& builder) {
+ sk_sp<SkShader> shader = builder.makeShader(nullptr);
+ LOG_ALWAYS_FATAL_IF(!shader, "%s, Failed to make shader!", __func__);
+ SkPaint paint;
+ paint.setShader(std::move(shader));
+ paint.setBlendMode(SkBlendMode::kSrc);
+ surface->getCanvas()->drawPaint(paint);
+ return surface->makeImageSnapshot();
+}
+
+} // namespace
+
+MouriMap::MouriMap()
+ : mCrosstalkAndChunk16x16(makeEffect(kCrosstalkAndChunk16x16)),
+ mChunk8x8(makeEffect(kChunk8x8)),
+ mBlur(makeEffect(kBlur)),
+ mTonemap(makeEffect(kTonemap)) {}
+
+sk_sp<SkShader> MouriMap::mouriMap(SkiaGpuContext* context, sk_sp<SkShader> input,
+ float hdrSdrRatio) {
+ auto downchunked = downchunk(context, input, hdrSdrRatio);
+ auto localLux = blur(context, downchunked.get());
+ return tonemap(input, localLux.get(), hdrSdrRatio);
+}
+
+sk_sp<SkImage> MouriMap::downchunk(SkiaGpuContext* context, sk_sp<SkShader> input,
+ float hdrSdrRatio) const {
+ SkMatrix matrix;
+ SkImage* image = input->isAImage(&matrix, (SkTileMode*)nullptr);
+ SkRuntimeShaderBuilder crosstalkAndChunk16x16Builder(mCrosstalkAndChunk16x16);
+ crosstalkAndChunk16x16Builder.child("bitmap") = input;
+ crosstalkAndChunk16x16Builder.uniform("hdrSdrRatio") = hdrSdrRatio;
+ // TODO: fp16 might be overkill. Most practical surfaces use 8-bit RGB for HDR UI and 10-bit YUV
+ // for HDR video. These downsample operations compute log2(max(linear RGB, 1.0)). So we don't
+ // care about LDR precision since they all resolve to LDR-max. For appropriately mastered HDR
+ // content that follows BT. 2408, 25% of the bit range for HLG and 42% of the bit range for PQ
+ // are reserved for HDR. This means that we can fit the entire HDR range for 10-bit HLG inside
+ // of 8 bits. We can also fit about half of the range for PQ, but most content does not fill the
+ // entire 10k nit range for PQ. Furthermore, we blur all of this later on anyways, so we might
+ // not need to be so precise. So, it's possible that we could use A8 or R8 instead. If we want
+ // to be really conservative we can try to use R16 or even RGBA1010102 to fake an R10 surface,
+ // which would cut write bandwidth significantly.
+ static constexpr auto kFirstDownscaleAmount = 16;
+ sk_sp<SkSurface> firstDownsampledSurface = context->createRenderTarget(
+ image->imageInfo()
+ .makeWH(std::max(1, image->width() / kFirstDownscaleAmount),
+ std::max(1, image->height() / kFirstDownscaleAmount))
+ .makeColorType(kRGBA_F16_SkColorType));
+ LOG_ALWAYS_FATAL_IF(!firstDownsampledSurface, "%s: Failed to create surface!", __func__);
+ auto firstDownsampledImage =
+ makeImage(firstDownsampledSurface.get(), crosstalkAndChunk16x16Builder);
+ SkRuntimeShaderBuilder chunk8x8Builder(mChunk8x8);
+ chunk8x8Builder.child("bitmap") =
+ firstDownsampledImage->makeRawShader(SkTileMode::kClamp, SkTileMode::kClamp,
+ SkSamplingOptions());
+ static constexpr auto kSecondDownscaleAmount = 8;
+ sk_sp<SkSurface> secondDownsampledSurface = context->createRenderTarget(
+ firstDownsampledImage->imageInfo()
+ .makeWH(std::max(1, firstDownsampledImage->width() / kSecondDownscaleAmount),
+ std::max(1, firstDownsampledImage->height() / kSecondDownscaleAmount)));
+ LOG_ALWAYS_FATAL_IF(!secondDownsampledSurface, "%s: Failed to create surface!", __func__);
+ return makeImage(secondDownsampledSurface.get(), chunk8x8Builder);
+}
+sk_sp<SkImage> MouriMap::blur(SkiaGpuContext* context, SkImage* input) const {
+ SkRuntimeShaderBuilder blurBuilder(mBlur);
+ blurBuilder.child("bitmap") =
+ input->makeRawShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions());
+ sk_sp<SkSurface> blurSurface = context->createRenderTarget(input->imageInfo());
+ LOG_ALWAYS_FATAL_IF(!blurSurface, "%s: Failed to create surface!", __func__);
+ return makeImage(blurSurface.get(), blurBuilder);
+}
+sk_sp<SkShader> MouriMap::tonemap(sk_sp<SkShader> input, SkImage* localLux,
+ float hdrSdrRatio) const {
+ static constexpr float kScaleFactor = 1.0f / 128.0f;
+ SkRuntimeShaderBuilder tonemapBuilder(mTonemap);
+ tonemapBuilder.child("image") = input;
+ tonemapBuilder.child("lux") =
+ localLux->makeRawShader(SkTileMode::kClamp, SkTileMode::kClamp,
+ SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone));
+ tonemapBuilder.uniform("scaleFactor") = kScaleFactor;
+ tonemapBuilder.uniform("hdrSdrRatio") = hdrSdrRatio;
+ return tonemapBuilder.makeShader();
+}
+} // namespace skia
+} // namespace renderengine
+} // namespace android
\ No newline at end of file
diff --git a/libs/renderengine/skia/filters/MouriMap.h b/libs/renderengine/skia/filters/MouriMap.h
new file mode 100644
index 0000000..3c0df8a
--- /dev/null
+++ b/libs/renderengine/skia/filters/MouriMap.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2024 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 <SkImage.h>
+#include <SkRuntimeEffect.h>
+#include <SkShader.h>
+#include "../compat/SkiaGpuContext.h"
+namespace android {
+namespace renderengine {
+namespace skia {
+/**
+ * MouriMap is a fast, albeit not realtime, tonemapping algorithm optimized for near-exact
+ * preservation of SDR (or, equivalently, LDR) regions, while trying to do an acceptable job of
+ * preserving HDR detail.
+ *
+ * MouriMap is a local tonemapping algorithm, meaning that nearby pixels are taken into
+ * consideration when choosing a tonemapping curve.
+ *
+ * The algorithm conceptually is as follows:
+ * 1. Partition the image into 128x128 chunks, computing the log2(maximum luminance) in each chunk
+ *. a. Maximum luminance is computed as max(R, G, B), where the R, G, B values are in linear
+ *. luminance on a scale defined by the destination color gamut. Max(R, G, B) has been found
+ *. to minimize difference in hue while restricting to typical LDR color volumes. See: Burke,
+ *. Adam & Smith, Michael & Zink, Michael. 2020. Color Volume and Hue-preservation in HDR
+ *. Tone Mapping. SMPTE Motion Imaging Journal.
+ *. b. Each computed luminance is lower-bounded by 1.0 in Skia's color
+ *. management, or 203 nits.
+ * 2. Blur the resulting chunks using a 5x5 gaussian kernel, to smooth out the local luminance map.
+ * 3. Now, for each pixel in the original image:
+ * a. Upsample from the blurred chunks of luminance computed in (2). Call this luminance value
+ *. L: an estimate of the maximum luminance of surrounding pixels.
+ *. b. If the luminance is less than 1.0 (203 nits), then do not modify the pixel value of the
+ *. original image.
+ *. c. Otherwise,
+ *. parameterize a tone-mapping curve using a method described by Chrome:
+ *. https://docs.google.com/document/d/17T2ek1i2R7tXdfHCnM-i5n6__RoYe0JyMfKmTEjoGR8/.
+ *. i. Compute a gain G = (1 + max(linear R, linear G, linear B) / (L * L))
+ *. / (1 + max(linear R, linear G, linear B)). Note the similarity with the 1D curve
+ *. described by Erik Reinhard, Michael Stark, Peter Shirley, and James Ferwerda. 2002.
+ *. Photographic tone reproduction for digital images. ACM Trans. Graph.
+ *. ii. Multiply G by the linear source colors to compute the final colors.
+ *
+ * Because it is a multi-renderpass algorithm requiring multiple off-screen textures, MouriMap is
+ * typically not suitable to be ran "frequently", at high refresh rates (e.g., 120hz). However,
+ * MouriMap is sufficiently fast enough for infrequent composition where preserving SDR detail is
+ * most important, such as for screenshots.
+ */
+class MouriMap {
+public:
+ MouriMap();
+ // Apply the MouriMap tonemmaping operator to the input.
+ // The HDR/SDR ratio describes the luminace range of the input. 1.0 means SDR. Anything larger
+ // then 1.0 means that there is headroom above the SDR region.
+ sk_sp<SkShader> mouriMap(SkiaGpuContext* context, sk_sp<SkShader> input, float hdrSdrRatio);
+
+private:
+ sk_sp<SkImage> downchunk(SkiaGpuContext* context, sk_sp<SkShader> input,
+ float hdrSdrRatio) const;
+ sk_sp<SkImage> blur(SkiaGpuContext* context, SkImage* input) const;
+ sk_sp<SkShader> tonemap(sk_sp<SkShader> input, SkImage* localLux, float hdrSdrRatio) const;
+ const sk_sp<SkRuntimeEffect> mCrosstalkAndChunk16x16;
+ const sk_sp<SkRuntimeEffect> mChunk8x8;
+ const sk_sp<SkRuntimeEffect> mBlur;
+ const sk_sp<SkRuntimeEffect> mTonemap;
+};
+} // namespace skia
+} // namespace renderengine
+} // namespace android
\ No newline at end of file
diff --git a/libs/renderengine/tests/Android.bp b/libs/renderengine/tests/Android.bp
index 0eea187..0783714 100644
--- a/libs/renderengine/tests/Android.bp
+++ b/libs/renderengine/tests/Android.bp
@@ -46,6 +46,7 @@
"libshaders",
"libtonemap",
"libsurfaceflinger_common",
+ "libsurfaceflingerflags",
],
header_libs: [
"libtonemap_headers",
@@ -64,5 +65,6 @@
"libui",
"libutils",
"server_configurable_flags",
+ "libaconfig_storage_read_api_cc",
],
}
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index 4dcaff9..a8a9823 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -22,6 +22,7 @@
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wextra"
+#include <com_android_graphics_surfaceflinger_flags.h>
#include <cutils/properties.h>
#include <gtest/gtest.h>
#include <renderengine/ExternalTexture.h>
@@ -41,6 +42,14 @@
#include "../skia/SkiaVkRenderEngine.h"
#include "../threaded/RenderEngineThreaded.h"
+// TODO: b/341728634 - Clean up conditional compilation.
+#if COM_ANDROID_GRAPHICS_SURFACEFLINGER_FLAGS(GRAPHITE_RENDERENGINE) || \
+ COM_ANDROID_GRAPHICS_SURFACEFLINGER_FLAGS(FORCE_COMPILE_GRAPHITE_RENDERENGINE)
+#define COMPILE_GRAPHITE_RENDERENGINE 1
+#else
+#define COMPILE_GRAPHITE_RENDERENGINE 0
+#endif
+
constexpr int DEFAULT_DISPLAY_WIDTH = 128;
constexpr int DEFAULT_DISPLAY_HEIGHT = 256;
constexpr int DEFAULT_DISPLAY_OFFSET = 64;
@@ -152,6 +161,8 @@
}
};
+// TODO: b/341728634 - Clean up conditional compilation.
+#if COMPILE_GRAPHITE_RENDERENGINE
class GraphiteVkRenderEngineFactory : public RenderEngineFactory {
public:
std::string name() override { return "GraphiteVkRenderEngineFactory"; }
@@ -164,6 +175,7 @@
return renderengine::RenderEngine::SkiaBackend::GRAPHITE;
}
};
+#endif
class RenderEngineTest : public ::testing::TestWithParam<std::shared_ptr<RenderEngineFactory>> {
public:
@@ -1497,10 +1509,15 @@
expectBufferColor(Rect(kGreyLevels, 1), generator, 2);
}
+// TODO: b/341728634 - Clean up conditional compilation.
INSTANTIATE_TEST_SUITE_P(PerRenderEngineType, RenderEngineTest,
testing::Values(std::make_shared<SkiaGLESRenderEngineFactory>(),
- std::make_shared<GaneshVkRenderEngineFactory>(),
- std::make_shared<GraphiteVkRenderEngineFactory>()));
+ std::make_shared<GaneshVkRenderEngineFactory>()
+#if COMPILE_GRAPHITE_RENDERENGINE
+ ,
+ std::make_shared<GraphiteVkRenderEngineFactory>()
+#endif
+ ));
TEST_P(RenderEngineTest, drawLayers_noLayersToDraw) {
if (!GetParam()->apiSupported()) {
diff --git a/libs/sensor/libsensor_flags.aconfig b/libs/sensor/libsensor_flags.aconfig
index c511f4a..cbf3055 100644
--- a/libs/sensor/libsensor_flags.aconfig
+++ b/libs/sensor/libsensor_flags.aconfig
@@ -8,3 +8,10 @@
bug: "322228259"
is_fixed_read_only: true
}
+
+flag {
+ name: "sensor_event_queue_report_sensor_usage_in_tracing"
+ namespace: "sensors"
+ description: "When this flag is enabled, sensor event queue will report sensor usage when system trace is enabled."
+ bug: "333132224"
+}
\ No newline at end of file
diff --git a/libs/ui/DisplayIdentification.cpp b/libs/ui/DisplayIdentification.cpp
index 0908ae8..e5af740 100644
--- a/libs/ui/DisplayIdentification.cpp
+++ b/libs/ui/DisplayIdentification.cpp
@@ -320,6 +320,11 @@
std::optional<DisplayIdentificationInfo> parseDisplayIdentificationData(
uint8_t port, const DisplayIdentificationData& data) {
+ if (data.empty()) {
+ ALOGI("Display identification data is empty.");
+ return {};
+ }
+
if (!isEdid(data)) {
ALOGE("Display identification data has unknown format.");
return {};
diff --git a/libs/ui/tests/DisplayId_test.cpp b/libs/ui/tests/DisplayId_test.cpp
index 1115804..ef686df 100644
--- a/libs/ui/tests/DisplayId_test.cpp
+++ b/libs/ui/tests/DisplayId_test.cpp
@@ -63,6 +63,18 @@
EXPECT_EQ(id, DisplayId::fromValue<GpuVirtualDisplayId>(id.value));
}
+TEST(DisplayIdTest, createVirtualIdFromGpuVirtualId) {
+ const VirtualDisplayId id(GpuVirtualDisplayId(42));
+ EXPECT_TRUE(VirtualDisplayId::tryCast(id));
+ EXPECT_TRUE(GpuVirtualDisplayId::tryCast(id));
+ EXPECT_FALSE(HalVirtualDisplayId::tryCast(id));
+ EXPECT_FALSE(PhysicalDisplayId::tryCast(id));
+ EXPECT_FALSE(HalDisplayId::tryCast(id));
+
+ const bool isGpuVirtualId = (id.value & VirtualDisplayId::FLAG_GPU);
+ EXPECT_EQ((id.isVirtual() && isGpuVirtualId), GpuVirtualDisplayId::tryCast(id).has_value());
+}
+
TEST(DisplayIdTest, createGpuVirtualIdFromUniqueId) {
static const std::string kUniqueId("virtual:ui:DisplayId_test");
const auto idOpt = GpuVirtualDisplayId::fromUniqueId(kUniqueId);
@@ -90,4 +102,16 @@
EXPECT_EQ(id, DisplayId::fromValue<HalVirtualDisplayId>(id.value));
}
+TEST(DisplayIdTest, createVirtualIdFromHalVirtualId) {
+ const VirtualDisplayId id(HalVirtualDisplayId(42));
+ EXPECT_TRUE(VirtualDisplayId::tryCast(id));
+ EXPECT_TRUE(HalVirtualDisplayId::tryCast(id));
+ EXPECT_FALSE(GpuVirtualDisplayId::tryCast(id));
+ EXPECT_FALSE(PhysicalDisplayId::tryCast(id));
+ EXPECT_TRUE(HalDisplayId::tryCast(id));
+
+ const bool isGpuVirtualId = (id.value & VirtualDisplayId::FLAG_GPU);
+ EXPECT_EQ((id.isVirtual() && !isGpuVirtualId), HalVirtualDisplayId::tryCast(id).has_value());
+}
+
} // namespace android::ui
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 1ada33e..5b5afd3 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -254,6 +254,7 @@
}
}
+ std::vector<std::string> extensionStrings;
{ // scope for lock
std::lock_guard<std::mutex> _l(lock);
@@ -315,16 +316,14 @@
}
mClientApiString = sClientApiString;
- mExtensionString = gBuiltinExtensionString;
-
// b/269060366 Conditionally enabled EGL_ANDROID_get_frame_timestamps extension if the
// device's present timestamps are reliable (which may not be the case on emulators).
if (cnx->angleLoaded) {
if (android::base::GetBoolProperty("service.sf.present_timestamp", false)) {
- mExtensionString.append("EGL_ANDROID_get_frame_timestamps ");
+ extensionStrings.push_back("EGL_ANDROID_get_frame_timestamps");
}
} else {
- mExtensionString.append("EGL_ANDROID_get_frame_timestamps ");
+ extensionStrings.push_back("EGL_ANDROID_get_frame_timestamps");
}
hasColorSpaceSupport = findExtension(disp.queryString.extensions, "EGL_KHR_gl_colorspace");
@@ -335,10 +334,12 @@
// Add wide-color extensions if device can support wide-color
if (wideColorBoardConfig && hasColorSpaceSupport) {
- mExtensionString.append(
- "EGL_EXT_gl_colorspace_scrgb EGL_EXT_gl_colorspace_scrgb_linear "
- "EGL_EXT_gl_colorspace_display_p3_linear EGL_EXT_gl_colorspace_display_p3 "
- "EGL_EXT_gl_colorspace_display_p3_passthrough ");
+ std::vector<std::string> wideColorExtensions =
+ {"EGL_EXT_gl_colorspace_scrgb", "EGL_EXT_gl_colorspace_scrgb_linear",
+ "EGL_EXT_gl_colorspace_display_p3_linear", "EGL_EXT_gl_colorspace_display_p3",
+ "EGL_EXT_gl_colorspace_display_p3_passthrough"};
+ extensionStrings.insert(extensionStrings.end(), wideColorExtensions.begin(),
+ wideColorExtensions.end());
}
bool hasHdrBoardConfig = android::sysprop::has_HDR_display(false);
@@ -348,9 +349,11 @@
// Typically that means there is an HDR capable display attached, but could be
// support for attaching an HDR display. In either case, advertise support for
// HDR color spaces.
- mExtensionString.append("EGL_EXT_gl_colorspace_bt2020_hlg "
- "EGL_EXT_gl_colorspace_bt2020_linear "
- "EGL_EXT_gl_colorspace_bt2020_pq ");
+ std::vector<std::string> hdrExtensions = {"EGL_EXT_gl_colorspace_bt2020_hlg",
+ "EGL_EXT_gl_colorspace_bt2020_linear",
+ "EGL_EXT_gl_colorspace_bt2020_pq"};
+ extensionStrings.insert(extensionStrings.end(), hdrExtensions.begin(),
+ hdrExtensions.end());
}
char const* start = gExtensionString;
@@ -361,7 +364,7 @@
// NOTE: we could avoid the copy if we had strnstr.
const std::string ext(start, len);
if (findExtension(disp.queryString.extensions, ext.c_str(), len)) {
- mExtensionString.append(ext + " ");
+ extensionStrings.push_back(ext);
}
// advance to the next extension name, skipping the space.
start += len;
@@ -388,6 +391,14 @@
refCond.notify_all();
}
+ auto mergeExtensionStrings = [](const std::vector<std::string>& strings) {
+ std::ostringstream combinedStringStream;
+ std::copy(strings.begin(), strings.end(),
+ std::ostream_iterator<std::string>(combinedStringStream, " "));
+ // gBuiltinExtensionString already has a trailing space so is added here
+ return gBuiltinExtensionString + combinedStringStream.str();
+ };
+ mExtensionString = mergeExtensionStrings(extensionStrings);
return EGL_TRUE;
}
diff --git a/opengl/tests/EGLTest/Android.bp b/opengl/tests/EGLTest/Android.bp
index d96a895..aebd3f2 100644
--- a/opengl/tests/EGLTest/Android.bp
+++ b/opengl/tests/EGLTest/Android.bp
@@ -37,6 +37,11 @@
"libSurfaceFlingerProp",
],
+ static_libs: [
+ "libgmock",
+ "libgtest",
+ ],
+
include_dirs: [
"frameworks/native/opengl/libs",
"frameworks/native/opengl/libs/EGL",
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index cbe4ef9..503d7df 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -15,6 +15,7 @@
*/
#include <gtest/gtest.h>
+#include <gmock/gmock.h>
#include <SurfaceFlingerProperties.h>
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
@@ -29,6 +30,8 @@
#include <gui/IGraphicBufferConsumer.h>
#include <gui/BufferQueue.h>
+#include "egl_display.h"
+
bool hasEglExtension(EGLDisplay dpy, const char* extensionName) {
const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
size_t cropExtLen = strlen(extensionName);
@@ -1011,4 +1014,57 @@
EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
}
+
+TEST_F(EGLTest, EGLCheckExtensionString) {
+ // check that the format of the extension string is correct
+
+ egl_display_t* display = egl_display_t::get(mEglDisplay);
+ ASSERT_NE(display, nullptr);
+
+ std::string extensionStrRegex = "((EGL_ANDROID_front_buffer_auto_refresh|"
+ "EGL_ANDROID_get_native_client_buffer|"
+ "EGL_ANDROID_presentation_time|"
+ "EGL_EXT_surface_CTA861_3_metadata|"
+ "EGL_EXT_surface_SMPTE2086_metadata|"
+ "EGL_KHR_get_all_proc_addresses|"
+ "EGL_KHR_swap_buffers_with_damage|"
+ "EGL_ANDROID_get_frame_timestamps|"
+ "EGL_EXT_gl_colorspace_scrgb|"
+ "EGL_EXT_gl_colorspace_scrgb_linear|"
+ "EGL_EXT_gl_colorspace_display_p3_linear|"
+ "EGL_EXT_gl_colorspace_display_p3|"
+ "EGL_EXT_gl_colorspace_display_p3_passthrough|"
+ "EGL_EXT_gl_colorspace_bt2020_hlg|"
+ "EGL_EXT_gl_colorspace_bt2020_linear|"
+ "EGL_EXT_gl_colorspace_bt2020_pq|"
+ "EGL_ANDROID_image_native_buffer|"
+ "EGL_ANDROID_native_fence_sync|"
+ "EGL_ANDROID_recordable|"
+ "EGL_EXT_create_context_robustness|"
+ "EGL_EXT_image_gl_colorspace|"
+ "EGL_EXT_pixel_format_float|"
+ "EGL_EXT_protected_content|"
+ "EGL_EXT_yuv_surface|"
+ "EGL_IMG_context_priority|"
+ "EGL_KHR_config_attribs|"
+ "EGL_KHR_create_context|"
+ "EGL_KHR_fence_sync|"
+ "EGL_KHR_gl_colorspace|"
+ "EGL_KHR_gl_renderbuffer_image|"
+ "EGL_KHR_gl_texture_2D_image|"
+ "EGL_KHR_gl_texture_3D_image|"
+ "EGL_KHR_gl_texture_cubemap_image|"
+ "EGL_KHR_image|"
+ "EGL_KHR_image_base|"
+ "EGL_KHR_mutable_render_buffer|"
+ "EGL_KHR_no_config_context|"
+ "EGL_KHR_partial_update|"
+ "EGL_KHR_surfaceless_context|"
+ "EGL_KHR_wait_sync|"
+ "EGL_EXT_buffer_age|"
+ "EGL_KHR_reusable_sync|"
+ "EGL_NV_context_priority_realtime) )+";
+ EXPECT_THAT(display->getExtensionString(), testing::MatchesRegex(extensionStrRegex));
+}
+
}
diff --git a/services/inputflinger/PointerChoreographer.cpp b/services/inputflinger/PointerChoreographer.cpp
index 8a1eed6..7d3a2df 100644
--- a/services/inputflinger/PointerChoreographer.cpp
+++ b/services/inputflinger/PointerChoreographer.cpp
@@ -30,10 +30,6 @@
namespace android {
-namespace input_flags = com::android::input::flags;
-static const bool HIDE_TOUCH_INDICATORS_FOR_SECURE_WINDOWS =
- input_flags::hide_pointer_indicators_for_secure_windows();
-
namespace {
bool isFromMouse(const NotifyMotionArgs& args) {
@@ -89,12 +85,48 @@
}
}
+// filters and returns a set of privacy sensitive displays that are currently visible.
+std::unordered_set<ui::LogicalDisplayId> getPrivacySensitiveDisplaysFromWindowInfos(
+ const std::vector<gui::WindowInfo>& windowInfos) {
+ std::unordered_set<ui::LogicalDisplayId> privacySensitiveDisplays;
+ for (const auto& windowInfo : windowInfos) {
+ if (!windowInfo.inputConfig.test(gui::WindowInfo::InputConfig::NOT_VISIBLE) &&
+ windowInfo.inputConfig.test(gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY)) {
+ privacySensitiveDisplays.insert(windowInfo.displayId);
+ }
+ }
+ return privacySensitiveDisplays;
+}
+
} // namespace
// --- PointerChoreographer ---
-PointerChoreographer::PointerChoreographer(InputListenerInterface& listener,
+PointerChoreographer::PointerChoreographer(InputListenerInterface& inputListener,
PointerChoreographerPolicyInterface& policy)
+ : PointerChoreographer(
+ inputListener, policy,
+ [](const sp<android::gui::WindowInfosListener>& listener) {
+ auto initialInfo = std::make_pair(std::vector<android::gui::WindowInfo>{},
+ std::vector<android::gui::DisplayInfo>{});
+#if defined(__ANDROID__)
+ SurfaceComposerClient::getDefault()->addWindowInfosListener(listener,
+ &initialInfo);
+#endif
+ return initialInfo.first;
+ },
+ [](const sp<android::gui::WindowInfosListener>& listener) {
+#if defined(__ANDROID__)
+ SurfaceComposerClient::getDefault()->removeWindowInfosListener(listener);
+#endif
+ }) {
+}
+
+PointerChoreographer::PointerChoreographer(
+ android::InputListenerInterface& listener,
+ android::PointerChoreographerPolicyInterface& policy,
+ const android::PointerChoreographer::WindowListenerRegisterConsumer& registerListener,
+ const android::PointerChoreographer::WindowListenerUnregisterConsumer& unregisterListener)
: mTouchControllerConstructor([this]() {
return mPolicy.createPointerController(
PointerControllerInterface::ControllerType::TOUCH);
@@ -104,7 +136,9 @@
mDefaultMouseDisplayId(ui::LogicalDisplayId::DEFAULT),
mNotifiedPointerDisplayId(ui::LogicalDisplayId::INVALID),
mShowTouchesEnabled(false),
- mStylusPointerIconEnabled(false) {}
+ mStylusPointerIconEnabled(false),
+ mRegisterListener(registerListener),
+ mUnregisterListener(unregisterListener) {}
PointerChoreographer::~PointerChoreographer() {
std::scoped_lock _l(mLock);
@@ -112,6 +146,7 @@
return;
}
mWindowInfoListener->onPointerChoreographerDestroyed();
+ mUnregisterListener(mWindowInfoListener);
}
void PointerChoreographer::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
@@ -246,10 +281,13 @@
}
// Use a mouse pointer controller for drawing tablets, or create one if it doesn't exist.
- auto [it, _] = mDrawingTabletPointersByDevice.try_emplace(args.deviceId,
- getMouseControllerConstructor(
- args.displayId));
- // TODO (b/325252005): Add handing for drawing tablets mouse pointer controller
+ auto [it, controllerAdded] =
+ mDrawingTabletPointersByDevice.try_emplace(args.deviceId,
+ getMouseControllerConstructor(
+ args.displayId));
+ if (controllerAdded) {
+ onControllerAddedOrRemovedLocked();
+ }
PointerControllerInterface& pc = *it->second;
@@ -290,7 +328,7 @@
auto [it, controllerAdded] =
mTouchPointersByDevice.try_emplace(args.deviceId, mTouchControllerConstructor);
if (controllerAdded) {
- onControllerAddedOrRemoved();
+ onControllerAddedOrRemovedLocked();
}
PointerControllerInterface& pc = *it->second;
@@ -326,10 +364,12 @@
}
// Get the stylus pointer controller for the device, or create one if it doesn't exist.
- auto [it, _] =
+ auto [it, controllerAdded] =
mStylusPointersByDevice.try_emplace(args.deviceId,
getStylusControllerConstructor(args.displayId));
- // TODO (b/325252005): Add handing for stylus pointer controller
+ if (controllerAdded) {
+ onControllerAddedOrRemovedLocked();
+ }
PointerControllerInterface& pc = *it->second;
@@ -369,30 +409,57 @@
mTouchPointersByDevice.erase(args.deviceId);
mStylusPointersByDevice.erase(args.deviceId);
mDrawingTabletPointersByDevice.erase(args.deviceId);
- onControllerAddedOrRemoved();
+ onControllerAddedOrRemovedLocked();
}
-void PointerChoreographer::onControllerAddedOrRemoved() {
- if (!HIDE_TOUCH_INDICATORS_FOR_SECURE_WINDOWS) {
+void PointerChoreographer::onControllerAddedOrRemovedLocked() {
+ if (!com::android::input::flags::hide_pointer_indicators_for_secure_windows()) {
return;
}
- bool requireListener = !mTouchPointersByDevice.empty();
- // TODO (b/325252005): Update for other types of pointer controllers
+ bool requireListener = !mTouchPointersByDevice.empty() || !mMousePointersByDisplay.empty() ||
+ !mDrawingTabletPointersByDevice.empty() || !mStylusPointersByDevice.empty();
if (requireListener && mWindowInfoListener == nullptr) {
mWindowInfoListener = sp<PointerChoreographerDisplayInfoListener>::make(this);
- auto initialInfo = std::make_pair(std::vector<android::gui::WindowInfo>{},
- std::vector<android::gui::DisplayInfo>{});
-#if defined(__ANDROID__)
- SurfaceComposerClient::getDefault()->addWindowInfosListener(mWindowInfoListener,
- &initialInfo);
-#endif
- onWindowInfosChangedLocked(initialInfo.first);
+ mWindowInfoListener->setInitialDisplayInfos(mRegisterListener(mWindowInfoListener));
+ onPrivacySensitiveDisplaysChangedLocked(mWindowInfoListener->getPrivacySensitiveDisplays());
} else if (!requireListener && mWindowInfoListener != nullptr) {
-#if defined(__ANDROID__)
- SurfaceComposerClient::getDefault()->removeWindowInfosListener(mWindowInfoListener);
-#endif
+ mUnregisterListener(mWindowInfoListener);
mWindowInfoListener = nullptr;
+ } else if (requireListener && mWindowInfoListener != nullptr) {
+ // controller may have been added to an existing privacy sensitive display, we need to
+ // update all controllers again
+ onPrivacySensitiveDisplaysChangedLocked(mWindowInfoListener->getPrivacySensitiveDisplays());
+ }
+}
+
+void PointerChoreographer::onPrivacySensitiveDisplaysChangedLocked(
+ const std::unordered_set<ui::LogicalDisplayId>& privacySensitiveDisplays) {
+ for (auto& [_, pc] : mTouchPointersByDevice) {
+ pc->clearSkipScreenshotFlags();
+ for (auto displayId : privacySensitiveDisplays) {
+ pc->setSkipScreenshotFlagForDisplay(displayId);
+ }
+ }
+
+ for (auto& [displayId, pc] : mMousePointersByDisplay) {
+ if (privacySensitiveDisplays.find(displayId) != privacySensitiveDisplays.end()) {
+ pc->setSkipScreenshotFlagForDisplay(displayId);
+ } else {
+ pc->clearSkipScreenshotFlags();
+ }
+ }
+
+ for (auto* pointerControllerByDevice :
+ {&mDrawingTabletPointersByDevice, &mStylusPointersByDevice}) {
+ for (auto& [_, pc] : *pointerControllerByDevice) {
+ auto displayId = pc->getDisplayId();
+ if (privacySensitiveDisplays.find(displayId) != privacySensitiveDisplays.end()) {
+ pc->setSkipScreenshotFlagForDisplay(displayId);
+ } else {
+ pc->clearSkipScreenshotFlags();
+ }
+ }
}
}
@@ -407,10 +474,10 @@
mNextListener.notify(args);
}
-void PointerChoreographer::onWindowInfosChanged(
- const std::vector<android::gui::WindowInfo>& windowInfos) {
+void PointerChoreographer::onPrivacySensitiveDisplaysChanged(
+ const std::unordered_set<ui::LogicalDisplayId>& privacySensitiveDisplays) {
std::scoped_lock _l(mLock);
- onWindowInfosChangedLocked(windowInfos);
+ onPrivacySensitiveDisplaysChangedLocked(privacySensitiveDisplays);
}
void PointerChoreographer::dump(std::string& dump) {
@@ -467,7 +534,7 @@
if (it == mMousePointersByDisplay.end()) {
it = mMousePointersByDisplay.emplace(displayId, getMouseControllerConstructor(displayId))
.first;
- // TODO (b/325252005): Add handing for mouse pointer controller
+ onControllerAddedOrRemovedLocked();
}
return {displayId, *it->second};
@@ -509,7 +576,9 @@
auto [mousePointerIt, isNewMousePointer] =
mMousePointersByDisplay.try_emplace(displayId,
getMouseControllerConstructor(displayId));
- // TODO (b/325252005): Add handing for mouse pointer controller
+ if (isNewMousePointer) {
+ onControllerAddedOrRemovedLocked();
+ }
mMouseDevices.emplace(info.getId());
if ((!isKnownMouse || isNewMousePointer) && canUnfadeOnDisplay(displayId)) {
@@ -549,7 +618,7 @@
mInputDeviceInfos.end();
});
- onControllerAddedOrRemoved();
+ onControllerAddedOrRemovedLocked();
// Check if we need to notify the policy if there's a change on the pointer display ID.
return calculatePointerDisplayChangeToNotify();
@@ -715,31 +784,6 @@
return false;
}
-void PointerChoreographer::onWindowInfosChangedLocked(
- const std::vector<android::gui::WindowInfo>& windowInfos) {
- // Mark all spot controllers secure on displays containing secure windows and
- // remove secure flag from others if required
- std::unordered_set<ui::LogicalDisplayId> privacySensitiveDisplays;
- std::unordered_set<ui::LogicalDisplayId> allDisplayIds;
- for (const auto& windowInfo : windowInfos) {
- allDisplayIds.insert(windowInfo.displayId);
- if (!windowInfo.inputConfig.test(gui::WindowInfo::InputConfig::NOT_VISIBLE) &&
- windowInfo.inputConfig.test(gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY)) {
- privacySensitiveDisplays.insert(windowInfo.displayId);
- }
- }
-
- for (auto& it : mTouchPointersByDevice) {
- auto& pc = it.second;
- for (ui::LogicalDisplayId displayId : allDisplayIds) {
- pc->setSkipScreenshot(displayId,
- privacySensitiveDisplays.find(displayId) !=
- privacySensitiveDisplays.end());
- }
- }
- // TODO (b/325252005): update skip screenshot flag for other types of pointer controllers
-}
-
void PointerChoreographer::setPointerIconVisibility(ui::LogicalDisplayId displayId, bool visible) {
std::scoped_lock lock(mLock);
if (visible) {
@@ -793,9 +837,27 @@
void PointerChoreographer::PointerChoreographerDisplayInfoListener::onWindowInfosChanged(
const gui::WindowInfosUpdate& windowInfosUpdate) {
std::scoped_lock _l(mListenerLock);
- if (mPointerChoreographer != nullptr) {
- mPointerChoreographer->onWindowInfosChanged(windowInfosUpdate.windowInfos);
+ if (mPointerChoreographer == nullptr) {
+ return;
}
+ auto newPrivacySensitiveDisplays =
+ getPrivacySensitiveDisplaysFromWindowInfos(windowInfosUpdate.windowInfos);
+ if (newPrivacySensitiveDisplays != mPrivacySensitiveDisplays) {
+ mPrivacySensitiveDisplays = std::move(newPrivacySensitiveDisplays);
+ mPointerChoreographer->onPrivacySensitiveDisplaysChanged(mPrivacySensitiveDisplays);
+ }
+}
+
+void PointerChoreographer::PointerChoreographerDisplayInfoListener::setInitialDisplayInfos(
+ const std::vector<gui::WindowInfo>& windowInfos) {
+ std::scoped_lock _l(mListenerLock);
+ mPrivacySensitiveDisplays = getPrivacySensitiveDisplaysFromWindowInfos(windowInfos);
+}
+
+std::unordered_set<ui::LogicalDisplayId /*displayId*/>
+PointerChoreographer::PointerChoreographerDisplayInfoListener::getPrivacySensitiveDisplays() {
+ std::scoped_lock _l(mListenerLock);
+ return mPrivacySensitiveDisplays;
}
void PointerChoreographer::PointerChoreographerDisplayInfoListener::
diff --git a/services/inputflinger/PointerChoreographer.h b/services/inputflinger/PointerChoreographer.h
index 12316c0..d9b075f 100644
--- a/services/inputflinger/PointerChoreographer.h
+++ b/services/inputflinger/PointerChoreographer.h
@@ -23,6 +23,7 @@
#include <android-base/thread_annotations.h>
#include <gui/WindowInfosListener.h>
#include <type_traits>
+#include <unordered_set>
namespace android {
@@ -107,9 +108,6 @@
void notifyDeviceReset(const NotifyDeviceResetArgs& args) override;
void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override;
- // Public because it's also used by tests to simulate the WindowInfosListener callback
- void onWindowInfosChanged(const std::vector<android::gui::WindowInfo>& windowInfos);
-
void dump(std::string& dump) override;
private:
@@ -133,20 +131,34 @@
void processTouchscreenAndStylusEventLocked(const NotifyMotionArgs& args) REQUIRES(mLock);
void processStylusHoverEventLocked(const NotifyMotionArgs& args) REQUIRES(mLock);
void processDeviceReset(const NotifyDeviceResetArgs& args);
- void onControllerAddedOrRemoved() REQUIRES(mLock);
- void onWindowInfosChangedLocked(const std::vector<android::gui::WindowInfo>& windowInfos)
+ void onControllerAddedOrRemovedLocked() REQUIRES(mLock);
+ void onPrivacySensitiveDisplaysChangedLocked(
+ const std::unordered_set<ui::LogicalDisplayId>& privacySensitiveDisplays)
REQUIRES(mLock);
+ void onPrivacySensitiveDisplaysChanged(
+ const std::unordered_set<ui::LogicalDisplayId>& privacySensitiveDisplays);
+ /* This listener keeps tracks of visible privacy sensitive displays and updates the
+ * choreographer if there are any changes.
+ *
+ * Listener uses mListenerLock to guard all private data as choreographer and SurfaceComposer
+ * both can call into the listener. To prevent deadlocks Choreographer can call listener with
+ * its lock held, but listener must not call choreographer with its lock.
+ */
class PointerChoreographerDisplayInfoListener : public gui::WindowInfosListener {
public:
explicit PointerChoreographerDisplayInfoListener(PointerChoreographer* pc)
: mPointerChoreographer(pc){};
void onWindowInfosChanged(const gui::WindowInfosUpdate&) override;
+ void setInitialDisplayInfos(const std::vector<gui::WindowInfo>& windowInfos);
+ std::unordered_set<ui::LogicalDisplayId /*displayId*/> getPrivacySensitiveDisplays();
void onPointerChoreographerDestroyed();
private:
std::mutex mListenerLock;
PointerChoreographer* mPointerChoreographer GUARDED_BY(mListenerLock);
+ std::unordered_set<ui::LogicalDisplayId /*displayId*/> mPrivacySensitiveDisplays
+ GUARDED_BY(mListenerLock);
};
sp<PointerChoreographerDisplayInfoListener> mWindowInfoListener GUARDED_BY(mLock);
@@ -180,6 +192,20 @@
bool mShowTouchesEnabled GUARDED_BY(mLock);
bool mStylusPointerIconEnabled GUARDED_BY(mLock);
std::set<ui::LogicalDisplayId /*displayId*/> mDisplaysWithPointersHidden;
+
+protected:
+ using WindowListenerRegisterConsumer = std::function<std::vector<gui::WindowInfo>(
+ const sp<android::gui::WindowInfosListener>&)>;
+ using WindowListenerUnregisterConsumer =
+ std::function<void(const sp<android::gui::WindowInfosListener>&)>;
+ explicit PointerChoreographer(InputListenerInterface& listener,
+ PointerChoreographerPolicyInterface&,
+ const WindowListenerRegisterConsumer& registerListener,
+ const WindowListenerUnregisterConsumer& unregisterListener);
+
+private:
+ const WindowListenerRegisterConsumer mRegisterListener;
+ const WindowListenerUnregisterConsumer mUnregisterListener;
};
} // namespace android
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index dae2b61..527edb6 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -4885,10 +4885,11 @@
mLock.lock();
- if (policyFlags & POLICY_FLAG_FILTERED) {
- // The events from InputFilter impersonate real hardware devices. Check these
- // events for consistency and print an error. An inconsistent event sent from
- // InputFilter could cause a crash in the later stages of dispatching pipeline.
+ {
+ // Verify all injected streams, whether the injection is coming from apps or from
+ // input filter. Print an error if the stream becomes inconsistent with this event.
+ // An inconsistent injected event sent could cause a crash in the later stages of
+ // dispatching pipeline.
auto [it, _] =
mInputFilterVerifiersByDisplay.try_emplace(displayId,
std::string("Injection on ") +
@@ -6388,9 +6389,8 @@
}
if (dispatchEntry.eventEntry->type == EventEntry::Type::KEY) {
- const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*(dispatchEntry.eventEntry));
fallbackKeyEntry =
- afterKeyEventLockedInterruptable(connection, dispatchEntry, keyEntry, handled);
+ afterKeyEventLockedInterruptable(connection, &dispatchEntry, handled);
}
} // End critical section: The -LockedInterruptable methods may have released the lock.
@@ -6614,8 +6614,17 @@
}
std::unique_ptr<const KeyEntry> InputDispatcher::afterKeyEventLockedInterruptable(
- const std::shared_ptr<Connection>& connection, DispatchEntry& dispatchEntry,
- const KeyEntry& keyEntry, bool handled) {
+ const std::shared_ptr<Connection>& connection, DispatchEntry* dispatchEntry, bool handled) {
+ // The dispatchEntry is currently valid, but it might point to a deleted object after we release
+ // the lock. For simplicity, make copies of the data of interest here and assume that
+ // 'dispatchEntry' is not valid after this section.
+ // Hold a strong reference to the EventEntry to ensure it's valid for the duration of this
+ // function, even if the DispatchEntry gets destroyed and releases its share of the ownership.
+ std::shared_ptr<const EventEntry> eventEntry = dispatchEntry->eventEntry;
+ const bool hasForegroundTarget = dispatchEntry->hasForegroundTarget();
+ const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*(eventEntry));
+ // To prevent misuse, ensure dispatchEntry is no longer valid.
+ dispatchEntry = nullptr;
if (keyEntry.flags & AKEY_EVENT_FLAG_FALLBACK) {
if (!handled) {
// Report the key as unhandled, since the fallback was not handled.
@@ -6632,7 +6641,7 @@
connection->inputState.removeFallbackKey(originalKeyCode);
}
- if (handled || !dispatchEntry.hasForegroundTarget()) {
+ if (handled || !hasForegroundTarget) {
// If the application handles the original key for which we previously
// generated a fallback or if the window is not a foreground window,
// then cancel the associated fallback key, if any.
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 6240e7f..e2fc7a0 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -687,8 +687,8 @@
std::map<ui::LogicalDisplayId /*displayId*/, InputVerifier> mVerifiersByDisplay;
// Returns a fallback KeyEntry that should be sent to the connection, if required.
std::unique_ptr<const KeyEntry> afterKeyEventLockedInterruptable(
- const std::shared_ptr<Connection>& connection, DispatchEntry& dispatchEntry,
- const KeyEntry& keyEntry, bool handled) REQUIRES(mLock);
+ const std::shared_ptr<Connection>& connection, DispatchEntry* dispatchEntry,
+ bool handled) REQUIRES(mLock);
// Find touched state and touched window by token.
std::tuple<TouchState*, TouchedWindow*, ui::LogicalDisplayId /*displayId*/>
diff --git a/services/inputflinger/include/PointerControllerInterface.h b/services/inputflinger/include/PointerControllerInterface.h
index cee44fc..e34ed0f 100644
--- a/services/inputflinger/include/PointerControllerInterface.h
+++ b/services/inputflinger/include/PointerControllerInterface.h
@@ -142,10 +142,13 @@
/* Sets the custom pointer icon for mice or styluses. */
virtual void setCustomPointerIcon(const SpriteIcon& icon) = 0;
- /* Sets the flag to skip screenshot of the pointer indicators on the display matching the
- * provided displayId.
+ /* Sets the flag to skip screenshot of the pointer indicators on the display for the specified
+ * displayId. This flag can only be reset with resetSkipScreenshotFlags()
*/
- virtual void setSkipScreenshot(ui::LogicalDisplayId displayId, bool skip) = 0;
+ virtual void setSkipScreenshotFlagForDisplay(ui::LogicalDisplayId displayId) = 0;
+
+ /* Resets the flag to skip screenshot of the pointer indicators for all displays. */
+ virtual void clearSkipScreenshotFlags() = 0;
};
} // namespace android
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 2b33403..2daf195 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -409,7 +409,7 @@
mDropUntilNextSync = true;
} else {
for_each_mapper_in_subdevice(rawEvent->deviceId, [&](InputMapper& mapper) {
- out += mapper.process(rawEvent);
+ out += mapper.process(*rawEvent);
});
}
--count;
diff --git a/services/inputflinger/reader/controller/PeripheralController.cpp b/services/inputflinger/reader/controller/PeripheralController.cpp
index 27b9d23..49ad8b5 100644
--- a/services/inputflinger/reader/controller/PeripheralController.cpp
+++ b/services/inputflinger/reader/controller/PeripheralController.cpp
@@ -418,7 +418,11 @@
}
rawInfos.insert_or_assign(rawId, rawInfo.value());
// Check if this is a group LEDs for player ID
- std::regex lightPattern("([a-z]+)([0-9]+)");
+ // The name for the light has already been parsed and is the `function`
+ // value; for player ID lights the function is expected to be `player-#`.
+ // However, the Sony driver will use `sony#` instead on SIXAXIS
+ // gamepads.
+ std::regex lightPattern("(player|sony)-?([0-9]+)");
std::smatch results;
if (std::regex_match(rawInfo->name, results, lightPattern)) {
std::string commonName = results[1].str();
diff --git a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp
index 09a5f08..90685de 100644
--- a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp
+++ b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp
@@ -155,8 +155,8 @@
mMotionAccumulator.finishSync();
}
- mCursorButtonAccumulator.process(&rawEvent);
- mMotionAccumulator.process(&rawEvent);
+ mCursorButtonAccumulator.process(rawEvent);
+ mMotionAccumulator.process(rawEvent);
return out;
}
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index c67314d..20cdb59 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -55,14 +55,14 @@
mRelY = 0;
}
-void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
- if (rawEvent->type == EV_REL) {
- switch (rawEvent->code) {
+void CursorMotionAccumulator::process(const RawEvent& rawEvent) {
+ if (rawEvent.type == EV_REL) {
+ switch (rawEvent.code) {
case REL_X:
- mRelX = rawEvent->value;
+ mRelX = rawEvent.value;
break;
case REL_Y:
- mRelY = rawEvent->value;
+ mRelY = rawEvent.value;
break;
}
}
@@ -215,16 +215,16 @@
return InputMapper::reset(when);
}
-std::list<NotifyArgs> CursorInputMapper::process(const RawEvent* rawEvent) {
+std::list<NotifyArgs> CursorInputMapper::process(const RawEvent& rawEvent) {
std::list<NotifyArgs> out;
mCursorButtonAccumulator.process(rawEvent);
mCursorMotionAccumulator.process(rawEvent);
mCursorScrollAccumulator.process(rawEvent);
- if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
+ if (rawEvent.type == EV_SYN && rawEvent.code == SYN_REPORT) {
const auto [eventTime, readTime] =
applyBluetoothTimestampSmoothening(getDeviceContext().getDeviceIdentifier(),
- rawEvent->when, rawEvent->readTime,
+ rawEvent.when, rawEvent.readTime,
mLastEventTime);
out += sync(eventTime, readTime);
mLastEventTime = eventTime;
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.h b/services/inputflinger/reader/mapper/CursorInputMapper.h
index 75ca9c0..2108488 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.h
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.h
@@ -34,7 +34,7 @@
CursorMotionAccumulator();
void reset(InputDeviceContext& deviceContext);
- void process(const RawEvent* rawEvent);
+ void process(const RawEvent& rawEvent);
void finishSync();
inline int32_t getRelativeX() const { return mRelX; }
@@ -62,7 +62,7 @@
const InputReaderConfiguration& readerConfig,
ConfigurationChanges changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
- [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
+ [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override;
virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) override;
diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
index 987d2d0..3af1d04 100644
--- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
@@ -61,13 +61,13 @@
return InputMapper::reset(when);
}
-std::list<NotifyArgs> ExternalStylusInputMapper::process(const RawEvent* rawEvent) {
+std::list<NotifyArgs> ExternalStylusInputMapper::process(const RawEvent& rawEvent) {
std::list<NotifyArgs> out;
mSingleTouchMotionAccumulator.process(rawEvent);
mTouchButtonAccumulator.process(rawEvent);
- if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
- out += sync(rawEvent->when);
+ if (rawEvent.type == EV_SYN && rawEvent.code == SYN_REPORT) {
+ out += sync(rawEvent.when);
}
return out;
}
diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
index 97df02b..c040a7b 100644
--- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
+++ b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
@@ -39,7 +39,7 @@
const InputReaderConfiguration& config,
ConfigurationChanges changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
- [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
+ [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override;
private:
SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h
index c7eea0e..2c51448 100644
--- a/services/inputflinger/reader/mapper/InputMapper.h
+++ b/services/inputflinger/reader/mapper/InputMapper.h
@@ -78,7 +78,7 @@
const InputReaderConfiguration& config,
ConfigurationChanges changes);
[[nodiscard]] virtual std::list<NotifyArgs> reset(nsecs_t when);
- [[nodiscard]] virtual std::list<NotifyArgs> process(const RawEvent* rawEvent) = 0;
+ [[nodiscard]] virtual std::list<NotifyArgs> process(const RawEvent& rawEvent) = 0;
[[nodiscard]] virtual std::list<NotifyArgs> timeoutExpired(nsecs_t when);
virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
index 5ce4d30..41e018d 100644
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
@@ -259,29 +259,29 @@
return InputMapper::reset(when);
}
-std::list<NotifyArgs> JoystickInputMapper::process(const RawEvent* rawEvent) {
+std::list<NotifyArgs> JoystickInputMapper::process(const RawEvent& rawEvent) {
std::list<NotifyArgs> out;
- switch (rawEvent->type) {
+ switch (rawEvent.type) {
case EV_ABS: {
- auto it = mAxes.find(rawEvent->code);
+ auto it = mAxes.find(rawEvent.code);
if (it != mAxes.end()) {
Axis& axis = it->second;
float newValue, highNewValue;
switch (axis.axisInfo.mode) {
case AxisInfo::MODE_INVERT:
- newValue = (axis.rawAxisInfo.maxValue - rawEvent->value) * axis.scale +
+ newValue = (axis.rawAxisInfo.maxValue - rawEvent.value) * axis.scale +
axis.offset;
highNewValue = 0.0f;
break;
case AxisInfo::MODE_SPLIT:
- if (rawEvent->value < axis.axisInfo.splitValue) {
- newValue = (axis.axisInfo.splitValue - rawEvent->value) * axis.scale +
+ if (rawEvent.value < axis.axisInfo.splitValue) {
+ newValue = (axis.axisInfo.splitValue - rawEvent.value) * axis.scale +
axis.offset;
highNewValue = 0.0f;
- } else if (rawEvent->value > axis.axisInfo.splitValue) {
+ } else if (rawEvent.value > axis.axisInfo.splitValue) {
newValue = 0.0f;
highNewValue =
- (rawEvent->value - axis.axisInfo.splitValue) * axis.highScale +
+ (rawEvent.value - axis.axisInfo.splitValue) * axis.highScale +
axis.highOffset;
} else {
newValue = 0.0f;
@@ -289,7 +289,7 @@
}
break;
default:
- newValue = rawEvent->value * axis.scale + axis.offset;
+ newValue = rawEvent.value * axis.scale + axis.offset;
highNewValue = 0.0f;
break;
}
@@ -300,9 +300,9 @@
}
case EV_SYN:
- switch (rawEvent->code) {
+ switch (rawEvent.code) {
case SYN_REPORT:
- out += sync(rawEvent->when, rawEvent->readTime, /*force=*/false);
+ out += sync(rawEvent.when, rawEvent.readTime, /*force=*/false);
break;
}
break;
diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.h b/services/inputflinger/reader/mapper/JoystickInputMapper.h
index 313f092..621d38b 100644
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.h
+++ b/services/inputflinger/reader/mapper/JoystickInputMapper.h
@@ -35,7 +35,7 @@
const InputReaderConfiguration& config,
ConfigurationChanges changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
- [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
+ [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override;
private:
struct Axis {
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
index 2e32380..91ec62d 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
@@ -236,15 +236,15 @@
return out;
}
-std::list<NotifyArgs> KeyboardInputMapper::process(const RawEvent* rawEvent) {
+std::list<NotifyArgs> KeyboardInputMapper::process(const RawEvent& rawEvent) {
std::list<NotifyArgs> out;
- mHidUsageAccumulator.process(*rawEvent);
- switch (rawEvent->type) {
+ mHidUsageAccumulator.process(rawEvent);
+ switch (rawEvent.type) {
case EV_KEY: {
- int32_t scanCode = rawEvent->code;
+ int32_t scanCode = rawEvent.code;
if (isSupportedScanCode(scanCode)) {
- out += processKey(rawEvent->when, rawEvent->readTime, rawEvent->value != 0,
+ out += processKey(rawEvent.when, rawEvent.readTime, rawEvent.value != 0,
scanCode, mHidUsageAccumulator.consumeCurrentHidUsage());
}
break;
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.h b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
index bee2a99..c7df558 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.h
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
@@ -36,7 +36,7 @@
const InputReaderConfiguration& config,
ConfigurationChanges changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
- [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
+ [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override;
int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode) override;
int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) override;
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
index bca9d91..1986fe2 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
@@ -40,7 +40,7 @@
return TouchInputMapper::reset(when);
}
-std::list<NotifyArgs> MultiTouchInputMapper::process(const RawEvent* rawEvent) {
+std::list<NotifyArgs> MultiTouchInputMapper::process(const RawEvent& rawEvent) {
std::list<NotifyArgs> out = TouchInputMapper::process(rawEvent);
mMultiTouchMotionAccumulator.process(rawEvent);
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
index 5c173f3..cca2327 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
@@ -31,7 +31,7 @@
~MultiTouchInputMapper() override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
- [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
+ [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override;
[[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when,
const InputReaderConfiguration& config,
ConfigurationChanges changes) override;
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
index 0ddbc06..27ff52f 100644
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
@@ -101,12 +101,12 @@
return InputMapper::reset(when);
}
-std::list<NotifyArgs> RotaryEncoderInputMapper::process(const RawEvent* rawEvent) {
+std::list<NotifyArgs> RotaryEncoderInputMapper::process(const RawEvent& rawEvent) {
std::list<NotifyArgs> out;
mRotaryEncoderScrollAccumulator.process(rawEvent);
- if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
- out += sync(rawEvent->when, rawEvent->readTime);
+ if (rawEvent.type == EV_SYN && rawEvent.code == SYN_REPORT) {
+ out += sync(rawEvent.when, rawEvent.readTime);
}
return out;
}
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
index fe5d152..14c540b 100644
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
+++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
@@ -39,7 +39,7 @@
const InputReaderConfiguration& config,
ConfigurationChanges changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
- [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
+ [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override;
private:
CursorScrollAccumulator mRotaryEncoderScrollAccumulator;
diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.cpp b/services/inputflinger/reader/mapper/SensorInputMapper.cpp
index a131e35..d7f2993 100644
--- a/services/inputflinger/reader/mapper/SensorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/SensorInputMapper.cpp
@@ -251,35 +251,35 @@
mPrevMscTime = static_cast<uint32_t>(mscTime);
}
-std::list<NotifyArgs> SensorInputMapper::process(const RawEvent* rawEvent) {
+std::list<NotifyArgs> SensorInputMapper::process(const RawEvent& rawEvent) {
std::list<NotifyArgs> out;
- switch (rawEvent->type) {
+ switch (rawEvent.type) {
case EV_ABS: {
- auto it = mAxes.find(rawEvent->code);
+ auto it = mAxes.find(rawEvent.code);
if (it != mAxes.end()) {
Axis& axis = it->second;
- axis.newValue = rawEvent->value * axis.scale + axis.offset;
+ axis.newValue = rawEvent.value * axis.scale + axis.offset;
}
break;
}
case EV_SYN:
- switch (rawEvent->code) {
+ switch (rawEvent.code) {
case SYN_REPORT:
for (std::pair<const int32_t, Axis>& pair : mAxes) {
Axis& axis = pair.second;
axis.currentValue = axis.newValue;
}
- out += sync(rawEvent->when, /*force=*/false);
+ out += sync(rawEvent.when, /*force=*/false);
break;
}
break;
case EV_MSC:
- switch (rawEvent->code) {
+ switch (rawEvent.code) {
case MSC_TIMESTAMP:
// hardware timestamp is nano seconds
- processHardWareTimestamp(rawEvent->when, rawEvent->value);
+ processHardWareTimestamp(rawEvent.when, rawEvent.value);
break;
}
}
diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.h b/services/inputflinger/reader/mapper/SensorInputMapper.h
index a55dcd1..63bc151 100644
--- a/services/inputflinger/reader/mapper/SensorInputMapper.h
+++ b/services/inputflinger/reader/mapper/SensorInputMapper.h
@@ -40,7 +40,7 @@
const InputReaderConfiguration& config,
ConfigurationChanges changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
- [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
+ [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override;
bool enableSensor(InputDeviceSensorType sensorType, std::chrono::microseconds samplingPeriod,
std::chrono::microseconds maxBatchReportLatency) override;
void disableSensor(InputDeviceSensorType sensorType) override;
diff --git a/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp b/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp
index ed0e270..140bb0c 100644
--- a/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp
@@ -30,7 +30,7 @@
return TouchInputMapper::reset(when);
}
-std::list<NotifyArgs> SingleTouchInputMapper::process(const RawEvent* rawEvent) {
+std::list<NotifyArgs> SingleTouchInputMapper::process(const RawEvent& rawEvent) {
std::list<NotifyArgs> out = TouchInputMapper::process(rawEvent);
mSingleTouchMotionAccumulator.process(rawEvent);
diff --git a/services/inputflinger/reader/mapper/SingleTouchInputMapper.h b/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
index 7726bfb..bc38711 100644
--- a/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
@@ -31,7 +31,7 @@
~SingleTouchInputMapper() override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
- [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
+ [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override;
protected:
void syncTouch(nsecs_t when, RawState* outState) override;
diff --git a/services/inputflinger/reader/mapper/SwitchInputMapper.cpp b/services/inputflinger/reader/mapper/SwitchInputMapper.cpp
index 05338da..f131fb7 100644
--- a/services/inputflinger/reader/mapper/SwitchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/SwitchInputMapper.cpp
@@ -30,16 +30,16 @@
return AINPUT_SOURCE_SWITCH;
}
-std::list<NotifyArgs> SwitchInputMapper::process(const RawEvent* rawEvent) {
+std::list<NotifyArgs> SwitchInputMapper::process(const RawEvent& rawEvent) {
std::list<NotifyArgs> out;
- switch (rawEvent->type) {
+ switch (rawEvent.type) {
case EV_SW:
- processSwitch(rawEvent->code, rawEvent->value);
+ processSwitch(rawEvent.code, rawEvent.value);
break;
case EV_SYN:
- if (rawEvent->code == SYN_REPORT) {
- out += sync(rawEvent->when);
+ if (rawEvent.code == SYN_REPORT) {
+ out += sync(rawEvent.when);
}
}
return out;
diff --git a/services/inputflinger/reader/mapper/SwitchInputMapper.h b/services/inputflinger/reader/mapper/SwitchInputMapper.h
index 2fb48bb..5d8aa2c 100644
--- a/services/inputflinger/reader/mapper/SwitchInputMapper.h
+++ b/services/inputflinger/reader/mapper/SwitchInputMapper.h
@@ -29,7 +29,7 @@
virtual ~SwitchInputMapper();
virtual uint32_t getSources() const override;
- [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
+ [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override;
virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode) override;
virtual void dump(std::string& dump) override;
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 8b4b691..9d049ae 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -537,18 +537,6 @@
return getDeviceContext().getAssociatedViewport();
}
- const std::optional<std::string> associatedDisplayUniqueIdByDescriptor =
- getDeviceContext().getAssociatedDisplayUniqueIdByDescriptor();
- if (associatedDisplayUniqueIdByDescriptor) {
- return getDeviceContext().getAssociatedViewport();
- }
-
- const std::optional<std::string> associatedDisplayUniqueIdByPort =
- getDeviceContext().getAssociatedDisplayUniqueIdByPort();
- if (associatedDisplayUniqueIdByPort) {
- return getDeviceContext().getAssociatedViewport();
- }
-
if (mDeviceMode == DeviceMode::POINTER) {
std::optional<DisplayViewport> viewport =
mConfig.getDisplayViewportById(mConfig.defaultPointerDisplayId);
@@ -1415,14 +1403,14 @@
mExternalStylusFusionTimeout = LLONG_MAX;
}
-std::list<NotifyArgs> TouchInputMapper::process(const RawEvent* rawEvent) {
+std::list<NotifyArgs> TouchInputMapper::process(const RawEvent& rawEvent) {
mCursorButtonAccumulator.process(rawEvent);
mCursorScrollAccumulator.process(rawEvent);
mTouchButtonAccumulator.process(rawEvent);
std::list<NotifyArgs> out;
- if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
- out += sync(rawEvent->when, rawEvent->readTime);
+ if (rawEvent.type == EV_SYN && rawEvent.code == SYN_REPORT) {
+ out += sync(rawEvent.when, rawEvent.readTime);
}
return out;
}
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index b24f2ff..30c58a5 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -174,7 +174,7 @@
const InputReaderConfiguration& config,
ConfigurationChanges changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
- [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
+ [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override;
int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode) override;
int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) override;
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
index b8911db..24efae8 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
@@ -24,6 +24,7 @@
#include <mutex>
#include <optional>
+#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/thread_annotations.h>
#include <android/input.h>
@@ -241,10 +242,10 @@
mMetricsId(metricsIdFromInputDeviceIdentifier(deviceContext.getDeviceIdentifier())) {
RawAbsoluteAxisInfo slotAxisInfo;
deviceContext.getAbsoluteAxisInfo(ABS_MT_SLOT, &slotAxisInfo);
- if (!slotAxisInfo.valid || slotAxisInfo.maxValue <= 0) {
- ALOGW("Touchpad \"%s\" doesn't have a valid ABS_MT_SLOT axis, and probably won't work "
- "properly.",
- deviceContext.getName().c_str());
+ if (!slotAxisInfo.valid || slotAxisInfo.maxValue < 0) {
+ LOG(WARNING) << "Touchpad " << deviceContext.getName()
+ << " doesn't have a valid ABS_MT_SLOT axis, and probably won't work properly.";
+ slotAxisInfo.maxValue = 0;
}
mMotionAccumulator.configure(deviceContext, slotAxisInfo.maxValue + 1, true);
@@ -416,17 +417,17 @@
mResettingInterpreter = false;
}
-std::list<NotifyArgs> TouchpadInputMapper::process(const RawEvent* rawEvent) {
+std::list<NotifyArgs> TouchpadInputMapper::process(const RawEvent& rawEvent) {
if (mPointerCaptured) {
- return mCapturedEventConverter.process(*rawEvent);
+ return mCapturedEventConverter.process(rawEvent);
}
if (mMotionAccumulator.getActiveSlotsCount() == 0) {
- mGestureStartTime = rawEvent->when;
+ mGestureStartTime = rawEvent.when;
}
std::optional<SelfContainedHardwareState> state = mStateConverter.processRawEvent(rawEvent);
if (state) {
updatePalmDetectionMetrics();
- return sendHardwareState(rawEvent->when, rawEvent->readTime, *state);
+ return sendHardwareState(rawEvent.when, rawEvent.readTime, *state);
} else {
return {};
}
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.h b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
index 546fa5b..8baa63e 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
@@ -56,7 +56,7 @@
const InputReaderConfiguration& config,
ConfigurationChanges changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
- [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
+ [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override;
[[nodiscard]] std::list<NotifyArgs> timeoutExpired(nsecs_t when) override;
void consumeGesture(const Gesture* gesture);
diff --git a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
index 8d78d0f..a3a48ef 100644
--- a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
@@ -36,7 +36,7 @@
info.setVibrator(true);
}
-std::list<NotifyArgs> VibratorInputMapper::process(const RawEvent* rawEvent) {
+std::list<NotifyArgs> VibratorInputMapper::process(const RawEvent& rawEvent) {
// TODO: Handle FF_STATUS, although it does not seem to be widely supported.
return {};
}
diff --git a/services/inputflinger/reader/mapper/VibratorInputMapper.h b/services/inputflinger/reader/mapper/VibratorInputMapper.h
index 9079c73..7519682 100644
--- a/services/inputflinger/reader/mapper/VibratorInputMapper.h
+++ b/services/inputflinger/reader/mapper/VibratorInputMapper.h
@@ -30,7 +30,7 @@
virtual uint32_t getSources() const override;
virtual void populateDeviceInfo(InputDeviceInfo& deviceInfo) override;
- [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
+ [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override;
[[nodiscard]] std::list<NotifyArgs> vibrate(const VibrationSequence& sequence, ssize_t repeat,
int32_t token) override;
diff --git a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.cpp
index 153236c..9e722d4 100644
--- a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.cpp
+++ b/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.cpp
@@ -47,32 +47,32 @@
mBtnTask = 0;
}
-void CursorButtonAccumulator::process(const RawEvent* rawEvent) {
- if (rawEvent->type == EV_KEY) {
- switch (rawEvent->code) {
+void CursorButtonAccumulator::process(const RawEvent& rawEvent) {
+ if (rawEvent.type == EV_KEY) {
+ switch (rawEvent.code) {
case BTN_LEFT:
- mBtnLeft = rawEvent->value;
+ mBtnLeft = rawEvent.value;
break;
case BTN_RIGHT:
- mBtnRight = rawEvent->value;
+ mBtnRight = rawEvent.value;
break;
case BTN_MIDDLE:
- mBtnMiddle = rawEvent->value;
+ mBtnMiddle = rawEvent.value;
break;
case BTN_BACK:
- mBtnBack = rawEvent->value;
+ mBtnBack = rawEvent.value;
break;
case BTN_SIDE:
- mBtnSide = rawEvent->value;
+ mBtnSide = rawEvent.value;
break;
case BTN_FORWARD:
- mBtnForward = rawEvent->value;
+ mBtnForward = rawEvent.value;
break;
case BTN_EXTRA:
- mBtnExtra = rawEvent->value;
+ mBtnExtra = rawEvent.value;
break;
case BTN_TASK:
- mBtnTask = rawEvent->value;
+ mBtnTask = rawEvent.value;
break;
}
}
diff --git a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h b/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h
index 6960644..256b2bb 100644
--- a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h
+++ b/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h
@@ -29,7 +29,7 @@
CursorButtonAccumulator();
void reset(const InputDeviceContext& deviceContext);
- void process(const RawEvent* rawEvent);
+ void process(const RawEvent& rawEvent);
uint32_t getButtonState() const;
inline bool isLeftPressed() const { return mBtnLeft; }
diff --git a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp
index 0714694..f85cab2 100644
--- a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp
+++ b/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp
@@ -39,14 +39,14 @@
mRelHWheel = 0;
}
-void CursorScrollAccumulator::process(const RawEvent* rawEvent) {
- if (rawEvent->type == EV_REL) {
- switch (rawEvent->code) {
+void CursorScrollAccumulator::process(const RawEvent& rawEvent) {
+ if (rawEvent.type == EV_REL) {
+ switch (rawEvent.code) {
case REL_WHEEL:
- mRelWheel = rawEvent->value;
+ mRelWheel = rawEvent.value;
break;
case REL_HWHEEL:
- mRelHWheel = rawEvent->value;
+ mRelHWheel = rawEvent.value;
break;
}
}
diff --git a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h b/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h
index ae1b7a3..e563620 100644
--- a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h
+++ b/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h
@@ -31,7 +31,7 @@
void configure(InputDeviceContext& deviceContext);
void reset(InputDeviceContext& deviceContext);
- void process(const RawEvent* rawEvent);
+ void process(const RawEvent& rawEvent);
void finishSync();
inline bool haveRelativeVWheel() const { return mHaveRelWheel; }
diff --git a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp
index b3f1700..4919068 100644
--- a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp
+++ b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp
@@ -45,12 +45,12 @@
mCurrentSlot = -1;
}
-void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
- if (rawEvent->type == EV_ABS) {
+void MultiTouchMotionAccumulator::process(const RawEvent& rawEvent) {
+ if (rawEvent.type == EV_ABS) {
bool newSlot = false;
if (mUsingSlotsProtocol) {
- if (rawEvent->code == ABS_MT_SLOT) {
- mCurrentSlot = rawEvent->value;
+ if (rawEvent.code == ABS_MT_SLOT) {
+ mCurrentSlot = rawEvent.value;
newSlot = true;
}
} else if (mCurrentSlot < 0) {
@@ -72,12 +72,12 @@
if (!mUsingSlotsProtocol) {
slot.mInUse = true;
}
- if (rawEvent->code == ABS_MT_POSITION_X || rawEvent->code == ABS_MT_POSITION_Y) {
- warnIfNotInUse(*rawEvent, slot);
+ if (rawEvent.code == ABS_MT_POSITION_X || rawEvent.code == ABS_MT_POSITION_Y) {
+ warnIfNotInUse(rawEvent, slot);
}
- slot.populateAxisValue(rawEvent->code, rawEvent->value);
+ slot.populateAxisValue(rawEvent.code, rawEvent.value);
}
- } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) {
+ } else if (rawEvent.type == EV_SYN && rawEvent.code == SYN_MT_REPORT) {
// MultiTouch Sync: The driver has returned all data for *one* of the pointers.
mCurrentSlot += 1;
}
diff --git a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h
index a0f2147..388ed82 100644
--- a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h
+++ b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h
@@ -76,7 +76,7 @@
void configure(const InputDeviceContext& deviceContext, size_t slotCount,
bool usingSlotsProtocol);
void reset(const InputDeviceContext& deviceContext);
- void process(const RawEvent* rawEvent);
+ void process(const RawEvent& rawEvent);
void finishSync();
size_t getActiveSlotsCount() const;
diff --git a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp
index 27b8e40..2b82ddf 100644
--- a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp
+++ b/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp
@@ -45,29 +45,29 @@
mAbsTiltY = 0;
}
-void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) {
- if (rawEvent->type == EV_ABS) {
- switch (rawEvent->code) {
+void SingleTouchMotionAccumulator::process(const RawEvent& rawEvent) {
+ if (rawEvent.type == EV_ABS) {
+ switch (rawEvent.code) {
case ABS_X:
- mAbsX = rawEvent->value;
+ mAbsX = rawEvent.value;
break;
case ABS_Y:
- mAbsY = rawEvent->value;
+ mAbsY = rawEvent.value;
break;
case ABS_PRESSURE:
- mAbsPressure = rawEvent->value;
+ mAbsPressure = rawEvent.value;
break;
case ABS_TOOL_WIDTH:
- mAbsToolWidth = rawEvent->value;
+ mAbsToolWidth = rawEvent.value;
break;
case ABS_DISTANCE:
- mAbsDistance = rawEvent->value;
+ mAbsDistance = rawEvent.value;
break;
case ABS_TILT_X:
- mAbsTiltX = rawEvent->value;
+ mAbsTiltX = rawEvent.value;
break;
case ABS_TILT_Y:
- mAbsTiltY = rawEvent->value;
+ mAbsTiltY = rawEvent.value;
break;
}
}
diff --git a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.h b/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.h
index 93056f0..fb74bca 100644
--- a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.h
+++ b/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.h
@@ -28,7 +28,7 @@
public:
SingleTouchMotionAccumulator();
- void process(const RawEvent* rawEvent);
+ void process(const RawEvent& rawEvent);
void reset(InputDeviceContext& deviceContext);
inline int32_t getAbsoluteX() const { return mAbsX; }
diff --git a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp
index 8c4bed3..ba8577e 100644
--- a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp
+++ b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp
@@ -52,60 +52,60 @@
mHidUsageAccumulator.reset();
}
-void TouchButtonAccumulator::process(const RawEvent* rawEvent) {
- mHidUsageAccumulator.process(*rawEvent);
+void TouchButtonAccumulator::process(const RawEvent& rawEvent) {
+ mHidUsageAccumulator.process(rawEvent);
- if (rawEvent->type == EV_KEY) {
- switch (rawEvent->code) {
+ if (rawEvent.type == EV_KEY) {
+ switch (rawEvent.code) {
case BTN_TOUCH:
- mBtnTouch = rawEvent->value;
+ mBtnTouch = rawEvent.value;
break;
case BTN_STYLUS:
- mBtnStylus = rawEvent->value;
+ mBtnStylus = rawEvent.value;
break;
case BTN_STYLUS2:
case BTN_0: // BTN_0 is what gets mapped for the HID usage
// Digitizers.SecondaryBarrelSwitch
- mBtnStylus2 = rawEvent->value;
+ mBtnStylus2 = rawEvent.value;
break;
case BTN_TOOL_FINGER:
- mBtnToolFinger = rawEvent->value;
+ mBtnToolFinger = rawEvent.value;
break;
case BTN_TOOL_PEN:
- mBtnToolPen = rawEvent->value;
+ mBtnToolPen = rawEvent.value;
break;
case BTN_TOOL_RUBBER:
- mBtnToolRubber = rawEvent->value;
+ mBtnToolRubber = rawEvent.value;
break;
case BTN_TOOL_BRUSH:
- mBtnToolBrush = rawEvent->value;
+ mBtnToolBrush = rawEvent.value;
break;
case BTN_TOOL_PENCIL:
- mBtnToolPencil = rawEvent->value;
+ mBtnToolPencil = rawEvent.value;
break;
case BTN_TOOL_AIRBRUSH:
- mBtnToolAirbrush = rawEvent->value;
+ mBtnToolAirbrush = rawEvent.value;
break;
case BTN_TOOL_MOUSE:
- mBtnToolMouse = rawEvent->value;
+ mBtnToolMouse = rawEvent.value;
break;
case BTN_TOOL_LENS:
- mBtnToolLens = rawEvent->value;
+ mBtnToolLens = rawEvent.value;
break;
case BTN_TOOL_DOUBLETAP:
- mBtnToolDoubleTap = rawEvent->value;
+ mBtnToolDoubleTap = rawEvent.value;
break;
case BTN_TOOL_TRIPLETAP:
- mBtnToolTripleTap = rawEvent->value;
+ mBtnToolTripleTap = rawEvent.value;
break;
case BTN_TOOL_QUADTAP:
- mBtnToolQuadTap = rawEvent->value;
+ mBtnToolQuadTap = rawEvent.value;
break;
case BTN_TOOL_QUINTTAP:
- mBtnToolQuintTap = rawEvent->value;
+ mBtnToolQuintTap = rawEvent.value;
break;
default:
- processMappedKey(rawEvent->code, rawEvent->value);
+ processMappedKey(rawEvent.code, rawEvent.value);
}
return;
}
diff --git a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h
index e829692..c7adf84 100644
--- a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h
+++ b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h
@@ -33,7 +33,7 @@
void configure();
void reset();
- void process(const RawEvent* rawEvent);
+ void process(const RawEvent& rawEvent);
uint32_t getButtonState() const;
ToolType getToolType() const;
diff --git a/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.cpp b/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.cpp
index b89b7f3..6885adb 100644
--- a/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.cpp
+++ b/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.cpp
@@ -40,15 +40,15 @@
}
std::optional<SelfContainedHardwareState> HardwareStateConverter::processRawEvent(
- const RawEvent* rawEvent) {
+ const RawEvent& rawEvent) {
std::optional<SelfContainedHardwareState> out;
- if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
- out = produceHardwareState(rawEvent->when);
+ if (rawEvent.type == EV_SYN && rawEvent.code == SYN_REPORT) {
+ out = produceHardwareState(rawEvent.when);
mMotionAccumulator.finishSync();
mMscTimestamp = 0;
}
- if (rawEvent->type == EV_MSC && rawEvent->code == MSC_TIMESTAMP) {
- mMscTimestamp = rawEvent->value;
+ if (rawEvent.type == EV_MSC && rawEvent.code == MSC_TIMESTAMP) {
+ mMscTimestamp = rawEvent.value;
}
mCursorButtonAccumulator.process(rawEvent);
mMotionAccumulator.process(rawEvent);
diff --git a/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.h b/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.h
index 633448e..07e62c6 100644
--- a/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.h
+++ b/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.h
@@ -44,7 +44,7 @@
HardwareStateConverter(const InputDeviceContext& deviceContext,
MultiTouchMotionAccumulator& motionAccumulator);
- std::optional<SelfContainedHardwareState> processRawEvent(const RawEvent* event);
+ std::optional<SelfContainedHardwareState> processRawEvent(const RawEvent& event);
void reset();
private:
diff --git a/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp b/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp
index 69264f8..f4a5e0d 100644
--- a/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp
+++ b/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp
@@ -90,7 +90,7 @@
// prefixed with "gestureProp." and have spaces replaced by underscores. So, for example, the
// configuration key "gestureProp.Palm_Width" refers to the "Palm Width" property.
const std::string gesturePropPrefix = "gestureProp.";
- for (const std::string key : idcProperties.getKeysWithPrefix(gesturePropPrefix)) {
+ for (const std::string& key : idcProperties.getKeysWithPrefix(gesturePropPrefix)) {
std::string propertyName = key.substr(gesturePropPrefix.length());
for (size_t i = 0; i < propertyName.length(); i++) {
if (propertyName[i] == '_') {
diff --git a/services/inputflinger/tests/FakePointerController.cpp b/services/inputflinger/tests/FakePointerController.cpp
index 2bb57b3..d0998ba 100644
--- a/services/inputflinger/tests/FakePointerController.cpp
+++ b/services/inputflinger/tests/FakePointerController.cpp
@@ -76,13 +76,15 @@
mCustomIconStyle = icon.style;
}
-void FakePointerController::setSkipScreenshot(ui::LogicalDisplayId displayId, bool skip) {
- if (skip) {
- mDisplaysToSkipScreenshot.insert(displayId);
- } else {
- mDisplaysToSkipScreenshot.erase(displayId);
- }
-};
+void FakePointerController::setSkipScreenshotFlagForDisplay(ui::LogicalDisplayId displayId) {
+ mDisplaysToSkipScreenshotFlagChanged = true;
+ mDisplaysToSkipScreenshot.insert(displayId);
+}
+
+void FakePointerController::clearSkipScreenshotFlags() {
+ mDisplaysToSkipScreenshotFlagChanged = true;
+ mDisplaysToSkipScreenshot.clear();
+}
void FakePointerController::assertViewportSet(ui::LogicalDisplayId displayId) {
ASSERT_TRUE(mDisplayId);
@@ -125,13 +127,21 @@
ASSERT_EQ(std::nullopt, mCustomIconStyle);
}
-void FakePointerController::assertIsHiddenOnMirroredDisplays(ui::LogicalDisplayId displayId,
- bool isHidden) {
- if (isHidden) {
- ASSERT_TRUE(mDisplaysToSkipScreenshot.find(displayId) != mDisplaysToSkipScreenshot.end());
- } else {
- ASSERT_TRUE(mDisplaysToSkipScreenshot.find(displayId) == mDisplaysToSkipScreenshot.end());
- }
+void FakePointerController::assertIsSkipScreenshotFlagSet(ui::LogicalDisplayId displayId) {
+ ASSERT_TRUE(mDisplaysToSkipScreenshot.find(displayId) != mDisplaysToSkipScreenshot.end());
+}
+
+void FakePointerController::assertIsSkipScreenshotFlagNotSet(ui::LogicalDisplayId displayId) {
+ ASSERT_TRUE(mDisplaysToSkipScreenshot.find(displayId) == mDisplaysToSkipScreenshot.end());
+}
+
+void FakePointerController::assertSkipScreenshotFlagChanged() {
+ ASSERT_TRUE(mDisplaysToSkipScreenshotFlagChanged);
+ mDisplaysToSkipScreenshotFlagChanged = false;
+}
+
+void FakePointerController::assertSkipScreenshotFlagNotChanged() {
+ ASSERT_FALSE(mDisplaysToSkipScreenshotFlagChanged);
}
bool FakePointerController::isPointerShown() {
diff --git a/services/inputflinger/tests/FakePointerController.h b/services/inputflinger/tests/FakePointerController.h
index 5bc713f..2c76c62 100644
--- a/services/inputflinger/tests/FakePointerController.h
+++ b/services/inputflinger/tests/FakePointerController.h
@@ -45,7 +45,8 @@
void setDisplayViewport(const DisplayViewport& viewport) override;
void updatePointerIcon(PointerIconStyle iconId) override;
void setCustomPointerIcon(const SpriteIcon& icon) override;
- void setSkipScreenshot(ui::LogicalDisplayId displayId, bool skip) override;
+ void setSkipScreenshotFlagForDisplay(ui::LogicalDisplayId displayId) override;
+ void clearSkipScreenshotFlags() override;
void fade(Transition) override;
void assertViewportSet(ui::LogicalDisplayId displayId);
@@ -56,7 +57,10 @@
void assertPointerIconNotSet();
void assertCustomPointerIconSet(PointerIconStyle iconId);
void assertCustomPointerIconNotSet();
- void assertIsHiddenOnMirroredDisplays(ui::LogicalDisplayId displayId, bool isHidden);
+ void assertIsSkipScreenshotFlagSet(ui::LogicalDisplayId displayId);
+ void assertIsSkipScreenshotFlagNotSet(ui::LogicalDisplayId displayId);
+ void assertSkipScreenshotFlagChanged();
+ void assertSkipScreenshotFlagNotChanged();
bool isPointerShown();
private:
@@ -80,6 +84,7 @@
std::map<ui::LogicalDisplayId, std::vector<int32_t>> mSpotsByDisplay;
std::unordered_set<ui::LogicalDisplayId> mDisplaysToSkipScreenshot;
+ bool mDisplaysToSkipScreenshotFlagChanged{false};
};
} // namespace android
diff --git a/services/inputflinger/tests/HardwareStateConverter_test.cpp b/services/inputflinger/tests/HardwareStateConverter_test.cpp
index ff9bd9e..34c81fc 100644
--- a/services/inputflinger/tests/HardwareStateConverter_test.cpp
+++ b/services/inputflinger/tests/HardwareStateConverter_test.cpp
@@ -81,7 +81,7 @@
event.type = type;
event.code = code;
event.value = value;
- std::optional<SelfContainedHardwareState> schs = mConverter->processRawEvent(&event);
+ std::optional<SelfContainedHardwareState> schs = mConverter->processRawEvent(event);
EXPECT_FALSE(schs.has_value());
}
@@ -93,7 +93,7 @@
event.type = EV_SYN;
event.code = SYN_REPORT;
event.value = 0;
- return mConverter->processRawEvent(&event);
+ return mConverter->processRawEvent(event);
}
std::shared_ptr<FakeEventHub> mFakeEventHub;
diff --git a/services/inputflinger/tests/InputMapperTest.cpp b/services/inputflinger/tests/InputMapperTest.cpp
index fea1349..b5c9232 100644
--- a/services/inputflinger/tests/InputMapperTest.cpp
+++ b/services/inputflinger/tests/InputMapperTest.cpp
@@ -104,7 +104,7 @@
event.type = type;
event.code = code;
event.value = value;
- return mMapper->process(&event);
+ return mMapper->process(event);
}
const char* InputMapperTest::DEVICE_NAME = "device";
@@ -195,7 +195,7 @@
event.type = type;
event.code = code;
event.value = value;
- std::list<NotifyArgs> processArgList = mapper.process(&event);
+ std::list<NotifyArgs> processArgList = mapper.process(event);
for (const NotifyArgs& args : processArgList) {
mFakeListener->notify(args);
}
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 07fa59f..8989fce 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -309,9 +309,9 @@
return {};
}
- std::list<NotifyArgs> process(const RawEvent* rawEvent) override {
+ std::list<NotifyArgs> process(const RawEvent& rawEvent) override {
std::scoped_lock<std::mutex> lock(mLock);
- mLastEvent = *rawEvent;
+ mLastEvent = rawEvent;
mProcessWasCalled = true;
mStateChangedCondition.notify_all();
return mProcessResult;
@@ -10582,24 +10582,24 @@
ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
}
-TEST_F(LightControllerTest, PlayerIdLight) {
+TEST_F(LightControllerTest, SonyPlayerIdLight) {
RawLightInfo info1 = {.id = 1,
- .name = "player1",
+ .name = "sony1",
.maxBrightness = 255,
.flags = InputLightClass::BRIGHTNESS,
.path = ""};
RawLightInfo info2 = {.id = 2,
- .name = "player2",
+ .name = "sony2",
.maxBrightness = 255,
.flags = InputLightClass::BRIGHTNESS,
.path = ""};
RawLightInfo info3 = {.id = 3,
- .name = "player3",
+ .name = "sony3",
.maxBrightness = 255,
.flags = InputLightClass::BRIGHTNESS,
.path = ""};
RawLightInfo info4 = {.id = 4,
- .name = "player4",
+ .name = "sony4",
.maxBrightness = 255,
.flags = InputLightClass::BRIGHTNESS,
.path = ""};
@@ -10613,6 +10613,49 @@
controller.populateDeviceInfo(&info);
std::vector<InputDeviceLightInfo> lights = info.getLights();
ASSERT_EQ(1U, lights.size());
+ ASSERT_STREQ("sony", lights[0].name.c_str());
+ ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type);
+ ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
+ ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
+
+ ASSERT_FALSE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
+ ASSERT_TRUE(controller.setLightPlayerId(lights[0].id, LIGHT_PLAYER_ID));
+ ASSERT_EQ(controller.getLightPlayerId(lights[0].id).value_or(-1), LIGHT_PLAYER_ID);
+ ASSERT_STREQ("sony", lights[0].name.c_str());
+}
+
+TEST_F(LightControllerTest, PlayerIdLight) {
+ RawLightInfo info1 = {.id = 1,
+ .name = "player-1",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS,
+ .path = ""};
+ RawLightInfo info2 = {.id = 2,
+ .name = "player-2",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS,
+ .path = ""};
+ RawLightInfo info3 = {.id = 3,
+ .name = "player-3",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS,
+ .path = ""};
+ RawLightInfo info4 = {.id = 4,
+ .name = "player-4",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS,
+ .path = ""};
+ mFakeEventHub->addRawLightInfo(info1.id, std::move(info1));
+ mFakeEventHub->addRawLightInfo(info2.id, std::move(info2));
+ mFakeEventHub->addRawLightInfo(info3.id, std::move(info3));
+ mFakeEventHub->addRawLightInfo(info4.id, std::move(info4));
+
+ PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
+ InputDeviceInfo info;
+ controller.populateDeviceInfo(&info);
+ std::vector<InputDeviceLightInfo> lights = info.getLights();
+ ASSERT_EQ(1U, lights.size());
+ ASSERT_STREQ("player", lights[0].name.c_str());
ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type);
ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
diff --git a/services/inputflinger/tests/InterfaceMocks.h b/services/inputflinger/tests/InterfaceMocks.h
index 2d4e917..4441724 100644
--- a/services/inputflinger/tests/InterfaceMocks.h
+++ b/services/inputflinger/tests/InterfaceMocks.h
@@ -27,7 +27,9 @@
#include <EventHub.h>
#include <InputReaderBase.h>
+#include <InputReaderContext.h>
#include <NotifyArgs.h>
+#include <PointerChoreographerPolicyInterface.h>
#include <StylusState.h>
#include <VibrationElement.h>
#include <android-base/logging.h>
@@ -178,4 +180,12 @@
MOCK_METHOD(void, sysfsNodeChanged, (const std::string& sysfsNodePath), (override));
};
+class MockPointerChoreographerPolicyInterface : public PointerChoreographerPolicyInterface {
+public:
+ MOCK_METHOD(std::shared_ptr<PointerControllerInterface>, createPointerController,
+ (PointerControllerInterface::ControllerType), (override));
+ MOCK_METHOD(void, notifyPointerDisplayIdChanged,
+ (ui::LogicalDisplayId displayId, const FloatPoint& position), (override));
+};
+
} // namespace android
diff --git a/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp b/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp
index 5e67506..b441a23 100644
--- a/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp
+++ b/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp
@@ -38,7 +38,7 @@
event.type = type;
event.code = code;
event.value = value;
- mMotionAccumulator.process(&event);
+ mMotionAccumulator.process(event);
}
};
diff --git a/services/inputflinger/tests/PointerChoreographer_test.cpp b/services/inputflinger/tests/PointerChoreographer_test.cpp
index 1689b33..3f2d6ec 100644
--- a/services/inputflinger/tests/PointerChoreographer_test.cpp
+++ b/services/inputflinger/tests/PointerChoreographer_test.cpp
@@ -22,6 +22,7 @@
#include <vector>
#include "FakePointerController.h"
+#include "InterfaceMocks.h"
#include "NotifyArgsBuilders.h"
#include "TestEventMatchers.h"
#include "TestInputListener.h"
@@ -89,10 +90,55 @@
// --- PointerChoreographerTest ---
-class PointerChoreographerTest : public testing::Test, public PointerChoreographerPolicyInterface {
+class TestPointerChoreographer : public PointerChoreographer {
+public:
+ TestPointerChoreographer(InputListenerInterface& inputListener,
+ PointerChoreographerPolicyInterface& policy,
+ sp<gui::WindowInfosListener>& windowInfoListener,
+ const std::vector<gui::WindowInfo>& mInitialWindowInfos);
+};
+
+TestPointerChoreographer::TestPointerChoreographer(
+ InputListenerInterface& inputListener, PointerChoreographerPolicyInterface& policy,
+ sp<gui::WindowInfosListener>& windowInfoListener,
+ const std::vector<gui::WindowInfo>& mInitialWindowInfos)
+ : PointerChoreographer(
+ inputListener, policy,
+ [&windowInfoListener,
+ &mInitialWindowInfos](const sp<android::gui::WindowInfosListener>& listener) {
+ windowInfoListener = listener;
+ return mInitialWindowInfos;
+ },
+ [&windowInfoListener](const sp<android::gui::WindowInfosListener>& listener) {
+ windowInfoListener = nullptr;
+ }) {}
+
+class PointerChoreographerTest : public testing::Test {
protected:
TestInputListener mTestListener;
- PointerChoreographer mChoreographer{mTestListener, *this};
+ sp<gui::WindowInfosListener> mRegisteredWindowInfoListener;
+ std::vector<gui::WindowInfo> mInjectedInitialWindowInfos;
+ testing::NiceMock<MockPointerChoreographerPolicyInterface> mMockPolicy;
+ TestPointerChoreographer mChoreographer{mTestListener, mMockPolicy,
+ mRegisteredWindowInfoListener,
+ mInjectedInitialWindowInfos};
+
+ void SetUp() override {
+ // flag overrides
+ input_flags::hide_pointer_indicators_for_secure_windows(true);
+
+ ON_CALL(mMockPolicy, createPointerController).WillByDefault([this](ControllerType type) {
+ std::shared_ptr<FakePointerController> pc = std::make_shared<FakePointerController>();
+ EXPECT_FALSE(pc->isPointerShown());
+ mCreatedControllers.emplace_back(type, pc);
+ return pc;
+ });
+
+ ON_CALL(mMockPolicy, notifyPointerDisplayIdChanged)
+ .WillByDefault([this](ui::LogicalDisplayId displayId, const FloatPoint& position) {
+ mPointerDisplayIdNotified = displayId;
+ });
+ }
std::shared_ptr<FakePointerController> assertPointerControllerCreated(
ControllerType expectedType) {
@@ -131,23 +177,20 @@
void assertPointerDisplayIdNotNotified() { ASSERT_EQ(std::nullopt, mPointerDisplayIdNotified); }
+ void assertWindowInfosListenerRegistered() {
+ ASSERT_NE(nullptr, mRegisteredWindowInfoListener)
+ << "WindowInfosListener was not registered";
+ }
+
+ void assertWindowInfosListenerNotRegistered() {
+ ASSERT_EQ(nullptr, mRegisteredWindowInfoListener)
+ << "WindowInfosListener was not unregistered";
+ }
+
private:
std::deque<std::pair<ControllerType, std::shared_ptr<FakePointerController>>>
mCreatedControllers;
std::optional<ui::LogicalDisplayId> mPointerDisplayIdNotified;
-
- std::shared_ptr<PointerControllerInterface> createPointerController(
- ControllerType type) override {
- std::shared_ptr<FakePointerController> pc = std::make_shared<FakePointerController>();
- EXPECT_FALSE(pc->isPointerShown());
- mCreatedControllers.emplace_back(type, pc);
- return pc;
- }
-
- void notifyPointerDisplayIdChanged(ui::LogicalDisplayId displayId,
- const FloatPoint& position) override {
- mPointerDisplayIdNotified = displayId;
- }
};
TEST_F(PointerChoreographerTest, ForwardsArgsToInnerListener) {
@@ -1636,74 +1679,252 @@
firstMousePc->assertPointerIconNotSet();
}
-TEST_F_WITH_FLAGS(PointerChoreographerTest, HidesTouchSpotsOnMirroredDisplaysForSecureWindow,
- REQUIRES_FLAGS_ENABLED(
- ACONFIG_FLAG(input_flags, hide_pointer_indicators_for_secure_windows))) {
- // Add a touch device and enable show touches.
- mChoreographer.notifyInputDevicesChanged(
- {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID)}});
- mChoreographer.setShowTouchesEnabled(true);
+using SkipPointerScreenshotForPrivacySensitiveDisplaysFixtureParam =
+ std::tuple<std::string_view /*name*/, uint32_t /*source*/, ControllerType, PointerBuilder,
+ std::function<void(PointerChoreographer&)>, int32_t /*action*/>;
- // Emit touch events to create PointerController
- mChoreographer.notifyMotion(
- MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
- .pointer(FIRST_TOUCH_POINTER)
- .deviceId(DEVICE_ID)
- .displayId(DISPLAY_ID)
- .build());
+class SkipPointerScreenshotForPrivacySensitiveDisplaysTestFixture
+ : public PointerChoreographerTest,
+ public ::testing::WithParamInterface<
+ SkipPointerScreenshotForPrivacySensitiveDisplaysFixtureParam> {
+protected:
+ void initializePointerDevice(const PointerBuilder& pointerBuilder, const uint32_t source,
+ const std::function<void(PointerChoreographer&)> onControllerInit,
+ const int32_t action) {
+ mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- // By default touch indicators should not be hidden
- auto pc = assertPointerControllerCreated(ControllerType::TOUCH);
- pc->assertIsHiddenOnMirroredDisplays(DISPLAY_ID, /*isHidden=*/false);
- pc->assertIsHiddenOnMirroredDisplays(ANOTHER_DISPLAY_ID, /*isHidden=*/false);
+ // Add appropriate pointer device
+ mChoreographer.notifyInputDevicesChanged(
+ {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, source, DISPLAY_ID)}});
+ onControllerInit(mChoreographer);
- // adding secure window on display should set flag to hide pointer indicators on corresponding
- // mirrored display
+ // Emit input events to create PointerController
+ mChoreographer.notifyMotion(MotionArgsBuilder(action, source)
+ .pointer(pointerBuilder)
+ .deviceId(DEVICE_ID)
+ .displayId(DISPLAY_ID)
+ .build());
+ }
+};
+
+INSTANTIATE_TEST_SUITE_P(
+ PointerChoreographerTest, SkipPointerScreenshotForPrivacySensitiveDisplaysTestFixture,
+ ::testing::Values(
+ std::make_tuple(
+ "TouchSpots", AINPUT_SOURCE_TOUCHSCREEN, ControllerType::TOUCH,
+ FIRST_TOUCH_POINTER,
+ [](PointerChoreographer& pc) { pc.setShowTouchesEnabled(true); },
+ AMOTION_EVENT_ACTION_DOWN),
+ std::make_tuple(
+ "Mouse", AINPUT_SOURCE_MOUSE, ControllerType::MOUSE, MOUSE_POINTER,
+ [](PointerChoreographer& pc) {}, AMOTION_EVENT_ACTION_DOWN),
+ std::make_tuple(
+ "Stylus", AINPUT_SOURCE_STYLUS, ControllerType::STYLUS, STYLUS_POINTER,
+ [](PointerChoreographer& pc) { pc.setStylusPointerIconEnabled(true); },
+ AMOTION_EVENT_ACTION_HOVER_ENTER),
+ std::make_tuple(
+ "DrawingTablet", AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS,
+ ControllerType::MOUSE, STYLUS_POINTER, [](PointerChoreographer& pc) {},
+ AMOTION_EVENT_ACTION_HOVER_ENTER)),
+ [](const testing::TestParamInfo<
+ SkipPointerScreenshotForPrivacySensitiveDisplaysFixtureParam>& p) {
+ return std::string{std::get<0>(p.param)};
+ });
+
+TEST_P(SkipPointerScreenshotForPrivacySensitiveDisplaysTestFixture,
+ WindowInfosListenerIsOnlyRegisteredWhenRequired) {
+ const auto& [name, source, controllerType, pointerBuilder, onControllerInit, action] =
+ GetParam();
+ assertWindowInfosListenerNotRegistered();
+
+ // Listener should registered when a pointer device is added
+ initializePointerDevice(pointerBuilder, source, onControllerInit, action);
+ assertWindowInfosListenerRegistered();
+
+ mChoreographer.notifyInputDevicesChanged({});
+ assertWindowInfosListenerNotRegistered();
+}
+
+TEST_P(SkipPointerScreenshotForPrivacySensitiveDisplaysTestFixture,
+ InitialDisplayInfoIsPopulatedForListener) {
+ const auto& [name, source, controllerType, pointerBuilder, onControllerInit, action] =
+ GetParam();
+ // listener should not be registered if there is no pointer device
+ assertWindowInfosListenerNotRegistered();
+
gui::WindowInfo windowInfo;
windowInfo.displayId = DISPLAY_ID;
windowInfo.inputConfig |= gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY;
- mChoreographer.onWindowInfosChanged({windowInfo});
- pc->assertIsHiddenOnMirroredDisplays(DISPLAY_ID, /*isHidden=*/true);
- pc->assertIsHiddenOnMirroredDisplays(ANOTHER_DISPLAY_ID, /*isHidden=*/false);
+ mInjectedInitialWindowInfos = {windowInfo};
- // removing the secure window should reset the state
- windowInfo.inputConfig.clear(gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY);
- mChoreographer.onWindowInfosChanged({windowInfo});
- pc->assertIsHiddenOnMirroredDisplays(DISPLAY_ID, /*isHidden=*/false);
- pc->assertIsHiddenOnMirroredDisplays(ANOTHER_DISPLAY_ID, /*isHidden=*/false);
+ initializePointerDevice(pointerBuilder, source, onControllerInit, action);
+ assertWindowInfosListenerRegistered();
+
+ // Pointer indicators should be hidden based on the initial display info
+ auto pc = assertPointerControllerCreated(controllerType);
+ pc->assertIsSkipScreenshotFlagSet(DISPLAY_ID);
+ pc->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID);
+
+ // un-marking the privacy sensitive display should reset the state
+ windowInfo.inputConfig.clear();
+ gui::DisplayInfo displayInfo;
+ displayInfo.displayId = DISPLAY_ID;
+ mRegisteredWindowInfoListener
+ ->onWindowInfosChanged(/*windowInfosUpdate=*/
+ {{windowInfo}, {displayInfo}, /*vsyncId=*/0, /*timestamp=*/0});
+
+ pc->assertIsSkipScreenshotFlagNotSet(DISPLAY_ID);
+ pc->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID);
}
-TEST_F_WITH_FLAGS(PointerChoreographerTest,
- DoesNotHidesTouchSpotsOnMirroredDisplaysForInvisibleWindow,
- REQUIRES_FLAGS_ENABLED(
- ACONFIG_FLAG(input_flags, hide_pointer_indicators_for_secure_windows))) {
- // Add a touch device and enable show touches.
- mChoreographer.notifyInputDevicesChanged(
- {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID)}});
- mChoreographer.setShowTouchesEnabled(true);
+TEST_P(SkipPointerScreenshotForPrivacySensitiveDisplaysTestFixture,
+ SkipsPointerScreenshotForPrivacySensitiveWindows) {
+ const auto& [name, source, controllerType, pointerBuilder, onControllerInit, action] =
+ GetParam();
+ initializePointerDevice(pointerBuilder, source, onControllerInit, action);
- // Emit touch events to create PointerController
- mChoreographer.notifyMotion(
- MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
- .pointer(FIRST_TOUCH_POINTER)
- .deviceId(DEVICE_ID)
- .displayId(DISPLAY_ID)
- .build());
+ // By default pointer indicators should not be hidden
+ auto pc = assertPointerControllerCreated(controllerType);
+ pc->assertIsSkipScreenshotFlagNotSet(DISPLAY_ID);
+ pc->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID);
- // By default touch indicators should not be hidden
- auto pc = assertPointerControllerCreated(ControllerType::TOUCH);
- pc->assertIsHiddenOnMirroredDisplays(DISPLAY_ID, /*isHidden=*/false);
- pc->assertIsHiddenOnMirroredDisplays(ANOTHER_DISPLAY_ID, /*isHidden=*/false);
+ // marking a display privacy sensitive should set flag to hide pointer indicators on the
+ // display screenshot
+ gui::WindowInfo windowInfo;
+ windowInfo.displayId = DISPLAY_ID;
+ windowInfo.inputConfig |= gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY;
+ gui::DisplayInfo displayInfo;
+ displayInfo.displayId = DISPLAY_ID;
+ assertWindowInfosListenerRegistered();
+ mRegisteredWindowInfoListener
+ ->onWindowInfosChanged(/*windowInfosUpdate=*/
+ {{windowInfo}, {displayInfo}, /*vsyncId=*/0, /*timestamp=*/0});
- // adding secure but hidden window on display should still not set flag to hide pointer
- // indicators
+ pc->assertIsSkipScreenshotFlagSet(DISPLAY_ID);
+ pc->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID);
+
+ // un-marking the privacy sensitive display should reset the state
+ windowInfo.inputConfig.clear();
+ mRegisteredWindowInfoListener
+ ->onWindowInfosChanged(/*windowInfosUpdate=*/
+ {{windowInfo}, {displayInfo}, /*vsyncId=*/0, /*timestamp=*/0});
+
+ pc->assertIsSkipScreenshotFlagNotSet(DISPLAY_ID);
+ pc->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID);
+}
+
+TEST_P(SkipPointerScreenshotForPrivacySensitiveDisplaysTestFixture,
+ DoesNotSkipPointerScreenshotForHiddenPrivacySensitiveWindows) {
+ const auto& [name, source, controllerType, pointerBuilder, onControllerInit, action] =
+ GetParam();
+ initializePointerDevice(pointerBuilder, source, onControllerInit, action);
+
+ // By default pointer indicators should not be hidden
+ auto pc = assertPointerControllerCreated(controllerType);
+ pc->assertIsSkipScreenshotFlagNotSet(DISPLAY_ID);
+ pc->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID);
+
gui::WindowInfo windowInfo;
windowInfo.displayId = DISPLAY_ID;
windowInfo.inputConfig |= gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY;
windowInfo.inputConfig |= gui::WindowInfo::InputConfig::NOT_VISIBLE;
- mChoreographer.onWindowInfosChanged({windowInfo});
- pc->assertIsHiddenOnMirroredDisplays(DISPLAY_ID, /*isHidden=*/false);
- pc->assertIsHiddenOnMirroredDisplays(ANOTHER_DISPLAY_ID, /*isHidden=*/false);
+ gui::DisplayInfo displayInfo;
+ displayInfo.displayId = DISPLAY_ID;
+ assertWindowInfosListenerRegistered();
+ mRegisteredWindowInfoListener
+ ->onWindowInfosChanged(/*windowInfosUpdate=*/
+ {{windowInfo}, {displayInfo}, /*vsyncId=*/0, /*timestamp=*/0});
+
+ pc->assertIsSkipScreenshotFlagNotSet(DISPLAY_ID);
+ pc->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID);
+}
+
+TEST_P(SkipPointerScreenshotForPrivacySensitiveDisplaysTestFixture,
+ DoesNotUpdateControllerForUnchangedPrivacySensitiveWindows) {
+ const auto& [name, source, controllerType, pointerBuilder, onControllerInit, action] =
+ GetParam();
+ initializePointerDevice(pointerBuilder, source, onControllerInit, action);
+
+ auto pc = assertPointerControllerCreated(controllerType);
+ gui::WindowInfo windowInfo;
+ windowInfo.displayId = DISPLAY_ID;
+ windowInfo.inputConfig |= gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY;
+ gui::DisplayInfo displayInfo;
+ displayInfo.displayId = DISPLAY_ID;
+ assertWindowInfosListenerRegistered();
+ mRegisteredWindowInfoListener
+ ->onWindowInfosChanged(/*windowInfosUpdate=*/
+ {{windowInfo}, {displayInfo}, /*vsyncId=*/0, /*timestamp=*/0});
+
+ gui::WindowInfo windowInfo2 = windowInfo;
+ windowInfo2.inputConfig.clear();
+ pc->assertSkipScreenshotFlagChanged();
+
+ // controller should not be updated if there are no changes in privacy sensitive windows
+ mRegisteredWindowInfoListener->onWindowInfosChanged(/*windowInfosUpdate=*/
+ {{windowInfo, windowInfo2},
+ {displayInfo},
+ /*vsyncId=*/0,
+ /*timestamp=*/0});
+ pc->assertSkipScreenshotFlagNotChanged();
+}
+
+TEST_F_WITH_FLAGS(
+ PointerChoreographerTest, HidesPointerScreenshotForExistingPrivacySensitiveWindows,
+ REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
+ hide_pointer_indicators_for_secure_windows))) {
+ mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
+
+ // Add a first mouse device
+ mChoreographer.notifyInputDevicesChanged(
+ {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, DISPLAY_ID)}});
+
+ mChoreographer.notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
+ .pointer(MOUSE_POINTER)
+ .deviceId(DEVICE_ID)
+ .displayId(DISPLAY_ID)
+ .build());
+
+ gui::WindowInfo windowInfo;
+ windowInfo.displayId = DISPLAY_ID;
+ windowInfo.inputConfig |= gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY;
+ gui::DisplayInfo displayInfo;
+ displayInfo.displayId = DISPLAY_ID;
+ assertWindowInfosListenerRegistered();
+ mRegisteredWindowInfoListener
+ ->onWindowInfosChanged(/*windowInfosUpdate=*/
+ {{windowInfo}, {displayInfo}, /*vsyncId=*/0, /*timestamp=*/0});
+
+ auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
+ pc->assertIsSkipScreenshotFlagSet(DISPLAY_ID);
+ pc->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID);
+
+ // Add a second touch device and controller
+ mChoreographer.notifyInputDevicesChanged(
+ {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID)}});
+ mChoreographer.setShowTouchesEnabled(true);
+ mChoreographer.notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(FIRST_TOUCH_POINTER)
+ .deviceId(DEVICE_ID)
+ .displayId(DISPLAY_ID)
+ .build());
+
+ // Pointer indicators should be hidden for this controller by default
+ auto pc2 = assertPointerControllerCreated(ControllerType::TOUCH);
+ pc->assertIsSkipScreenshotFlagSet(DISPLAY_ID);
+ pc->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID);
+
+ // un-marking the privacy sensitive display should reset the state
+ windowInfo.inputConfig.clear();
+ mRegisteredWindowInfoListener
+ ->onWindowInfosChanged(/*windowInfosUpdate=*/
+ {{windowInfo}, {displayInfo}, /*vsyncId=*/0, /*timestamp=*/0});
+
+ pc->assertIsSkipScreenshotFlagNotSet(DISPLAY_ID);
+ pc->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID);
+ pc2->assertIsSkipScreenshotFlagNotSet(DISPLAY_ID);
+ pc2->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID);
}
TEST_P(StylusTestFixture, SetsPointerIconForStylus) {
@@ -2073,4 +2294,41 @@
assertPointerControllerRemoved(pc);
}
+class PointerChoreographerWindowInfoListenerTest : public testing::Test {};
+
+TEST_F_WITH_FLAGS(
+ PointerChoreographerWindowInfoListenerTest,
+ doesNotCrashIfListenerCalledAfterPointerChoreographerDestroyed,
+ REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
+ hide_pointer_indicators_for_secure_windows))) {
+ sp<android::gui::WindowInfosListener> registeredListener;
+ sp<android::gui::WindowInfosListener> localListenerCopy;
+ {
+ testing::NiceMock<MockPointerChoreographerPolicyInterface> mockPolicy;
+ EXPECT_CALL(mockPolicy, createPointerController(ControllerType::MOUSE))
+ .WillOnce(testing::Return(std::make_shared<FakePointerController>()));
+ TestInputListener testListener;
+ std::vector<gui::WindowInfo> injectedInitialWindowInfos;
+ TestPointerChoreographer testChoreographer{testListener, mockPolicy, registeredListener,
+ injectedInitialWindowInfos};
+ testChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
+
+ // Add mouse to create controller and listener
+ testChoreographer.notifyInputDevicesChanged(
+ {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, DISPLAY_ID)}});
+
+ ASSERT_NE(nullptr, registeredListener) << "WindowInfosListener was not registered";
+ localListenerCopy = registeredListener;
+ }
+ ASSERT_EQ(nullptr, registeredListener) << "WindowInfosListener was not unregistered";
+
+ gui::WindowInfo windowInfo;
+ windowInfo.displayId = DISPLAY_ID;
+ windowInfo.inputConfig |= gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY;
+ gui::DisplayInfo displayInfo;
+ displayInfo.displayId = DISPLAY_ID;
+ localListenerCopy->onWindowInfosChanged(
+ /*windowInfosUpdate=*/{{windowInfo}, {displayInfo}, /*vsyncId=*/0, /*timestamp=*/0});
+}
+
} // namespace android
diff --git a/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp
index af20a27..8361517 100644
--- a/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp
@@ -81,7 +81,7 @@
mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), policyConfig,
InputReaderConfiguration::Change(0));
RawEvent rawEvent = getFuzzedRawEvent(*fdp);
- unused += mapper.process(&rawEvent);
+ unused += mapper.process(rawEvent);
},
[&]() -> void {
std::list<NotifyArgs> unused = mapper.reset(fdp->ConsumeIntegral<nsecs_t>());
diff --git a/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp
index 3b3f8d2..9e02502 100644
--- a/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp
@@ -79,7 +79,7 @@
},
[&]() -> void {
RawEvent rawEvent = getFuzzedRawEvent(*fdp);
- std::list<NotifyArgs> unused = mapper.process(&rawEvent);
+ std::list<NotifyArgs> unused = mapper.process(rawEvent);
},
[&]() -> void {
mapper.getKeyCodeState(fdp->ConsumeIntegral<uint32_t>(),
diff --git a/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp
index d3f6690..f29577d 100644
--- a/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp
@@ -100,7 +100,7 @@
},
[&]() -> void {
RawEvent rawEvent = getFuzzedRawEvent(*fdp);
- std::list<NotifyArgs> unused = mapper.process(&rawEvent);
+ std::list<NotifyArgs> unused = mapper.process(rawEvent);
},
[&]() -> void {
mapper.getKeyCodeState(fdp->ConsumeIntegral<uint32_t>(),
diff --git a/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp
index ac2030a..a42d447 100644
--- a/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp
@@ -44,7 +44,7 @@
[&]() -> void { mapper.getSources(); },
[&]() -> void {
RawEvent rawEvent = getFuzzedRawEvent(*fdp);
- std::list<NotifyArgs> unused = mapper.process(&rawEvent);
+ std::list<NotifyArgs> unused = mapper.process(rawEvent);
},
[&]() -> void {
mapper.getSwitchState(fdp->ConsumeIntegral<uint32_t>(),
diff --git a/services/inputflinger/tests/fuzzers/TouchpadInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/TouchpadInputFuzzer.cpp
index 643e8b9..c620032 100644
--- a/services/inputflinger/tests/fuzzers/TouchpadInputFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/TouchpadInputFuzzer.cpp
@@ -176,7 +176,7 @@
},
[&]() -> void {
RawEvent event = getFuzzedRawEvent(*fdp);
- std::list<NotifyArgs> unused = mapper.process(&event);
+ std::list<NotifyArgs> unused = mapper.process(event);
},
})();
}
diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp
index afaf0ae..f4b0265 100644
--- a/services/sensorservice/Android.bp
+++ b/services/sensorservice/Android.bp
@@ -84,6 +84,7 @@
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
"server_configurable_flags",
+ "libaconfig_storage_read_api_cc",
],
static_libs: [
diff --git a/services/sensorservice/OWNERS b/services/sensorservice/OWNERS
index 90c2330..7347ac7 100644
--- a/services/sensorservice/OWNERS
+++ b/services/sensorservice/OWNERS
@@ -1,3 +1 @@
-arthuri@google.com
bduddie@google.com
-stange@google.com
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 70ca702..31b7f88 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -1273,7 +1273,10 @@
} else {
int handle = mSensorEventBuffer[i].dynamic_sensor_meta.handle;
disconnectDynamicSensor(handle, activeConnections);
- device.cleanupDisconnectedDynamicSensor(handle);
+ if (sensorservice_flags::
+ sensor_service_clear_dynamic_sensor_data_at_the_end()) {
+ device.cleanupDisconnectedDynamicSensor(handle);
+ }
}
}
}
diff --git a/services/sensorservice/senserservice_flags.aconfig b/services/sensorservice/senserservice_flags.aconfig
index 5b499a8..7abfbaa 100644
--- a/services/sensorservice/senserservice_flags.aconfig
+++ b/services/sensorservice/senserservice_flags.aconfig
@@ -27,4 +27,4 @@
namespace: "sensors"
description: "When this flag is enabled, sensor service will only erase dynamic sensor data at the end of the threadLoop to prevent race condition."
bug: "329020894"
-}
\ No newline at end of file
+}
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 8ca796e..1b6c598 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -85,6 +85,7 @@
"libui",
"libutils",
"libSurfaceFlingerProp",
+ "libaconfig_storage_read_api_cc"
],
static_libs: [
"iinputflinger_aidl_lib_static",
@@ -98,6 +99,7 @@
"libscheduler",
"libserviceutils",
"libshaders",
+ "libsurfaceflingerflags",
"libtimestats",
"libtonemap",
],
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index d420838..191d475 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -306,7 +306,7 @@
virtual void finishFrame(GpuCompositionResult&&) = 0;
virtual std::optional<base::unique_fd> composeSurfaces(
const Region&, std::shared_ptr<renderengine::ExternalTexture>, base::unique_fd&) = 0;
- virtual void presentFrameAndReleaseLayers() = 0;
+ virtual void presentFrameAndReleaseLayers(bool flushEvenWhenDisabled) = 0;
virtual void renderCachedSets(const CompositionRefreshArgs&) = 0;
virtual bool chooseCompositionStrategy(
std::optional<android::HWComposer::DeviceRequestedChanges>*) = 0;
@@ -314,6 +314,7 @@
const std::optional<android::HWComposer::DeviceRequestedChanges>& changes) = 0;
virtual bool getSkipColorTransform() const = 0;
virtual FrameFences presentFrame() = 0;
+ virtual void executeCommands() = 0;
virtual std::vector<LayerFE::LayerSettings> generateClientCompositionRequests(
bool supportsProtectedContent, ui::Dataspace outputDataspace,
std::vector<LayerFE*> &outLayerRef) = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
index d87968f..d1eff24 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
@@ -60,6 +60,7 @@
void applyCompositionStrategy(const std::optional<DeviceRequestedChanges>&) override;
bool getSkipColorTransform() const override;
compositionengine::Output::FrameFences presentFrame() override;
+ void executeCommands() override;
void setExpensiveRenderingExpected(bool) override;
void finishFrame(GpuCompositionResult&&) override;
bool supportsOffloadPresent() const override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index adcbbb9..9990a74 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -104,7 +104,7 @@
std::optional<base::unique_fd> composeSurfaces(const Region&,
std::shared_ptr<renderengine::ExternalTexture>,
base::unique_fd&) override;
- void presentFrameAndReleaseLayers() override;
+ void presentFrameAndReleaseLayers(bool flushEvenWhenDisabled) override;
void renderCachedSets(const CompositionRefreshArgs&) override;
void cacheClientCompositionRequests(uint32_t) override;
bool canPredictCompositionStrategy(const CompositionRefreshArgs&) override;
@@ -123,7 +123,8 @@
virtual std::future<bool> chooseCompositionStrategyAsync(
std::optional<android::HWComposer::DeviceRequestedChanges>*);
virtual void resetCompositionStrategy();
- virtual ftl::Future<std::monostate> presentFrameAndReleaseLayersAsync();
+ virtual ftl::Future<std::monostate> presentFrameAndReleaseLayersAsync(
+ bool flushEvenWhenDisabled);
protected:
std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(const sp<LayerFE>&) const;
@@ -137,6 +138,7 @@
void applyCompositionStrategy(const std::optional<DeviceRequestedChanges>&) override{};
bool getSkipColorTransform() const override;
compositionengine::Output::FrameFences presentFrame() override;
+ void executeCommands() override {}
virtual renderengine::DisplaySettings generateClientCompositionDisplaySettings(
const std::shared_ptr<renderengine::ExternalTexture>& buffer) const;
std::vector<LayerFE::LayerSettings> generateClientCompositionRequests(
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index 3f3deae..d5bf2b5 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -121,9 +121,10 @@
base::unique_fd&));
MOCK_CONST_METHOD0(getSkipColorTransform, bool());
- MOCK_METHOD0(presentFrameAndReleaseLayers, void());
+ MOCK_METHOD(void, presentFrameAndReleaseLayers, (bool flushEvenWhenDisabled));
MOCK_METHOD1(renderCachedSets, void(const CompositionRefreshArgs&));
MOCK_METHOD0(presentFrame, compositionengine::Output::FrameFences());
+ MOCK_METHOD(void, executeCommands, ());
MOCK_METHOD3(generateClientCompositionRequests,
std::vector<LayerFE::LayerSettings>(bool, ui::Dataspace, std::vector<compositionengine::LayerFE*>&));
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index 83b1b68..c1617d7 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -361,6 +361,15 @@
static_cast<ui::PixelFormat>(clientTargetProperty.clientTargetProperty.pixelFormat));
}
+void Display::executeCommands() {
+ const auto halDisplayIdOpt = HalDisplayId::tryCast(mId);
+ if (mIsDisconnected || !halDisplayIdOpt) {
+ return;
+ }
+
+ getCompositionEngine().getHwComposer().executeCommands(*halDisplayIdOpt);
+}
+
compositionengine::Output::FrameFences Display::presentFrame() {
auto fences = impl::Output::presentFrame();
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 84f3f25..5b9a102 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -479,8 +479,9 @@
devOptRepaintFlash(refreshArgs);
finishFrame(std::move(result));
ftl::Future<std::monostate> future;
+ const bool flushEvenWhenDisabled = !refreshArgs.bufferIdsToUncache.empty();
if (mOffloadPresent) {
- future = presentFrameAndReleaseLayersAsync();
+ future = presentFrameAndReleaseLayersAsync(flushEvenWhenDisabled);
// Only offload for this frame. The next frame will determine whether it
// needs to be offloaded. Leave the HwcAsyncWorker in place. For one thing,
@@ -488,7 +489,7 @@
// we don't want to churn.
mOffloadPresent = false;
} else {
- presentFrameAndReleaseLayers();
+ presentFrameAndReleaseLayers(flushEvenWhenDisabled);
future = ftl::yield<std::monostate>({});
}
renderCachedSets(refreshArgs);
@@ -1100,9 +1101,9 @@
finishPrepareFrame();
}
-ftl::Future<std::monostate> Output::presentFrameAndReleaseLayersAsync() {
+ftl::Future<std::monostate> Output::presentFrameAndReleaseLayersAsync(bool flushEvenWhenDisabled) {
return ftl::Future<bool>(std::move(mHwComposerAsyncWorker->send([&]() {
- presentFrameAndReleaseLayers();
+ presentFrameAndReleaseLayers(flushEvenWhenDisabled);
return true;
})))
.then([](bool) { return std::monostate{}; });
@@ -1177,7 +1178,8 @@
}
}
- presentFrameAndReleaseLayers();
+ constexpr bool kFlushEvenWhenDisabled = false;
+ presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
std::this_thread::sleep_for(*refreshArgs.devOptFlashDirtyRegionsDelay);
@@ -1567,11 +1569,16 @@
return false;
}
-void Output::presentFrameAndReleaseLayers() {
+void Output::presentFrameAndReleaseLayers(bool flushEvenWhenDisabled) {
ATRACE_FORMAT("%s for %s", __func__, mNamePlusId.c_str());
ALOGV(__FUNCTION__);
if (!getState().isEnabled) {
+ if (flushEvenWhenDisabled && FlagManager::getInstance().flush_buffer_slots_to_uncache()) {
+ // Some commands, like clearing buffer slots, should still be executed
+ // even if the display is not enabled.
+ executeCommands();
+ }
return;
}
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index a95a5c6..39163ea 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -1067,8 +1067,8 @@
EXPECT_CALL(mHwComposer, presentAndGetReleaseFences(_, _));
EXPECT_CALL(*mDisplaySurface, onFrameCommitted());
-
- mDisplay->presentFrameAndReleaseLayers();
+ constexpr bool kFlushEvenWhenDisabled = false;
+ mDisplay->presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
}
} // namespace
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index 4612117..629d9f2 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -63,6 +63,7 @@
(override));
MOCK_METHOD2(presentAndGetReleaseFences,
status_t(HalDisplayId, std::optional<std::chrono::steady_clock::time_point>));
+ MOCK_METHOD(status_t, executeCommands, (HalDisplayId));
MOCK_METHOD2(setPowerMode, status_t(PhysicalDisplayId, hal::PowerMode));
MOCK_METHOD2(setActiveConfig, status_t(HalDisplayId, size_t));
MOCK_METHOD2(setColorTransform, status_t(HalDisplayId, const mat4&));
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 0dc3c9f..c34168d 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -2014,7 +2014,7 @@
MOCK_METHOD0(prepareFrameAsync, GpuCompositionResult());
MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&));
MOCK_METHOD1(finishFrame, void(GpuCompositionResult&&));
- MOCK_METHOD0(presentFrameAndReleaseLayers, void());
+ MOCK_METHOD(void, presentFrameAndReleaseLayers, (bool flushEvenWhenDisabled), (override));
MOCK_METHOD1(renderCachedSets, void(const compositionengine::CompositionRefreshArgs&));
MOCK_METHOD1(canPredictCompositionStrategy, bool(const CompositionRefreshArgs&));
MOCK_METHOD(void, setHintSessionRequiresRenderEngine, (bool requiresRenderEngine),
@@ -2046,7 +2046,7 @@
EXPECT_CALL(mOutput, prepareFrame());
EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args)));
EXPECT_CALL(mOutput, finishFrame(_));
- EXPECT_CALL(mOutput, presentFrameAndReleaseLayers());
+ EXPECT_CALL(mOutput, presentFrameAndReleaseLayers(false));
EXPECT_CALL(mOutput, renderCachedSets(Ref(args)));
mOutput.present(args);
@@ -2067,7 +2067,7 @@
EXPECT_CALL(mOutput, prepareFrameAsync());
EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args)));
EXPECT_CALL(mOutput, finishFrame(_));
- EXPECT_CALL(mOutput, presentFrameAndReleaseLayers());
+ EXPECT_CALL(mOutput, presentFrameAndReleaseLayers(false));
EXPECT_CALL(mOutput, renderCachedSets(Ref(args)));
mOutput.present(args);
@@ -2913,7 +2913,7 @@
std::optional<base::unique_fd>(const Region&,
std::shared_ptr<renderengine::ExternalTexture>,
base::unique_fd&));
- MOCK_METHOD0(presentFrameAndReleaseLayers, void());
+ MOCK_METHOD(void, presentFrameAndReleaseLayers, (bool flushEvenWhenDisabled));
MOCK_METHOD0(prepareFrame, void());
MOCK_METHOD0(updateProtectedContentState, void());
MOCK_METHOD2(dequeueRenderBuffer,
@@ -2950,7 +2950,8 @@
mOutput.mState.isEnabled = false;
InSequence seq;
- EXPECT_CALL(mOutput, presentFrameAndReleaseLayers());
+ constexpr bool kFlushEvenWhenDisabled = false;
+ EXPECT_CALL(mOutput, presentFrameAndReleaseLayers(kFlushEvenWhenDisabled));
EXPECT_CALL(mOutput, prepareFrame());
mOutput.devOptRepaintFlash(mRefreshArgs);
@@ -2962,7 +2963,8 @@
InSequence seq;
EXPECT_CALL(mOutput, getDirtyRegion()).WillOnce(Return(kEmptyRegion));
- EXPECT_CALL(mOutput, presentFrameAndReleaseLayers());
+ constexpr bool kFlushEvenWhenDisabled = false;
+ EXPECT_CALL(mOutput, presentFrameAndReleaseLayers(kFlushEvenWhenDisabled));
EXPECT_CALL(mOutput, prepareFrame());
mOutput.devOptRepaintFlash(mRefreshArgs);
@@ -2978,7 +2980,8 @@
EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _));
EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion), _, _));
EXPECT_CALL(*mRenderSurface, queueBuffer(_, 1.f));
- EXPECT_CALL(mOutput, presentFrameAndReleaseLayers());
+ constexpr bool kFlushEvenWhenDisabled = false;
+ EXPECT_CALL(mOutput, presentFrameAndReleaseLayers(kFlushEvenWhenDisabled));
EXPECT_CALL(mOutput, prepareFrame());
mOutput.devOptRepaintFlash(mRefreshArgs);
@@ -2996,7 +2999,7 @@
std::optional<base::unique_fd>(const Region&,
std::shared_ptr<renderengine::ExternalTexture>,
base::unique_fd&));
- MOCK_METHOD0(presentFrameAndReleaseLayers, void());
+ MOCK_METHOD(void, presentFrameAndReleaseLayers, (bool flushEvenWhenDisabled), (override));
MOCK_METHOD0(updateProtectedContentState, void());
MOCK_METHOD2(dequeueRenderBuffer,
bool(base::unique_fd*, std::shared_ptr<renderengine::ExternalTexture>*));
@@ -3139,7 +3142,8 @@
struct OutputPartialMock : public OutputPartialMockBase {
// Sets up the helper functions called by the function under test to use
// mock implementations.
- MOCK_METHOD0(presentFrame, compositionengine::Output::FrameFences());
+ MOCK_METHOD(compositionengine::Output::FrameFences, presentFrame, ());
+ MOCK_METHOD(void, executeCommands, ());
};
struct Layer {
@@ -3177,9 +3181,67 @@
};
TEST_F(OutputPostFramebufferTest, ifNotEnabledDoesNothing) {
+ SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::flush_buffer_slots_to_uncache,
+ true);
mOutput.mState.isEnabled = false;
+ EXPECT_CALL(mOutput, executeCommands()).Times(0);
+ EXPECT_CALL(mOutput, presentFrame()).Times(0);
- mOutput.presentFrameAndReleaseLayers();
+ constexpr bool kFlushEvenWhenDisabled = false;
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
+}
+
+TEST_F(OutputPostFramebufferTest, ifNotEnabledExecutesCommandsIfFlush) {
+ SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::flush_buffer_slots_to_uncache,
+ true);
+ mOutput.mState.isEnabled = false;
+ EXPECT_CALL(mOutput, executeCommands());
+ EXPECT_CALL(mOutput, presentFrame()).Times(0);
+
+ constexpr bool kFlushEvenWhenDisabled = true;
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
+}
+
+TEST_F(OutputPostFramebufferTest, ifEnabledDoNotExecuteCommands) {
+ SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::flush_buffer_slots_to_uncache,
+ true);
+ mOutput.mState.isEnabled = true;
+
+ compositionengine::Output::FrameFences frameFences;
+
+ EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
+
+ // This should only be called for disabled outputs. This test's goal is to verify this line;
+ // the other expectations help satisfy the StrictMocks.
+ EXPECT_CALL(mOutput, executeCommands()).Times(0);
+
+ EXPECT_CALL(mOutput, presentFrame()).WillOnce(Return(frameFences));
+ EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
+
+ constexpr bool kFlushEvenWhenDisabled = true;
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
+}
+
+TEST_F(OutputPostFramebufferTest, ifEnabledDoNotExecuteCommands2) {
+ // Same test as ifEnabledDoNotExecuteCommands, but with this variable set to false.
+ constexpr bool kFlushEvenWhenDisabled = false;
+
+ SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::flush_buffer_slots_to_uncache,
+ true);
+ mOutput.mState.isEnabled = true;
+
+ compositionengine::Output::FrameFences frameFences;
+
+ EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
+
+ // This should only be called for disabled outputs. This test's goal is to verify this line;
+ // the other expectations help satisfy the StrictMocks.
+ EXPECT_CALL(mOutput, executeCommands()).Times(0);
+
+ EXPECT_CALL(mOutput, presentFrame()).WillOnce(Return(frameFences));
+ EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
+
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
}
TEST_F(OutputPostFramebufferTest, ifEnabledMustFlipThenPresentThenSendPresentCompleted) {
@@ -3197,7 +3259,8 @@
EXPECT_CALL(mOutput, presentFrame()).WillOnce(Return(frameFences));
EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
- mOutput.presentFrameAndReleaseLayers();
+ constexpr bool kFlushEvenWhenDisabled = true;
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
}
TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) {
@@ -3241,7 +3304,8 @@
EXPECT_EQ(FenceResult(layer3Fence), futureFenceResult.get());
});
- mOutput.presentFrameAndReleaseLayers();
+ constexpr bool kFlushEvenWhenDisabled = false;
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
}
TEST_F(OutputPostFramebufferTest, releaseFencesAreSetInLayerFE) {
@@ -3282,7 +3346,8 @@
EXPECT_EQ(FenceResult(layer3Fence), releaseFence);
});
- mOutput.presentFrameAndReleaseLayers();
+ constexpr bool kFlushEvenWhenDisabled = false;
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
}
TEST_F(OutputPostFramebufferTest, releaseFencesIncludeClientTargetAcquireFence) {
@@ -3308,7 +3373,8 @@
EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed).WillOnce(Return());
EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed).WillOnce(Return());
- mOutput.presentFrameAndReleaseLayers();
+ constexpr bool kFlushEvenWhenDisabled = false;
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
}
TEST_F(OutputPostFramebufferTest, setReleaseFencesIncludeClientTargetAcquireFence) {
@@ -3333,7 +3399,8 @@
EXPECT_CALL(*mLayer1.layerFE, setReleaseFence).WillOnce(Return());
EXPECT_CALL(*mLayer2.layerFE, setReleaseFence).WillOnce(Return());
EXPECT_CALL(*mLayer3.layerFE, setReleaseFence).WillOnce(Return());
- mOutput.presentFrameAndReleaseLayers();
+ constexpr bool kFlushEvenWhenDisabled = false;
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
}
TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) {
@@ -3381,7 +3448,8 @@
EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get());
});
- mOutput.presentFrameAndReleaseLayers();
+ constexpr bool kFlushEvenWhenDisabled = false;
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
// After the call the list of released layers should have been cleared.
EXPECT_TRUE(mOutput.getReleasedLayersForTest().empty());
@@ -3429,7 +3497,8 @@
EXPECT_EQ(FenceResult(presentFence), fenceResult);
});
- mOutput.presentFrameAndReleaseLayers();
+ constexpr bool kFlushEvenWhenDisabled = false;
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
// After the call the list of released layers should have been cleared.
EXPECT_TRUE(mOutput.getReleasedLayersForTest().empty());
@@ -5272,8 +5341,9 @@
struct OutputPartialMock : public OutputPrepareFrameAsyncTest::OutputPartialMock {
// Set up the helper functions called by the function under test to use
// mock implementations.
- MOCK_METHOD0(presentFrameAndReleaseLayers, void());
- MOCK_METHOD0(presentFrameAndReleaseLayersAsync, ftl::Future<std::monostate>());
+ MOCK_METHOD(void, presentFrameAndReleaseLayers, (bool flushEvenWhenDisabled));
+ MOCK_METHOD(ftl::Future<std::monostate>, presentFrameAndReleaseLayersAsync,
+ (bool flushEvenWhenDisabled));
};
OutputPresentFrameAndReleaseLayersAsyncTest() {
mOutput->setDisplayColorProfileForTest(
@@ -5290,16 +5360,16 @@
};
TEST_F(OutputPresentFrameAndReleaseLayersAsyncTest, notCalledWhenNotRequested) {
- EXPECT_CALL(*mOutput, presentFrameAndReleaseLayersAsync()).Times(0);
- EXPECT_CALL(*mOutput, presentFrameAndReleaseLayers()).Times(1);
+ EXPECT_CALL(*mOutput, presentFrameAndReleaseLayersAsync(_)).Times(0);
+ EXPECT_CALL(*mOutput, presentFrameAndReleaseLayers(_)).Times(1);
mOutput->present(mRefreshArgs);
}
TEST_F(OutputPresentFrameAndReleaseLayersAsyncTest, calledWhenRequested) {
- EXPECT_CALL(*mOutput, presentFrameAndReleaseLayersAsync())
+ EXPECT_CALL(*mOutput, presentFrameAndReleaseLayersAsync(false))
.WillOnce(Return(ftl::yield<std::monostate>({})));
- EXPECT_CALL(*mOutput, presentFrameAndReleaseLayers()).Times(0);
+ EXPECT_CALL(*mOutput, presentFrameAndReleaseLayers(_)).Times(0);
mOutput->offloadPresentNextFrame();
mOutput->present(mRefreshArgs);
@@ -5307,9 +5377,10 @@
TEST_F(OutputPresentFrameAndReleaseLayersAsyncTest, calledForOneFrame) {
::testing::InSequence inseq;
- EXPECT_CALL(*mOutput, presentFrameAndReleaseLayersAsync())
+ constexpr bool kFlushEvenWhenDisabled = false;
+ EXPECT_CALL(*mOutput, presentFrameAndReleaseLayersAsync(kFlushEvenWhenDisabled))
.WillOnce(Return(ftl::yield<std::monostate>({})));
- EXPECT_CALL(*mOutput, presentFrameAndReleaseLayers()).Times(1);
+ EXPECT_CALL(*mOutput, presentFrameAndReleaseLayers(kFlushEvenWhenDisabled)).Times(1);
mOutput->offloadPresentNextFrame();
mOutput->present(mRefreshArgs);
@@ -5390,5 +5461,59 @@
mOutput.updateProtectedContentState();
}
+struct OutputPresentFrameAndReleaseLayersTest : public testing::Test {
+ struct OutputPartialMock : public OutputPartialMockBase {
+ // Sets up the helper functions called by the function under test (and functions we can
+ // ignore) to use mock implementations.
+ MOCK_METHOD1(updateColorProfile, void(const compositionengine::CompositionRefreshArgs&));
+ MOCK_METHOD1(updateCompositionState,
+ void(const compositionengine::CompositionRefreshArgs&));
+ MOCK_METHOD0(planComposition, void());
+ MOCK_METHOD1(writeCompositionState, void(const compositionengine::CompositionRefreshArgs&));
+ MOCK_METHOD1(setColorTransform, void(const compositionengine::CompositionRefreshArgs&));
+ MOCK_METHOD0(beginFrame, void());
+ MOCK_METHOD0(prepareFrame, void());
+ MOCK_METHOD0(prepareFrameAsync, GpuCompositionResult());
+ MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&));
+ MOCK_METHOD1(finishFrame, void(GpuCompositionResult&&));
+ MOCK_METHOD(void, presentFrameAndReleaseLayers, (bool flushEvenWhenDisabled), (override));
+ MOCK_METHOD1(renderCachedSets, void(const compositionengine::CompositionRefreshArgs&));
+ MOCK_METHOD1(canPredictCompositionStrategy, bool(const CompositionRefreshArgs&));
+ MOCK_METHOD(void, setHintSessionRequiresRenderEngine, (bool requiresRenderEngine),
+ (override));
+ MOCK_METHOD(bool, isPowerHintSessionEnabled, (), (override));
+ MOCK_METHOD(bool, isPowerHintSessionGpuReportingEnabled, (), (override));
+ };
+
+ OutputPresentFrameAndReleaseLayersTest() {
+ EXPECT_CALL(mOutput, isPowerHintSessionEnabled()).WillRepeatedly(Return(true));
+ EXPECT_CALL(mOutput, isPowerHintSessionGpuReportingEnabled()).WillRepeatedly(Return(true));
+ }
+
+ NiceMock<OutputPartialMock> mOutput;
+};
+
+TEST_F(OutputPresentFrameAndReleaseLayersTest, noBuffersToUncache) {
+ CompositionRefreshArgs args;
+ ASSERT_TRUE(args.bufferIdsToUncache.empty());
+ mOutput.editState().isEnabled = false;
+
+ constexpr bool kFlushEvenWhenDisabled = false;
+ EXPECT_CALL(mOutput, presentFrameAndReleaseLayers(kFlushEvenWhenDisabled));
+
+ mOutput.present(args);
+}
+
+TEST_F(OutputPresentFrameAndReleaseLayersTest, buffersToUncache) {
+ CompositionRefreshArgs args;
+ args.bufferIdsToUncache.push_back(1);
+ mOutput.editState().isEnabled = false;
+
+ constexpr bool kFlushEvenWhenDisabled = true;
+ EXPECT_CALL(mOutput, presentFrameAndReleaseLayers(kFlushEvenWhenDisabled));
+
+ mOutput.present(args);
+}
+
} // namespace
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 3bf0eaa..a57e626 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -474,7 +474,6 @@
features |= RefreshRateOverlay::Features::SetByHwc;
}
- // TODO(b/296636258) Update to use the render rate range in VRR mode.
const auto fpsRange = mRefreshRateSelector->getSupportedRefreshRateRange();
mRefreshRateOverlay = RefreshRateOverlay::create(fpsRange, features);
if (mRefreshRateOverlay) {
@@ -485,11 +484,14 @@
}
}
-void DisplayDevice::updateRefreshRateOverlayRate(Fps vsyncRate, Fps renderFps, bool setByHwc) {
+void DisplayDevice::updateRefreshRateOverlayRate(Fps refreshRate, Fps renderFps, bool setByHwc) {
ATRACE_CALL();
if (mRefreshRateOverlay) {
if (!mRefreshRateOverlay->isSetByHwc() || setByHwc) {
- mRefreshRateOverlay->changeRefreshRate(vsyncRate, renderFps);
+ if (mRefreshRateSelector->isVrrDevice() && !mRefreshRateOverlay->isSetByHwc()) {
+ refreshRate = renderFps;
+ }
+ mRefreshRateOverlay->changeRefreshRate(refreshRate, renderFps);
} else {
mRefreshRateOverlay->changeRenderRate(renderFps);
}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index ef3e77d..a21559f 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -226,7 +226,7 @@
// Enables an overlay to be displayed with the current refresh rate
void enableRefreshRateOverlay(bool enable, bool setByHwc, bool showSpinner, bool showRenderRate,
bool showInMiddle) REQUIRES(kMainThreadContext);
- void updateRefreshRateOverlayRate(Fps vsyncRate, Fps renderFps, bool setByHwc = false);
+ void updateRefreshRateOverlayRate(Fps refreshRate, Fps renderFps, bool setByHwc = false);
bool isRefreshRateOverlayEnabled() const { return mRefreshRateOverlay != nullptr; }
bool onKernelTimerChanged(std::optional<DisplayModeId>, bool timerExpired);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 3cfb9ca..3d285a8 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -600,6 +600,13 @@
return NO_ERROR;
}
+status_t HWComposer::executeCommands(HalDisplayId displayId) {
+ auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
+ auto error = static_cast<hal::Error>(mComposer->executeCommands(hwcDisplay->getId()));
+ RETURN_IF_HWC_ERROR_FOR("executeCommands", error, displayId, UNKNOWN_ERROR);
+ return NO_ERROR;
+}
+
status_t HWComposer::setPowerMode(PhysicalDisplayId displayId, hal::PowerMode mode) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index bc32cda..9368b7b 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -160,6 +160,8 @@
HalDisplayId,
std::optional<std::chrono::steady_clock::time_point> earliestPresentTime) = 0;
+ virtual status_t executeCommands(HalDisplayId) = 0;
+
// set power mode
virtual status_t setPowerMode(PhysicalDisplayId, hal::PowerMode) = 0;
@@ -361,6 +363,8 @@
HalDisplayId,
std::optional<std::chrono::steady_clock::time_point> earliestPresentTime) override;
+ status_t executeCommands(HalDisplayId) override;
+
// set power mode
status_t setPowerMode(PhysicalDisplayId, hal::PowerMode mode) override;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index d69bfaf..4b5a68c 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -316,7 +316,7 @@
status_t VirtualDisplaySurface::dequeueBuffer(Source source,
PixelFormat format, uint64_t usage, int* sslot, sp<Fence>* fence) {
- LOG_ALWAYS_FATAL_IF(mDisplayId.isVirtual());
+ LOG_ALWAYS_FATAL_IF(GpuVirtualDisplayId::tryCast(mDisplayId).has_value());
status_t result =
mSource[source]->dequeueBuffer(sslot, fence, mSinkBufferWidth, mSinkBufferHeight,
@@ -616,7 +616,7 @@
}
status_t VirtualDisplaySurface::refreshOutputBuffer() {
- LOG_ALWAYS_FATAL_IF(mDisplayId.isVirtual());
+ LOG_ALWAYS_FATAL_IF(GpuVirtualDisplayId::tryCast(mDisplayId).has_value());
if (mOutputProducerSlot >= 0) {
mSource[SOURCE_SINK]->cancelBuffer(
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
index 0dcbb3c..39a6b77 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
@@ -52,8 +52,12 @@
mChildren = hierarchy.mChildren;
}
-void LayerHierarchy::traverse(const Visitor& visitor,
- LayerHierarchy::TraversalPath& traversalPath) const {
+void LayerHierarchy::traverse(const Visitor& visitor, LayerHierarchy::TraversalPath& traversalPath,
+ uint32_t depth) const {
+ LLOG_ALWAYS_FATAL_WITH_TRACE_IF(depth > 50,
+ "Cycle detected in LayerHierarchy::traverse. See "
+ "traverse_stack_overflow_transactions.winscope");
+
if (mLayer) {
bool breakTraversal = !visitor(*this, traversalPath);
if (breakTraversal) {
@@ -66,7 +70,7 @@
for (auto& [child, childVariant] : mChildren) {
ScopedAddToTraversalPath addChildToTraversalPath(traversalPath, child->mLayer->id,
childVariant);
- child->traverse(visitor, traversalPath);
+ child->traverse(visitor, traversalPath, depth + 1);
}
}
@@ -256,27 +260,36 @@
hierarchy->mParent->updateChild(hierarchy, LayerHierarchy::Variant::Attached);
}
-void LayerHierarchyBuilder::attachHierarchyToRelativeParent(LayerHierarchy* root) {
- if (root->mLayer) {
- attachToRelativeParent(root);
- }
- for (auto& [child, childVariant] : root->mChildren) {
- if (childVariant == LayerHierarchy::Variant::Detached ||
- childVariant == LayerHierarchy::Variant::Attached) {
- attachHierarchyToRelativeParent(child);
+std::vector<LayerHierarchy*> LayerHierarchyBuilder::getDescendants(LayerHierarchy* root) {
+ std::vector<LayerHierarchy*> hierarchies;
+ hierarchies.push_back(root);
+ std::vector<LayerHierarchy*> descendants;
+ for (size_t i = 0; i < hierarchies.size(); i++) {
+ LayerHierarchy* hierarchy = hierarchies[i];
+ if (hierarchy->mLayer) {
+ descendants.push_back(hierarchy);
}
+ for (auto& [child, childVariant] : hierarchy->mChildren) {
+ if (childVariant == LayerHierarchy::Variant::Detached ||
+ childVariant == LayerHierarchy::Variant::Attached) {
+ hierarchies.push_back(child);
+ }
+ }
+ }
+ return descendants;
+}
+
+void LayerHierarchyBuilder::attachHierarchyToRelativeParent(LayerHierarchy* root) {
+ std::vector<LayerHierarchy*> hierarchiesToAttach = getDescendants(root);
+ for (LayerHierarchy* hierarchy : hierarchiesToAttach) {
+ attachToRelativeParent(hierarchy);
}
}
void LayerHierarchyBuilder::detachHierarchyFromRelativeParent(LayerHierarchy* root) {
- if (root->mLayer) {
- detachFromRelativeParent(root);
- }
- for (auto& [child, childVariant] : root->mChildren) {
- if (childVariant == LayerHierarchy::Variant::Detached ||
- childVariant == LayerHierarchy::Variant::Attached) {
- detachHierarchyFromRelativeParent(child);
- }
+ std::vector<LayerHierarchy*> hierarchiesToDetach = getDescendants(root);
+ for (LayerHierarchy* hierarchy : hierarchiesToDetach) {
+ detachFromRelativeParent(hierarchy);
}
}
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.h b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
index f62e758..d023f9e 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.h
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
@@ -147,7 +147,7 @@
if (mLayer) {
root.id = mLayer->id;
}
- traverse(visitor, root);
+ traverse(visitor, root, /*depth=*/0);
}
// Traverse the hierarchy in z-order, skipping children that have relative parents.
@@ -190,7 +190,8 @@
void sortChildrenByZOrder();
void updateChild(LayerHierarchy*, LayerHierarchy::Variant);
void traverseInZOrder(const Visitor& visitor, LayerHierarchy::TraversalPath& parent) const;
- void traverse(const Visitor& visitor, LayerHierarchy::TraversalPath& parent) const;
+ void traverse(const Visitor& visitor, LayerHierarchy::TraversalPath& parent,
+ uint32_t depth = 0) const;
void dump(std::ostream& out, const std::string& prefix, LayerHierarchy::Variant variant,
bool isLastChild, bool includeMirroredHierarchy) const;
@@ -217,6 +218,7 @@
void detachFromParent(LayerHierarchy*);
void attachToRelativeParent(LayerHierarchy*);
void detachFromRelativeParent(LayerHierarchy*);
+ std::vector<LayerHierarchy*> getDescendants(LayerHierarchy*);
void attachHierarchyToRelativeParent(LayerHierarchy*);
void detachHierarchyFromRelativeParent(LayerHierarchy*);
void init(const std::vector<std::unique_ptr<RequestedLayerState>>&);
diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
index 4b0618e..dd5e8bd 100644
--- a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
@@ -152,6 +152,10 @@
if (swapErase(linkedLayer->mirrorIds, layer.id)) {
linkedLayer->changes |= RequestedLayerState::Changes::Mirror;
}
+ if (linkedLayer->layerIdToMirror == layer.id) {
+ linkedLayer->layerIdToMirror = UNASSIGNED_LAYER_ID;
+ linkedLayer->changes |= RequestedLayerState::Changes::Mirror;
+ }
if (linkedLayer->touchCropId == layer.id) {
linkedLayer->touchCropId = UNASSIGNED_LAYER_ID;
}
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.h b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
index eef8dff..398e64a 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.h
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
@@ -84,7 +84,7 @@
// is a mirror root
bool ignoreLocalTransform;
gui::DropInputMode dropInputMode;
- bool isTrustedOverlay;
+ gui::TrustedOverlay trustedOverlay;
gui::GameMode gameMode;
scheduler::LayerInfo::FrameRate frameRate;
scheduler::LayerInfo::FrameRate inheritedFrameRate;
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index f2497d4..6d4b0b5 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -22,6 +22,7 @@
#include <numeric>
#include <optional>
+#include <common/FlagManager.h>
#include <ftl/small_map.h>
#include <gui/TraceUtils.h>
#include <ui/DisplayMap.h>
@@ -358,7 +359,7 @@
snapshot.relativeLayerMetadata.mMap.clear();
snapshot.inputInfo.touchOcclusionMode = gui::TouchOcclusionMode::BLOCK_UNTRUSTED;
snapshot.dropInputMode = gui::DropInputMode::NONE;
- snapshot.isTrustedOverlay = false;
+ snapshot.trustedOverlay = gui::TrustedOverlay::UNSET;
snapshot.gameMode = gui::GameMode::Unsupported;
snapshot.frameRate = {};
snapshot.fixedTransformHint = ui::Transform::ROT_INVALID;
@@ -735,7 +736,19 @@
}
if (forceUpdate || snapshot.clientChanges & layer_state_t::eTrustedOverlayChanged) {
- snapshot.isTrustedOverlay = parentSnapshot.isTrustedOverlay || requested.isTrustedOverlay;
+ switch (requested.trustedOverlay) {
+ case gui::TrustedOverlay::UNSET:
+ snapshot.trustedOverlay = parentSnapshot.trustedOverlay;
+ break;
+ case gui::TrustedOverlay::DISABLED:
+ snapshot.trustedOverlay = FlagManager::getInstance().override_trusted_overlay()
+ ? requested.trustedOverlay
+ : parentSnapshot.trustedOverlay;
+ break;
+ case gui::TrustedOverlay::ENABLED:
+ snapshot.trustedOverlay = requested.trustedOverlay;
+ break;
+ }
}
if (snapshot.isHiddenByPolicyFromParent &&
@@ -1112,7 +1125,7 @@
// Inherit the trusted state from the parent hierarchy, but don't clobber the trusted state
// if it was set by WM for a known system overlay
- if (snapshot.isTrustedOverlay) {
+ if (snapshot.trustedOverlay == gui::TrustedOverlay::ENABLED) {
snapshot.inputInfo.inputConfig |= InputConfig::TRUSTED_OVERLAY;
}
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
index 028bd19..3e8d740 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -118,7 +118,7 @@
shadowRadius = 0.f;
fixedTransformHint = ui::Transform::ROT_INVALID;
destinationFrame.makeInvalid();
- isTrustedOverlay = false;
+ trustedOverlay = gui::TrustedOverlay::UNSET;
dropInputMode = gui::DropInputMode::NONE;
dimmingEnabled = true;
defaultFrameRateCompatibility = static_cast<int8_t>(scheduler::FrameRateCompatibility::Default);
@@ -587,23 +587,22 @@
const uint64_t deniedFlags = layer_state_t::eProducerDisconnect | layer_state_t::eLayerChanged |
layer_state_t::eRelativeLayerChanged | layer_state_t::eTransparentRegionChanged |
- layer_state_t::eFlagsChanged | layer_state_t::eBlurRegionsChanged |
- layer_state_t::eLayerStackChanged | layer_state_t::eReparent |
+ layer_state_t::eBlurRegionsChanged | layer_state_t::eLayerStackChanged |
+ layer_state_t::eReparent |
(FlagManager::getInstance().latch_unsignaled_with_auto_refresh_changed()
? 0
- : layer_state_t::eAutoRefreshChanged);
+ : (layer_state_t::eAutoRefreshChanged | layer_state_t::eFlagsChanged));
if (s.what & deniedFlags) {
ATRACE_FORMAT_INSTANT("%s: false [has denied flags 0x%" PRIx64 "]", __func__,
s.what & deniedFlags);
return false;
}
- bool changedFlags = diff(s);
- static constexpr auto deniedChanges = layer_state_t::ePositionChanged |
- layer_state_t::eAlphaChanged | layer_state_t::eColorTransformChanged |
- layer_state_t::eBackgroundColorChanged | layer_state_t::eMatrixChanged |
- layer_state_t::eCornerRadiusChanged | layer_state_t::eBackgroundBlurRadiusChanged |
- layer_state_t::eBufferTransformChanged |
+ const uint64_t changedFlags = diff(s);
+ const uint64_t deniedChanges = layer_state_t::ePositionChanged | layer_state_t::eAlphaChanged |
+ layer_state_t::eColorTransformChanged | layer_state_t::eBackgroundColorChanged |
+ layer_state_t::eMatrixChanged | layer_state_t::eCornerRadiusChanged |
+ layer_state_t::eBackgroundBlurRadiusChanged | layer_state_t::eBufferTransformChanged |
layer_state_t::eTransformToDisplayInverseChanged | layer_state_t::eCropChanged |
layer_state_t::eDataspaceChanged | layer_state_t::eHdrMetadataChanged |
layer_state_t::eSidebandStreamChanged | layer_state_t::eColorSpaceAgnosticChanged |
@@ -611,10 +610,13 @@
layer_state_t::eTrustedOverlayChanged | layer_state_t::eStretchChanged |
layer_state_t::eBufferCropChanged | layer_state_t::eDestinationFrameChanged |
layer_state_t::eDimmingEnabledChanged | layer_state_t::eExtendedRangeBrightnessChanged |
- layer_state_t::eDesiredHdrHeadroomChanged;
+ layer_state_t::eDesiredHdrHeadroomChanged |
+ (FlagManager::getInstance().latch_unsignaled_with_auto_refresh_changed()
+ ? layer_state_t::eFlagsChanged
+ : 0);
if (changedFlags & deniedChanges) {
ATRACE_FORMAT_INSTANT("%s: false [has denied changes flags 0x%" PRIx64 "]", __func__,
- s.what & deniedChanges);
+ changedFlags & deniedChanges);
return false;
}
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 363b35c..6b97e2f 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -3902,7 +3902,7 @@
}
if (s.what & layer_state_t::eTrustedOverlayChanged) {
- if (mDrawingState.isTrustedOverlay != s.isTrustedOverlay) {
+ if (mDrawingState.isTrustedOverlay != (s.trustedOverlay == gui::TrustedOverlay::ENABLED)) {
ATRACE_FORMAT_INSTANT("%s: false [eTrustedOverlayChanged changed]", __func__);
return false;
}
diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp
index 753886a..496033b 100644
--- a/services/surfaceflinger/LayerProtoHelper.cpp
+++ b/services/surfaceflinger/LayerProtoHelper.cpp
@@ -382,7 +382,8 @@
layerInfo->set_corner_radius(
(snapshot.roundedCorner.radius.x + snapshot.roundedCorner.radius.y) / 2.0);
layerInfo->set_background_blur_radius(snapshot.backgroundBlurRadius);
- layerInfo->set_is_trusted_overlay(snapshot.isTrustedOverlay);
+ layerInfo->set_is_trusted_overlay(snapshot.trustedOverlay == gui::TrustedOverlay::ENABLED);
+ // TODO(b/339701674) update protos
LayerProtoHelper::writeToProtoDeprecated(transform, layerInfo->mutable_transform());
LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(),
[&]() { return layerInfo->mutable_position(); });
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index b960e33..9527a99 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -28,7 +28,7 @@
namespace android {
-auto RefreshRateOverlay::draw(int vsyncRate, int renderFps, SkColor color,
+auto RefreshRateOverlay::draw(int refreshRate, int renderFps, SkColor color,
ui::Transform::RotationFlags rotation, ftl::Flags<Features> features)
-> Buffers {
const size_t loopCount = features.test(Features::Spinner) ? 6 : 1;
@@ -71,7 +71,7 @@
canvas->setMatrix(canvasTransform);
int left = 0;
- drawNumber(vsyncRate, left, color, *canvas);
+ drawNumber(refreshRate, left, color, *canvas);
left += 3 * (kDigitWidth + kDigitSpace);
if (features.test(Features::Spinner)) {
switch (i) {
@@ -171,7 +171,7 @@
return mSurfaceControl != nullptr;
}
-auto RefreshRateOverlay::getOrCreateBuffers(Fps vsyncRate, Fps renderFps) -> const Buffers& {
+auto RefreshRateOverlay::getOrCreateBuffers(Fps refreshRate, Fps renderFps) -> const Buffers& {
static const Buffers kNoBuffers;
if (!mSurfaceControl) return kNoBuffers;
@@ -198,21 +198,15 @@
createTransaction().setTransform(mSurfaceControl->get(), transform).apply();
BufferCache::const_iterator it =
- mBufferCache.find({vsyncRate.getIntValue(), renderFps.getIntValue(), transformHint});
+ mBufferCache.find({refreshRate.getIntValue(), renderFps.getIntValue(), transformHint});
if (it == mBufferCache.end()) {
- // HWC minFps is not known by the framework in order
- // to consider lower rates we set minFps to 0.
- const int minFps = isSetByHwc() ? 0 : mFpsRange.min.getIntValue();
const int maxFps = mFpsRange.max.getIntValue();
- // Clamp to the range. The current vsyncRate may be outside of this range if the display
- // has changed its set of supported refresh rates.
- const int displayIntFps = std::clamp(vsyncRate.getIntValue(), minFps, maxFps);
+ // Clamp to supported refresh rate range: the current refresh rate may be outside of this
+ // range if the display has changed its set of supported refresh rates.
+ const int refreshIntFps = std::clamp(refreshRate.getIntValue(), 0, maxFps);
const int renderIntFps = renderFps.getIntValue();
-
- // Ensure non-zero range to avoid division by zero.
- const float fpsScale =
- static_cast<float>(displayIntFps - minFps) / std::max(1, maxFps - minFps);
+ const float fpsScale = static_cast<float>(refreshIntFps) / maxFps;
constexpr SkColor kMinFpsColor = SK_ColorRED;
constexpr SkColor kMaxFpsColor = SK_ColorGREEN;
@@ -228,9 +222,9 @@
const SkColor color = colorBase.toSkColor();
- auto buffers = draw(displayIntFps, renderIntFps, color, transformHint, mFeatures);
+ auto buffers = draw(refreshIntFps, renderIntFps, color, transformHint, mFeatures);
it = mBufferCache
- .try_emplace({displayIntFps, renderIntFps, transformHint}, std::move(buffers))
+ .try_emplace({refreshIntFps, renderIntFps, transformHint}, std::move(buffers))
.first;
}
@@ -260,25 +254,26 @@
createTransaction().setLayerStack(mSurfaceControl->get(), stack).apply();
}
-void RefreshRateOverlay::changeRefreshRate(Fps vsyncRate, Fps renderFps) {
- mVsyncRate = vsyncRate;
+void RefreshRateOverlay::changeRefreshRate(Fps refreshRate, Fps renderFps) {
+ mRefreshRate = refreshRate;
mRenderFps = renderFps;
- const auto buffer = getOrCreateBuffers(vsyncRate, renderFps)[mFrame];
+ const auto buffer = getOrCreateBuffers(refreshRate, renderFps)[mFrame];
createTransaction().setBuffer(mSurfaceControl->get(), buffer).apply();
}
void RefreshRateOverlay::changeRenderRate(Fps renderFps) {
- if (mFeatures.test(Features::RenderRate) && mVsyncRate && FlagManager::getInstance().misc1()) {
+ if (mFeatures.test(Features::RenderRate) && mRefreshRate &&
+ FlagManager::getInstance().misc1()) {
mRenderFps = renderFps;
- const auto buffer = getOrCreateBuffers(*mVsyncRate, renderFps)[mFrame];
+ const auto buffer = getOrCreateBuffers(*mRefreshRate, renderFps)[mFrame];
createTransaction().setBuffer(mSurfaceControl->get(), buffer).apply();
}
}
void RefreshRateOverlay::animate() {
- if (!mFeatures.test(Features::Spinner) || !mVsyncRate) return;
+ if (!mFeatures.test(Features::Spinner) || !mRefreshRate) return;
- const auto& buffers = getOrCreateBuffers(*mVsyncRate, *mRenderFps);
+ const auto& buffers = getOrCreateBuffers(*mRefreshRate, *mRenderFps);
mFrame = (mFrame + 1) % buffers.size();
const auto buffer = buffers[mFrame];
createTransaction().setBuffer(mSurfaceControl->get(), buffer).apply();
diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h
index 0fec470..b2896f0 100644
--- a/services/surfaceflinger/RefreshRateOverlay.h
+++ b/services/surfaceflinger/RefreshRateOverlay.h
@@ -65,7 +65,7 @@
using Buffers = std::vector<sp<GraphicBuffer>>;
- static Buffers draw(int vsyncRate, int renderFps, SkColor, ui::Transform::RotationFlags,
+ static Buffers draw(int refreshRate, int renderFps, SkColor, ui::Transform::RotationFlags,
ftl::Flags<Features>);
static void drawNumber(int number, int left, SkColor, SkCanvas&);
@@ -74,12 +74,12 @@
SurfaceComposerClient::Transaction createTransaction() const;
struct Key {
- int vsyncRate;
+ int refreshRate;
int renderFps;
ui::Transform::RotationFlags flags;
bool operator==(Key other) const {
- return vsyncRate == other.vsyncRate && renderFps == other.renderFps &&
+ return refreshRate == other.refreshRate && renderFps == other.renderFps &&
flags == other.flags;
}
};
@@ -87,7 +87,7 @@
using BufferCache = ftl::SmallMap<Key, Buffers, 9>;
BufferCache mBufferCache;
- std::optional<Fps> mVsyncRate;
+ std::optional<Fps> mRefreshRate;
std::optional<Fps> mRenderFps;
size_t mFrame = 0;
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 2b4e234..5add290 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -315,39 +315,15 @@
return true;
};
- std::function<std::vector<std::pair<Layer*, sp<LayerFE>>>()> getLayerSnapshots;
- if (mFlinger.mLayerLifecycleManagerEnabled) {
- auto filterFn = [&](const frontend::LayerSnapshot& snapshot,
- bool& outStopTraversal) -> bool {
- const Rect bounds =
- frontend::RequestedLayerState::reduce(Rect(snapshot.geomLayerBounds),
- snapshot.transparentRegionHint);
- const ui::Transform transform = snapshot.geomLayerTransform;
- return layerFilterFn(snapshot.name.c_str(), snapshot.path.id, bounds, transform,
- outStopTraversal);
- };
- getLayerSnapshots =
- mFlinger.getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID,
- filterFn);
- } else {
- auto traverseLayers = [&](const LayerVector::Visitor& visitor) {
- bool stopLayerFound = false;
- auto filterVisitor = [&](Layer* layer) {
- // We don't want to capture any layers beyond the stop layer
- if (stopLayerFound) return;
-
- if (!layerFilterFn(layer->getDebugName(), layer->getSequence(),
- Rect(layer->getBounds()), layer->getTransform(),
- stopLayerFound)) {
- return;
- }
- visitor(layer);
- };
- mFlinger.traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, {},
- filterVisitor);
- };
- getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers);
- }
+ auto filterFn = [&](const frontend::LayerSnapshot& snapshot, bool& outStopTraversal) -> bool {
+ const Rect bounds = frontend::RequestedLayerState::reduce(Rect(snapshot.geomLayerBounds),
+ snapshot.transparentRegionHint);
+ const ui::Transform transform = snapshot.geomLayerTransform;
+ return layerFilterFn(snapshot.name.c_str(), snapshot.path.id, bounds, transform,
+ outStopTraversal);
+ };
+ auto getLayerSnapshotsFn =
+ mFlinger.getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID, filterFn);
std::shared_ptr<renderengine::ExternalTexture> buffer = nullptr;
if (mCachedBuffer && mCachedBuffer->getBuffer()->getWidth() == sampledBounds.getWidth() &&
@@ -372,17 +348,30 @@
constexpr bool kGrayscale = false;
constexpr bool kIsProtected = false;
- if (const auto fenceResult =
- mFlinger.captureScreenshot(SurfaceFlinger::RenderAreaBuilderVariant(
- std::in_place_type<DisplayRenderAreaBuilder>,
- sampledBounds, sampledBounds.getSize(),
- ui::Dataspace::V0_SRGB,
- kHintForSeamlessTransition,
- true /* captureSecureLayers */, displayWeak),
- getLayerSnapshots, buffer, kRegionSampling, kGrayscale,
- kIsProtected, nullptr)
+ SurfaceFlinger::RenderAreaBuilderVariant
+ renderAreaBuilder(std::in_place_type<DisplayRenderAreaBuilder>, sampledBounds,
+ sampledBounds.getSize(), ui::Dataspace::V0_SRGB,
+ kHintForSeamlessTransition, true /* captureSecureLayers */,
+ displayWeak);
+
+ FenceResult fenceResult;
+ if (FlagManager::getInstance().single_hop_screenshot() &&
+ FlagManager::getInstance().ce_fence_promise()) {
+ std::vector<sp<LayerFE>> layerFEs;
+ auto displayState =
+ mFlinger.getDisplayAndLayerSnapshotsFromMainThread(renderAreaBuilder,
+ getLayerSnapshotsFn, layerFEs);
+ fenceResult =
+ mFlinger.captureScreenshot(renderAreaBuilder, buffer, kRegionSampling, kGrayscale,
+ kIsProtected, nullptr, displayState, layerFEs)
.get();
- fenceResult.ok()) {
+ } else {
+ fenceResult =
+ mFlinger.captureScreenshotLegacy(renderAreaBuilder, getLayerSnapshotsFn, buffer,
+ kRegionSampling, kGrayscale, kIsProtected, nullptr)
+ .get();
+ }
+ if (fenceResult.ok()) {
fenceResult.value()->waitForever(LOG_TAG);
}
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index 85ce713..dd3c4b0 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -737,7 +737,9 @@
return ticks<std::milli, float>(TimePoint::fromNs(timePoint) - now);
};
- Fps displayFps = mRenderRateOpt ? *mRenderRateOpt : Fps::fromPeriodNsecs(mIdealPeriod.ns());
+ Fps displayFps = !FlagManager::getInstance().vrr_bugfix_24q4() && mRenderRateOpt
+ ? *mRenderRateOpt
+ : Fps::fromPeriodNsecs(mIdealPeriod.ns());
const auto divisor = RefreshRateSelector::getFrameRateDivisor(displayFps, frameRate);
const auto now = TimePoint::now();
diff --git a/services/surfaceflinger/ScreenCaptureOutput.cpp b/services/surfaceflinger/ScreenCaptureOutput.cpp
index dd03366..8bb72b8 100644
--- a/services/surfaceflinger/ScreenCaptureOutput.cpp
+++ b/services/surfaceflinger/ScreenCaptureOutput.cpp
@@ -30,7 +30,7 @@
ScreenCaptureOutput, compositionengine::CompositionEngine, const RenderArea&,
const compositionengine::Output::ColorProfile&,
bool>(args.compositionEngine, args.renderArea, args.colorProfile, args.regionSampling,
- args.dimInGammaSpaceForEnhancedScreenshots);
+ args.dimInGammaSpaceForEnhancedScreenshots, args.enableLocalTonemapping);
output->editState().isSecure = args.renderArea.isSecure();
output->editState().isProtected = args.isProtected;
output->setCompositionEnabled(true);
@@ -63,11 +63,13 @@
ScreenCaptureOutput::ScreenCaptureOutput(
const RenderArea& renderArea, const compositionengine::Output::ColorProfile& colorProfile,
- bool regionSampling, bool dimInGammaSpaceForEnhancedScreenshots)
+ bool regionSampling, bool dimInGammaSpaceForEnhancedScreenshots,
+ bool enableLocalTonemapping)
: mRenderArea(renderArea),
mColorProfile(colorProfile),
mRegionSampling(regionSampling),
- mDimInGammaSpaceForEnhancedScreenshots(dimInGammaSpaceForEnhancedScreenshots) {}
+ mDimInGammaSpaceForEnhancedScreenshots(dimInGammaSpaceForEnhancedScreenshots),
+ mEnableLocalTonemapping(enableLocalTonemapping) {}
void ScreenCaptureOutput::updateColorProfile(const compositionengine::CompositionRefreshArgs&) {
auto& outputState = editState();
@@ -88,6 +90,11 @@
aidl::android::hardware::graphics::composer3::DimmingStage::GAMMA_OETF;
}
+ if (mEnableLocalTonemapping) {
+ clientCompositionDisplay.tonemapStrategy =
+ renderengine::DisplaySettings::TonemapStrategy::Local;
+ }
+
return clientCompositionDisplay;
}
diff --git a/services/surfaceflinger/ScreenCaptureOutput.h b/services/surfaceflinger/ScreenCaptureOutput.h
index 069f458..c233ead 100644
--- a/services/surfaceflinger/ScreenCaptureOutput.h
+++ b/services/surfaceflinger/ScreenCaptureOutput.h
@@ -39,6 +39,7 @@
bool treat170mAsSrgb;
bool dimInGammaSpaceForEnhancedScreenshots;
bool isProtected = false;
+ bool enableLocalTonemapping = false;
};
// ScreenCaptureOutput is used to compose a set of layers into a preallocated buffer.
@@ -49,7 +50,8 @@
public:
ScreenCaptureOutput(const RenderArea& renderArea,
const compositionengine::Output::ColorProfile& colorProfile,
- bool regionSampling, bool dimInGammaSpaceForEnhancedScreenshots);
+ bool regionSampling, bool dimInGammaSpaceForEnhancedScreenshots,
+ bool enableLocalTonemapping);
void updateColorProfile(const compositionengine::CompositionRefreshArgs&) override;
@@ -67,6 +69,7 @@
const compositionengine::Output::ColorProfile& mColorProfile;
const bool mRegionSampling;
const bool mDimInGammaSpaceForEnhancedScreenshots;
+ const bool mEnableLocalTonemapping;
};
std::shared_ptr<ScreenCaptureOutput> createScreenCaptureOutput(ScreenCaptureOutputArgs);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 62b0ded..59345db 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -40,6 +40,7 @@
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/PermissionCache.h>
+#include <com_android_graphics_surfaceflinger_flags.h>
#include <common/FlagManager.h>
#include <compositionengine/CompositionEngine.h>
#include <compositionengine/CompositionRefreshArgs.h>
@@ -813,8 +814,24 @@
.setGraphicsApi(renderengine::RenderEngine::GraphicsApi::VK);
} else {
const auto kVulkan = renderengine::RenderEngine::GraphicsApi::VK;
+// TODO: b/341728634 - Clean up conditional compilation.
+// Note: this guard in particular must check e.g.
+// COM_ANDROID_GRAPHICS_SURFACEFLINGER_FLAGS_GRAPHITE_RENDERENGINE directly (instead of calling e.g.
+// COM_ANDROID_GRAPHICS_SURFACEFLINGER_FLAGS(GRAPHITE_RENDERENGINE)) because that macro is undefined
+// in the libsurfaceflingerflags_test variant of com_android_graphics_surfaceflinger_flags.h, which
+// is used by layertracegenerator (which also needs SurfaceFlinger.cpp). :)
+#if COM_ANDROID_GRAPHICS_SURFACEFLINGER_FLAGS_GRAPHITE_RENDERENGINE || \
+ COM_ANDROID_GRAPHICS_SURFACEFLINGER_FLAGS_FORCE_COMPILE_GRAPHITE_RENDERENGINE
const bool useGraphite = FlagManager::getInstance().graphite_renderengine() &&
renderengine::RenderEngine::canSupport(kVulkan);
+#else
+ const bool useGraphite = false;
+ if (FlagManager::getInstance().graphite_renderengine()) {
+ ALOGE("RenderEngine's Graphite Skia backend was requested with the "
+ "debug.renderengine.graphite system property, but it is not compiled in this "
+ "build! Falling back to Ganesh backend selection logic.");
+ }
+#endif
const bool useVulkan = useGraphite ||
(FlagManager::getInstance().vulkan_renderengine() &&
renderengine::RenderEngine::canSupport(kVulkan));
@@ -1013,8 +1030,9 @@
ALOGD("TransactionTraceWriter: file=%s already exists", filename.c_str());
return;
}
- mTransactionTracing->flush();
+ ALOGD("TransactionTraceWriter: writing file=%s", filename.c_str());
mTransactionTracing->writeToFile(filename);
+ mTransactionTracing->flush();
};
if (std::this_thread::get_id() == mMainThreadId) {
writeFn();
@@ -2254,12 +2272,12 @@
kMainThreadContext) {
if (const auto displayIdOpt = getHwComposer().toPhysicalDisplayId(data.display)) {
if (const auto display = getDisplayDeviceLocked(*displayIdOpt)) {
- const Fps fps = Fps::fromPeriodNsecs(getHwComposer().getComposer()->isVrrSupported()
- ? data.refreshPeriodNanos
- : data.vsyncPeriodNanos);
- ATRACE_FORMAT("%s Fps %d", whence, fps.getIntValue());
- display->updateRefreshRateOverlayRate(fps, display->getActiveMode().fps,
- /* setByHwc */ true);
+ const Fps refreshRate = Fps::fromPeriodNsecs(
+ getHwComposer().getComposer()->isVrrSupported() ? data.refreshPeriodNanos
+ : data.vsyncPeriodNanos);
+ ATRACE_FORMAT("%s refresh rate = %d", whence, refreshRate.getIntValue());
+ display->updateRefreshRateOverlayRate(refreshRate, display->getActiveMode().fps,
+ /* showRefreshRate */ true);
}
}
}));
@@ -5710,7 +5728,7 @@
if (layer->setHdrMetadata(s.hdrMetadata)) flags |= eTraversalNeeded;
}
if (what & layer_state_t::eTrustedOverlayChanged) {
- if (layer->setTrustedOverlay(s.isTrustedOverlay)) {
+ if (layer->setTrustedOverlay(s.trustedOverlay == gui::TrustedOverlay::ENABLED)) {
flags |= eTraversalNeeded;
}
}
@@ -6521,12 +6539,17 @@
uint8_t port;
DisplayIdentificationData data;
if (!getHwComposer().getDisplayIdentificationData(*hwcDisplayId, &port, &data)) {
- result.append("no identification data\n");
+ result.append("no display identification data\n");
+ continue;
+ }
+
+ if (data.empty()) {
+ result.append("empty display identification data\n");
continue;
}
if (!isEdid(data)) {
- result.append("unknown identification data\n");
+ result.append("unknown format for display identification data\n");
continue;
}
@@ -7840,14 +7863,13 @@
namespace {
-ui::Dataspace pickBestDataspace(ui::Dataspace requestedDataspace, const DisplayDevice* display,
+ui::Dataspace pickBestDataspace(ui::Dataspace requestedDataspace,
+ const compositionengine::impl::OutputCompositionState& state,
bool capturingHdrLayers, bool hintForSeamlessTransition) {
- if (requestedDataspace != ui::Dataspace::UNKNOWN || display == nullptr) {
+ if (requestedDataspace != ui::Dataspace::UNKNOWN) {
return requestedDataspace;
}
- const auto& state = display->getCompositionDisplay()->getState();
-
const auto dataspaceForColorMode = ui::pickDataspaceFor(state.colorMode);
// TODO: Enable once HDR screenshots are ready.
@@ -7927,23 +7949,14 @@
}
}
- GetLayerSnapshotsFunction getLayerSnapshots;
- if (mLayerLifecycleManagerEnabled) {
- getLayerSnapshots =
- getLayerSnapshotsForScreenshots(layerStack, args.uid, std::move(excludeLayerIds));
- } else {
- auto traverseLayers = [this, args, excludeLayerIds,
- layerStack](const LayerVector::Visitor& visitor) {
- traverseLayersInLayerStack(layerStack, args.uid, std::move(excludeLayerIds), visitor);
- };
- getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers);
- }
+ GetLayerSnapshotsFunction getLayerSnapshotsFn =
+ getLayerSnapshotsForScreenshots(layerStack, args.uid, std::move(excludeLayerIds));
captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type<DisplayRenderAreaBuilder>,
args.sourceCrop, reqSize, args.dataspace,
args.hintForSeamlessTransition,
args.captureSecureLayers, displayWeak),
- getLayerSnapshots, reqSize, args.pixelFormat, args.allowProtected,
+ getLayerSnapshotsFn, reqSize, args.pixelFormat, args.allowProtected,
args.grayscale, captureListener);
}
@@ -7980,16 +7993,9 @@
return;
}
- GetLayerSnapshotsFunction getLayerSnapshots;
- if (mLayerLifecycleManagerEnabled) {
- getLayerSnapshots = getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID,
- /*snapshotFilterFn=*/nullptr);
- } else {
- auto traverseLayers = [this, layerStack](const LayerVector::Visitor& visitor) {
- traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, {}, visitor);
- };
- getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers);
- }
+ GetLayerSnapshotsFunction getLayerSnapshotsFn =
+ getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID,
+ /*snapshotFilterFn=*/nullptr);
if (captureListener == nullptr) {
ALOGE("capture screen must provide a capture listener callback");
@@ -8004,7 +8010,7 @@
Rect(), size, args.dataspace,
args.hintForSeamlessTransition,
false /* captureSecureLayers */, displayWeak),
- getLayerSnapshots, size, args.pixelFormat, kAllowProtected, kGrayscale,
+ getLayerSnapshotsFn, size, args.pixelFormat, kAllowProtected, kGrayscale,
captureListener);
}
@@ -8086,42 +8092,16 @@
return;
}
- GetLayerSnapshotsFunction getLayerSnapshots;
- if (mLayerLifecycleManagerEnabled) {
- std::optional<FloatRect> parentCrop = std::nullopt;
- if (args.childrenOnly) {
- parentCrop = crop.isEmpty() ? FloatRect(0, 0, reqSize.width, reqSize.height)
- : crop.toFloatRect();
- }
-
- getLayerSnapshots = getLayerSnapshotsForScreenshots(parent->sequence, args.uid,
- std::move(excludeLayerIds),
- args.childrenOnly, parentCrop);
- } else {
- auto traverseLayers = [parent, args, excludeLayerIds](const LayerVector::Visitor& visitor) {
- parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
- if (!layer->isVisible()) {
- return;
- } else if (args.childrenOnly && layer == parent.get()) {
- return;
- } else if (args.uid != CaptureArgs::UNSET_UID && args.uid != layer->getOwnerUid()) {
- return;
- }
-
- auto p = sp<Layer>::fromExisting(layer);
- while (p != nullptr) {
- if (excludeLayerIds.count(p->sequence) != 0) {
- return;
- }
- p = p->getParent();
- }
-
- visitor(layer);
- });
- };
- getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers);
+ std::optional<FloatRect> parentCrop = std::nullopt;
+ if (args.childrenOnly) {
+ parentCrop = crop.isEmpty() ? FloatRect(0, 0, reqSize.width, reqSize.height)
+ : crop.toFloatRect();
}
+ GetLayerSnapshotsFunction getLayerSnapshotsFn =
+ getLayerSnapshotsForScreenshots(parent->sequence, args.uid, std::move(excludeLayerIds),
+ args.childrenOnly, parentCrop);
+
if (captureListener == nullptr) {
ALOGD("capture screen must provide a capture listener callback");
invokeScreenCaptureError(BAD_VALUE, captureListener);
@@ -8132,7 +8112,7 @@
reqSize, dataspace, args.captureSecureLayers,
args.hintForSeamlessTransition, parent,
args.childrenOnly),
- getLayerSnapshots, reqSize, args.pixelFormat, args.allowProtected,
+ getLayerSnapshotsFn, reqSize, args.pixelFormat, args.allowProtected,
args.grayscale, captureListener);
}
@@ -8147,12 +8127,15 @@
owningLayer->prepareReleaseCallbacks(std::move(futureFence), layerStack);
}
-bool SurfaceFlinger::layersHasProtectedLayer(
- const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) const {
+// Loop over all visible layers to see whether there's any protected layer. A protected layer is
+// typically a layer with DRM contents, or have the GRALLOC_USAGE_PROTECTED set on the buffer.
+// A protected layer has no implication on whether it's secure, which is explicitly set by
+// application to avoid being screenshot or drawn via unsecure display.
+bool SurfaceFlinger::layersHasProtectedLayer(const std::vector<sp<LayerFE>>& layers) const {
bool protectedLayerFound = false;
- for (auto& [_, layerFe] : layers) {
+ for (auto& layerFE : layers) {
protectedLayerFound |=
- (layerFe->mSnapshot->isVisible && layerFe->mSnapshot->hasProtectedContent);
+ (layerFE->mSnapshot->isVisible && layerFE->mSnapshot->hasProtectedContent);
if (protectedLayerFound) {
break;
}
@@ -8160,8 +8143,28 @@
return protectedLayerFound;
}
+// Getting layer snapshots and display should take place on main thread.
+// Accessing display requires mStateLock, and contention for this lock
+// is reduced when grabbed from the main thread, thus also reducing
+// risk of deadlocks.
+std::optional<SurfaceFlinger::OutputCompositionState>
+SurfaceFlinger::getDisplayAndLayerSnapshotsFromMainThread(
+ RenderAreaBuilderVariant& renderAreaBuilder, GetLayerSnapshotsFunction getLayerSnapshotsFn,
+ std::vector<sp<LayerFE>>& layerFEs) {
+ return mScheduler
+ ->schedule([=, this, &renderAreaBuilder, &layerFEs]() REQUIRES(kMainThreadContext) {
+ auto layers = getLayerSnapshotsFn();
+ for (auto& [layer, layerFE] : layers) {
+ attachReleaseFenceFutureToLayer(layer, layerFE.get(), ui::INVALID_LAYER_STACK);
+ }
+ layerFEs = extractLayerFEs(layers);
+ return getDisplayStateFromRenderAreaBuilder(renderAreaBuilder);
+ })
+ .get();
+}
+
void SurfaceFlinger::captureScreenCommon(RenderAreaBuilderVariant renderAreaBuilder,
- GetLayerSnapshotsFunction getLayerSnapshots,
+ GetLayerSnapshotsFunction getLayerSnapshotsFn,
ui::Size bufferSize, ui::PixelFormat reqPixelFormat,
bool allowProtected, bool grayscale,
const sp<IScreenCaptureListener>& captureListener) {
@@ -8175,74 +8178,185 @@
return;
}
- // Loop over all visible layers to see whether there's any protected layer. A protected layer is
- // typically a layer with DRM contents, or have the GRALLOC_USAGE_PROTECTED set on the buffer.
- // A protected layer has no implication on whether it's secure, which is explicitly set by
- // application to avoid being screenshot or drawn via unsecure display.
- const bool supportsProtected = getRenderEngine().supportsProtectedContent();
- bool hasProtectedLayer = false;
- if (allowProtected && supportsProtected) {
- auto layers = mScheduler->schedule([=]() { return getLayerSnapshots(); }).get();
- hasProtectedLayer = layersHasProtectedLayer(layers);
- }
- const bool isProtected = hasProtectedLayer && allowProtected && supportsProtected;
- const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER |
- GRALLOC_USAGE_HW_TEXTURE |
- (isProtected ? GRALLOC_USAGE_PROTECTED
- : GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
- sp<GraphicBuffer> buffer =
- getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(),
- static_cast<android_pixel_format>(reqPixelFormat),
- 1 /* layerCount */, usage, "screenshot");
+ if (FlagManager::getInstance().single_hop_screenshot() &&
+ FlagManager::getInstance().ce_fence_promise()) {
+ std::vector<sp<LayerFE>> layerFEs;
+ auto displayState =
+ getDisplayAndLayerSnapshotsFromMainThread(renderAreaBuilder, getLayerSnapshotsFn,
+ layerFEs);
- const status_t bufferStatus = buffer->initCheck();
- if (bufferStatus != OK) {
- // Animations may end up being really janky, but don't crash here.
- // Otherwise an irreponsible process may cause an SF crash by allocating
- // too much.
- ALOGE("%s: Buffer failed to allocate: %d", __func__, bufferStatus);
- invokeScreenCaptureError(bufferStatus, captureListener);
- return;
+ const bool supportsProtected = getRenderEngine().supportsProtectedContent();
+ bool hasProtectedLayer = false;
+ if (allowProtected && supportsProtected) {
+ hasProtectedLayer = layersHasProtectedLayer(layerFEs);
+ }
+ const bool isProtected = hasProtectedLayer && allowProtected && supportsProtected;
+ const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER |
+ GRALLOC_USAGE_HW_TEXTURE |
+ (isProtected ? GRALLOC_USAGE_PROTECTED
+ : GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+ sp<GraphicBuffer> buffer =
+ getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(),
+ static_cast<android_pixel_format>(reqPixelFormat),
+ 1 /* layerCount */, usage, "screenshot");
+
+ const status_t bufferStatus = buffer->initCheck();
+ if (bufferStatus != OK) {
+ // Animations may end up being really janky, but don't crash here.
+ // Otherwise an irreponsible process may cause an SF crash by allocating
+ // too much.
+ ALOGE("%s: Buffer failed to allocate: %d", __func__, bufferStatus);
+ invokeScreenCaptureError(bufferStatus, captureListener);
+ return;
+ }
+ const std::shared_ptr<renderengine::ExternalTexture> texture = std::make_shared<
+ renderengine::impl::ExternalTexture>(buffer, getRenderEngine(),
+ renderengine::impl::ExternalTexture::Usage::
+ WRITEABLE);
+ auto futureFence =
+ captureScreenshot(renderAreaBuilder, texture, false /* regionSampling */, grayscale,
+ isProtected, captureListener, displayState, layerFEs);
+ futureFence.get();
+
+ } else {
+ const bool supportsProtected = getRenderEngine().supportsProtectedContent();
+ bool hasProtectedLayer = false;
+ if (allowProtected && supportsProtected) {
+ auto layers = mScheduler->schedule([=]() { return getLayerSnapshotsFn(); }).get();
+ hasProtectedLayer = layersHasProtectedLayer(extractLayerFEs(layers));
+ }
+ const bool isProtected = hasProtectedLayer && allowProtected && supportsProtected;
+ const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER |
+ GRALLOC_USAGE_HW_TEXTURE |
+ (isProtected ? GRALLOC_USAGE_PROTECTED
+ : GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+ sp<GraphicBuffer> buffer =
+ getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(),
+ static_cast<android_pixel_format>(reqPixelFormat),
+ 1 /* layerCount */, usage, "screenshot");
+
+ const status_t bufferStatus = buffer->initCheck();
+ if (bufferStatus != OK) {
+ // Animations may end up being really janky, but don't crash here.
+ // Otherwise an irreponsible process may cause an SF crash by allocating
+ // too much.
+ ALOGE("%s: Buffer failed to allocate: %d", __func__, bufferStatus);
+ invokeScreenCaptureError(bufferStatus, captureListener);
+ return;
+ }
+ const std::shared_ptr<renderengine::ExternalTexture> texture = std::make_shared<
+ renderengine::impl::ExternalTexture>(buffer, getRenderEngine(),
+ renderengine::impl::ExternalTexture::Usage::
+ WRITEABLE);
+ auto futureFence = captureScreenshotLegacy(renderAreaBuilder, getLayerSnapshotsFn, texture,
+ false /* regionSampling */, grayscale,
+ isProtected, captureListener);
+ futureFence.get();
}
- const std::shared_ptr<renderengine::ExternalTexture> texture = std::make_shared<
- renderengine::impl::ExternalTexture>(buffer, getRenderEngine(),
- renderengine::impl::ExternalTexture::Usage::
- WRITEABLE);
- auto futureFence =
- captureScreenshot(renderAreaBuilder, getLayerSnapshots, texture,
- false /* regionSampling */, grayscale, isProtected, captureListener);
- futureFence.get();
}
-ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot(
- RenderAreaBuilderVariant renderAreaBuilder, GetLayerSnapshotsFunction getLayerSnapshots,
- const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
- bool grayscale, bool isProtected, const sp<IScreenCaptureListener>& captureListener) {
- ATRACE_CALL();
-
- auto takeScreenshotFn = [=, this, renderAreaBuilder = std::move(renderAreaBuilder)]() REQUIRES(
- kMainThreadContext) mutable -> ftl::SharedFuture<FenceResult> {
- // LayerSnapshots must be obtained from the main thread.
- auto layers = getLayerSnapshots();
-
+std::optional<SurfaceFlinger::OutputCompositionState>
+SurfaceFlinger::getDisplayStateFromRenderAreaBuilder(RenderAreaBuilderVariant& renderAreaBuilder) {
+ sp<const DisplayDevice> display = nullptr;
+ {
+ Mutex::Autolock lock(mStateLock);
if (auto* layerRenderAreaBuilder =
std::get_if<LayerRenderAreaBuilder>(&renderAreaBuilder)) {
// LayerSnapshotBuilder should only be accessed from the main thread.
- frontend::LayerSnapshot* snapshot =
+ const frontend::LayerSnapshot* snapshot =
mLayerSnapshotBuilder.getSnapshot(layerRenderAreaBuilder->layer->getSequence());
if (!snapshot) {
ALOGW("Couldn't find layer snapshot for %d",
layerRenderAreaBuilder->layer->getSequence());
} else {
layerRenderAreaBuilder->setLayerSnapshot(*snapshot);
+ display = findDisplay(
+ [layerStack = snapshot->outputFilter.layerStack](const auto& display) {
+ return display.getLayerStack() == layerStack;
+ });
}
+ } else if (auto* displayRenderAreaBuilder =
+ std::get_if<DisplayRenderAreaBuilder>(&renderAreaBuilder)) {
+ display = displayRenderAreaBuilder->displayWeak.promote();
}
+ if (display == nullptr) {
+ display = getDefaultDisplayDeviceLocked();
+ }
+
+ if (display != nullptr) {
+ return std::optional{display->getCompositionDisplay()->getState()};
+ }
+ }
+ return std::nullopt;
+}
+
+std::vector<sp<LayerFE>> SurfaceFlinger::extractLayerFEs(
+ const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) const {
+ std::vector<sp<LayerFE>> layerFEs;
+ layerFEs.reserve(layers.size());
+ for (const auto& [_, layerFE] : layers) {
+ layerFEs.push_back(layerFE);
+ }
+ return layerFEs;
+}
+
+ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot(
+ const RenderAreaBuilderVariant& renderAreaBuilder,
+ const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
+ bool grayscale, bool isProtected, const sp<IScreenCaptureListener>& captureListener,
+ std::optional<OutputCompositionState>& displayState, std::vector<sp<LayerFE>>& layerFEs) {
+ ATRACE_CALL();
+
+ ScreenCaptureResults captureResults;
+ std::unique_ptr<const RenderArea> renderArea =
+ std::visit([](auto&& arg) -> std::unique_ptr<RenderArea> { return arg.build(); },
+ renderAreaBuilder);
+
+ if (!renderArea) {
+ ALOGW("Skipping screen capture because of invalid render area.");
+ if (captureListener) {
+ captureResults.fenceResult = base::unexpected(NO_MEMORY);
+ captureListener->onScreenCaptureCompleted(captureResults);
+ }
+ return ftl::yield<FenceResult>(base::unexpected(NO_ERROR)).share();
+ }
+
+ // Empty vector needed to pass into renderScreenImpl for legacy path
+ std::vector<std::pair<Layer*, sp<android::LayerFE>>> layers;
+ ftl::SharedFuture<FenceResult> renderFuture =
+ renderScreenImpl(std::move(renderArea), buffer, regionSampling, grayscale, isProtected,
+ captureResults, displayState, layers, layerFEs);
+
+ if (captureListener) {
+ // Defer blocking on renderFuture back to the Binder thread.
+ return ftl::Future(std::move(renderFuture))
+ .then([captureListener, captureResults = std::move(captureResults)](
+ FenceResult fenceResult) mutable -> FenceResult {
+ captureResults.fenceResult = std::move(fenceResult);
+ captureListener->onScreenCaptureCompleted(captureResults);
+ return base::unexpected(NO_ERROR);
+ })
+ .share();
+ }
+ return renderFuture;
+}
+
+ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshotLegacy(
+ RenderAreaBuilderVariant renderAreaBuilder, GetLayerSnapshotsFunction getLayerSnapshotsFn,
+ const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
+ bool grayscale, bool isProtected, const sp<IScreenCaptureListener>& captureListener) {
+ ATRACE_CALL();
+
+ auto takeScreenshotFn = [=, this, renderAreaBuilder = std::move(renderAreaBuilder)]() REQUIRES(
+ kMainThreadContext) mutable -> ftl::SharedFuture<FenceResult> {
+ auto layers = getLayerSnapshotsFn();
if (FlagManager::getInstance().ce_fence_promise()) {
for (auto& [layer, layerFE] : layers) {
attachReleaseFenceFutureToLayer(layer, layerFE.get(), ui::INVALID_LAYER_STACK);
}
}
+ auto displayState = getDisplayStateFromRenderAreaBuilder(renderAreaBuilder);
ScreenCaptureResults captureResults;
std::unique_ptr<const RenderArea> renderArea =
@@ -8258,9 +8372,10 @@
return ftl::yield<FenceResult>(base::unexpected(NO_ERROR)).share();
}
+ auto layerFEs = extractLayerFEs(layers);
ftl::SharedFuture<FenceResult> renderFuture =
renderScreenImpl(std::move(renderArea), buffer, regionSampling, grayscale,
- isProtected, captureResults, layers);
+ isProtected, captureResults, displayState, layers, layerFEs);
if (captureListener) {
// Defer blocking on renderFuture back to the Binder thread.
@@ -8290,22 +8405,14 @@
}
ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
- std::unique_ptr<const RenderArea> renderArea, GetLayerSnapshotsFunction getLayerSnapshots,
- const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
- bool grayscale, bool isProtected, ScreenCaptureResults& captureResults) {
- auto layers = getLayerSnapshots();
- return renderScreenImpl(std::move(renderArea), buffer, regionSampling, grayscale, isProtected,
- captureResults, layers);
-}
-
-ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
std::unique_ptr<const RenderArea> renderArea,
const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
bool grayscale, bool isProtected, ScreenCaptureResults& captureResults,
- std::vector<std::pair<Layer*, sp<android::LayerFE>>>& layers) {
+ std::optional<OutputCompositionState>& displayState,
+ std::vector<std::pair<Layer*, sp<LayerFE>>>& layers, std::vector<sp<LayerFE>>& layerFEs) {
ATRACE_CALL();
- for (auto& [_, layerFE] : layers) {
+ for (auto& layerFE : layerFEs) {
frontend::LayerSnapshot* snapshot = layerFE->mSnapshot.get();
captureResults.capturedSecureLayers |= (snapshot->isVisible && snapshot->isSecure);
captureResults.capturedHdrLayers |= isHdrLayer(*snapshot);
@@ -8325,81 +8432,64 @@
captureResults.capturedDataspace = requestedDataspace;
- {
- Mutex::Autolock lock(mStateLock);
- const DisplayDevice* display = nullptr;
- if (parent) {
- const frontend::LayerSnapshot* snapshot =
- mLayerSnapshotBuilder.getSnapshot(parent->sequence);
- if (snapshot) {
- display = findDisplay([layerStack = snapshot->outputFilter.layerStack](
- const auto& display) {
- return display.getLayerStack() == layerStack;
- }).get();
- }
- }
+ const bool enableLocalTonemapping = FlagManager::getInstance().local_tonemap_screenshots() &&
+ !renderArea->getHintForSeamlessTransition();
- if (display == nullptr) {
- display = renderArea->getDisplayDevice().get();
- }
+ if (displayState) {
+ const auto& state = displayState.value();
+ captureResults.capturedDataspace =
+ pickBestDataspace(requestedDataspace, state, captureResults.capturedHdrLayers,
+ renderArea->getHintForSeamlessTransition());
+ sdrWhitePointNits = state.sdrWhitePointNits;
- if (display == nullptr) {
- display = getDefaultDisplayDeviceLocked().get();
- }
-
- if (display != nullptr) {
- const auto& state = display->getCompositionDisplay()->getState();
- captureResults.capturedDataspace =
- pickBestDataspace(requestedDataspace, display, captureResults.capturedHdrLayers,
- renderArea->getHintForSeamlessTransition());
- sdrWhitePointNits = state.sdrWhitePointNits;
-
- if (!captureResults.capturedHdrLayers) {
- displayBrightnessNits = sdrWhitePointNits;
- } else {
- displayBrightnessNits = state.displayBrightnessNits;
- // Only clamp the display brightness if this is not a seamless transition. Otherwise
- // for seamless transitions it's important to match the current display state as the
- // buffer will be shown under these same conditions, and we want to avoid any
- // flickers
+ if (!captureResults.capturedHdrLayers) {
+ displayBrightnessNits = sdrWhitePointNits;
+ } else {
+ displayBrightnessNits = state.displayBrightnessNits;
+ if (!enableLocalTonemapping) {
+ // Only clamp the display brightness if this is not a seamless transition.
+ // Otherwise for seamless transitions it's important to match the current
+ // display state as the buffer will be shown under these same conditions, and we
+ // want to avoid any flickers
if (sdrWhitePointNits > 1.0f && !renderArea->getHintForSeamlessTransition()) {
- // Restrict the amount of HDR "headroom" in the screenshot to avoid over-dimming
- // the SDR portion. 2.0 chosen by experimentation
+ // Restrict the amount of HDR "headroom" in the screenshot to avoid
+ // over-dimming the SDR portion. 2.0 chosen by experimentation
constexpr float kMaxScreenshotHeadroom = 2.0f;
displayBrightnessNits = std::min(sdrWhitePointNits * kMaxScreenshotHeadroom,
displayBrightnessNits);
}
}
+ }
- // Screenshots leaving the device should be colorimetric
- if (requestedDataspace == ui::Dataspace::UNKNOWN &&
- renderArea->getHintForSeamlessTransition()) {
- renderIntent = state.renderIntent;
- }
+ // Screenshots leaving the device should be colorimetric
+ if (requestedDataspace == ui::Dataspace::UNKNOWN &&
+ renderArea->getHintForSeamlessTransition()) {
+ renderIntent = state.renderIntent;
}
}
captureResults.buffer = capturedBuffer->getBuffer();
ui::LayerStack layerStack{ui::DEFAULT_LAYER_STACK};
- if (!layers.empty()) {
- const sp<LayerFE>& layerFE = layers.back().second;
+ if (!layerFEs.empty()) {
+ const sp<LayerFE>& layerFE = layerFEs.back();
layerStack = layerFE->getCompositionState()->outputFilter.layerStack;
}
- auto copyLayerFEs = [&layers]() {
- std::vector<sp<compositionengine::LayerFE>> layerFEs;
- layerFEs.reserve(layers.size());
- for (const auto& [_, layerFE] : layers) {
- layerFEs.push_back(layerFE);
+ auto copyLayerFEs = [&layerFEs]() {
+ std::vector<sp<compositionengine::LayerFE>> ceLayerFEs;
+ ceLayerFEs.reserve(layerFEs.size());
+ for (const auto& layerFE : layerFEs) {
+ ceLayerFEs.push_back(layerFE);
}
- return layerFEs;
+ return ceLayerFEs;
};
auto present = [this, buffer = capturedBuffer, dataspace = captureResults.capturedDataspace,
sdrWhitePointNits, displayBrightnessNits, grayscale, isProtected,
layerFEs = copyLayerFEs(), layerStack, regionSampling,
- renderArea = std::move(renderArea), renderIntent]() -> FenceResult {
+ renderArea = std::move(renderArea), renderIntent,
+ enableLocalTonemapping]() -> FenceResult {
std::unique_ptr<compositionengine::CompositionEngine> compositionEngine =
mFactory.createCompositionEngine();
compositionEngine->setRenderEngine(mRenderEngine.get());
@@ -8408,7 +8498,11 @@
.renderIntent = renderIntent};
float targetBrightness = 1.0f;
- if (dataspace == ui::Dataspace::BT2020_HLG) {
+ if (enableLocalTonemapping) {
+ // Boost the whole scene so that SDR white is at 1.0 while still communicating the hdr
+ // sdr ratio via display brightness / sdrWhite nits.
+ targetBrightness = sdrWhitePointNits / displayBrightnessNits;
+ } else if (dataspace == ui::Dataspace::BT2020_HLG) {
const float maxBrightnessNits = displayBrightnessNits / sdrWhitePointNits * 203;
// With a low dimming ratio, don't fit the entire curve. Otherwise mixed content
// will appear way too bright.
@@ -8434,7 +8528,8 @@
.treat170mAsSrgb = mTreat170mAsSrgb,
.dimInGammaSpaceForEnhancedScreenshots =
dimInGammaSpaceForEnhancedScreenshots,
- .isProtected = isProtected});
+ .isProtected = isProtected,
+ .enableLocalTonemapping = enableLocalTonemapping});
const float colorSaturation = grayscale ? 0 : 1;
compositionengine::CompositionRefreshArgs refreshArgs{
@@ -8456,8 +8551,16 @@
//
// TODO(b/196334700) Once we use RenderEngineThreaded everywhere we can always defer the call
// to CompositionEngine::present.
- auto presentFuture = mRenderEngine->isThreaded() ? ftl::defer(std::move(present)).share()
- : ftl::yield(present()).share();
+ ftl::SharedFuture<FenceResult> presentFuture;
+ if (FlagManager::getInstance().single_hop_screenshot() &&
+ FlagManager::getInstance().ce_fence_promise()) {
+ presentFuture = mRenderEngine->isThreaded()
+ ? ftl::yield(present()).share()
+ : mScheduler->schedule(std::move(present)).share();
+ } else {
+ presentFuture = mRenderEngine->isThreaded() ? ftl::defer(std::move(present)).share()
+ : ftl::yield(present()).share();
+ }
if (!FlagManager::getInstance().ce_fence_promise()) {
for (auto& [layer, layerFE] : layers) {
@@ -8833,7 +8936,8 @@
const auto status =
getHwComposer().setRefreshRateChangedCallbackDebugEnabled(id, enable);
if (status != NO_ERROR) {
- ALOGE("Error updating the refresh rate changed callback debug enabled");
+ ALOGE("Error %s refresh rate changed callback debug",
+ enable ? "enabling" : "disabling");
enableOverlay(/*setByHwc*/ false);
}
}
@@ -10334,6 +10438,11 @@
return gui::getSchedulingPolicy(outPolicy);
}
+binder::Status SurfaceComposerAIDL::notifyShutdown() {
+ TransactionTraceWriter::getInstance().invoke("systemShutdown_", /* overwrite= */ false);
+ return ::android::binder::Status::ok();
+}
+
status_t SurfaceComposerAIDL::checkAccessPermission(bool usePermissionCache) {
if (!mFlinger->callingThreadHasUnscopedSurfaceFlingerAccess(usePermissionCache)) {
IPCThreadState* ipc = IPCThreadState::self();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 0682e95..1230717 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -892,32 +892,46 @@
void attachReleaseFenceFutureToLayer(Layer* layer, LayerFE* layerFE, ui::LayerStack layerStack);
// Checks if a protected layer exists in a list of layers.
- bool layersHasProtectedLayer(const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) const;
+ bool layersHasProtectedLayer(const std::vector<sp<LayerFE>>& layers) const;
+
+ using OutputCompositionState = compositionengine::impl::OutputCompositionState;
+
+ std::optional<OutputCompositionState> getDisplayAndLayerSnapshotsFromMainThread(
+ RenderAreaBuilderVariant& renderAreaBuilder,
+ GetLayerSnapshotsFunction getLayerSnapshotsFn, std::vector<sp<LayerFE>>& layerFEs);
void captureScreenCommon(RenderAreaBuilderVariant, GetLayerSnapshotsFunction,
ui::Size bufferSize, ui::PixelFormat, bool allowProtected,
bool grayscale, const sp<IScreenCaptureListener>&);
+ std::optional<OutputCompositionState> getDisplayStateFromRenderAreaBuilder(
+ RenderAreaBuilderVariant& renderAreaBuilder) REQUIRES(kMainThreadContext);
+
+ // Legacy layer raw pointer is not safe to access outside the main thread.
+ // Creates a new vector consisting only of LayerFEs, which can be safely
+ // accessed outside the main thread.
+ std::vector<sp<LayerFE>> extractLayerFEs(
+ const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) const;
+
ftl::SharedFuture<FenceResult> captureScreenshot(
+ const RenderAreaBuilderVariant& renderAreaBuilder,
+ const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
+ bool grayscale, bool isProtected, const sp<IScreenCaptureListener>& captureListener,
+ std::optional<OutputCompositionState>& displayState,
+ std::vector<sp<LayerFE>>& layerFEs);
+
+ ftl::SharedFuture<FenceResult> captureScreenshotLegacy(
RenderAreaBuilderVariant, GetLayerSnapshotsFunction,
const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling,
bool grayscale, bool isProtected, const sp<IScreenCaptureListener>&);
- // Overloaded version of renderScreenImpl that is used when layer snapshots have
- // not yet been captured, and thus cannot yet be passed in as a parameter.
- // Needed for TestableSurfaceFlinger.
- ftl::SharedFuture<FenceResult> renderScreenImpl(
- std::unique_ptr<const RenderArea>, GetLayerSnapshotsFunction,
- const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling,
- bool grayscale, bool isProtected, ScreenCaptureResults&) EXCLUDES(mStateLock)
- REQUIRES(kMainThreadContext);
-
ftl::SharedFuture<FenceResult> renderScreenImpl(
std::unique_ptr<const RenderArea>,
const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling,
bool grayscale, bool isProtected, ScreenCaptureResults&,
- std::vector<std::pair<Layer*, sp<android::LayerFE>>>& layers) EXCLUDES(mStateLock)
- REQUIRES(kMainThreadContext);
+ std::optional<OutputCompositionState>& displayState,
+ std::vector<std::pair<Layer*, sp<LayerFE>>>& layers,
+ std::vector<sp<LayerFE>>& layerFEs);
// If the uid provided is not UNSET_UID, the traverse will skip any layers that don't have a
// matching ownerUid
@@ -1681,6 +1695,7 @@
binder::Status getStalledTransactionInfo(
int pid, std::optional<gui::StalledTransactionInfo>* outInfo) override;
binder::Status getSchedulingPolicy(gui::SchedulingPolicy* outPolicy) override;
+ binder::Status notifyShutdown() override;
private:
static const constexpr bool kUsePermissionCache = true;
diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
index b3e9fab..fc496b2 100644
--- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
+++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
@@ -247,7 +247,8 @@
proto.set_auto_refresh(layer.autoRefresh);
}
if (layer.what & layer_state_t::eTrustedOverlayChanged) {
- proto.set_is_trusted_overlay(layer.isTrustedOverlay);
+ proto.set_is_trusted_overlay(layer.trustedOverlay == gui::TrustedOverlay::ENABLED);
+ // TODO(b/339701674) update protos
}
if (layer.what & layer_state_t::eBufferCropChanged) {
LayerProtoHelper::writeToProto(layer.bufferCrop, proto.mutable_buffer_crop());
@@ -515,7 +516,8 @@
layer.autoRefresh = proto.auto_refresh();
}
if (proto.what() & layer_state_t::eTrustedOverlayChanged) {
- layer.isTrustedOverlay = proto.is_trusted_overlay();
+ layer.trustedOverlay = proto.is_trusted_overlay() ? gui::TrustedOverlay::ENABLED
+ : gui::TrustedOverlay::UNSET;
}
if (proto.what() & layer_state_t::eBufferCropChanged) {
LayerProtoHelper::readFromProto(proto.buffer_crop(), layer.bufferCrop);
diff --git a/services/surfaceflinger/common/Android.bp b/services/surfaceflinger/common/Android.bp
index 6b971a7..c3594bc 100644
--- a/services/surfaceflinger/common/Android.bp
+++ b/services/surfaceflinger/common/Android.bp
@@ -17,6 +17,7 @@
shared_libs: [
"libSurfaceFlingerProp",
"server_configurable_flags",
+ "libaconfig_storage_read_api_cc",
],
static_libs: [
"librenderengine_includes",
@@ -56,6 +57,7 @@
name: "libsurfaceflinger_common_deps",
shared_libs: [
"server_configurable_flags",
+ "libaconfig_storage_read_api_cc",
],
static_libs: [
"libsurfaceflinger_common",
@@ -69,6 +71,7 @@
name: "libsurfaceflinger_common_test_deps",
shared_libs: [
"server_configurable_flags",
+ "libaconfig_storage_read_api_cc",
],
static_libs: [
"libsurfaceflinger_common_test",
diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp
index 121629f..4216771 100644
--- a/services/surfaceflinger/common/FlagManager.cpp
+++ b/services/surfaceflinger/common/FlagManager.cpp
@@ -147,6 +147,10 @@
DUMP_READ_ONLY_FLAG(detached_mirror);
DUMP_READ_ONLY_FLAG(commit_not_composited);
DUMP_READ_ONLY_FLAG(local_tonemap_screenshots);
+ DUMP_READ_ONLY_FLAG(override_trusted_overlay);
+ DUMP_READ_ONLY_FLAG(flush_buffer_slots_to_uncache);
+ DUMP_READ_ONLY_FLAG(force_compile_graphite_renderengine);
+ DUMP_READ_ONLY_FLAG(single_hop_screenshot);
#undef DUMP_READ_ONLY_FLAG
#undef DUMP_SERVER_FLAG
@@ -244,6 +248,10 @@
FLAG_MANAGER_READ_ONLY_FLAG(detached_mirror, "");
FLAG_MANAGER_READ_ONLY_FLAG(commit_not_composited, "");
FLAG_MANAGER_READ_ONLY_FLAG(local_tonemap_screenshots, "debug.sf.local_tonemap_screenshots");
+FLAG_MANAGER_READ_ONLY_FLAG(override_trusted_overlay, "");
+FLAG_MANAGER_READ_ONLY_FLAG(flush_buffer_slots_to_uncache, "");
+FLAG_MANAGER_READ_ONLY_FLAG(force_compile_graphite_renderengine, "");
+FLAG_MANAGER_READ_ONLY_FLAG(single_hop_screenshot, "");
/// Trunk stable server flags ///
FLAG_MANAGER_SERVER_FLAG(refresh_rate_overlay_on_external_display, "")
diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h
index 4cf4453..22118ab 100644
--- a/services/surfaceflinger/common/include/common/FlagManager.h
+++ b/services/surfaceflinger/common/include/common/FlagManager.h
@@ -86,6 +86,10 @@
bool detached_mirror() const;
bool commit_not_composited() const;
bool local_tonemap_screenshots() const;
+ bool override_trusted_overlay() const;
+ bool flush_buffer_slots_to_uncache() const;
+ bool force_compile_graphite_renderengine() const;
+ bool single_hop_screenshot() const;
protected:
// overridden for unit tests
diff --git a/services/surfaceflinger/surfaceflinger_flags.aconfig b/services/surfaceflinger/surfaceflinger_flags.aconfig
index dea74d0..56bca7f 100644
--- a/services/surfaceflinger/surfaceflinger_flags.aconfig
+++ b/services/surfaceflinger/surfaceflinger_flags.aconfig
@@ -161,7 +161,7 @@
flag {
name: "graphite_renderengine"
namespace: "core_graphics"
- description: "Use Skia's Graphite Vulkan backend in RenderEngine."
+ description: "Compile AND enable Skia's Graphite Vulkan backend in RenderEngine. See also: force_compile_graphite_renderengine."
bug: "293371537"
is_fixed_read_only: true
}
diff --git a/services/surfaceflinger/surfaceflinger_flags_new.aconfig b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
index 5b94f07..f4d4ee9 100644
--- a/services/surfaceflinger/surfaceflinger_flags_new.aconfig
+++ b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
@@ -52,7 +52,26 @@
metadata {
purpose: PURPOSE_BUGFIX
}
-} # deprecate_vsync_sf
+} # detached_mirror
+
+flag {
+ name: "flush_buffer_slots_to_uncache"
+ namespace: "core_graphics"
+ description: "Flush DisplayCommands for disabled displays in order to uncache requested buffers."
+ bug: "330806421"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+} # flush_buffer_slots_to_uncache
+
+flag {
+ name: "force_compile_graphite_renderengine"
+ namespace: "core_graphics"
+ description: "Compile Skia's Graphite Vulkan backend in RenderEngine, but do NOT enable it, unless graphite_renderengine is also set. It can also be enabled with the debug.renderengine.graphite system property for testing. In contrast, the graphite_renderengine flag both compiles AND enables Graphite in RenderEngine."
+ bug: "293371537"
+ is_fixed_read_only: true
+} # force_compile_graphite_renderengine
flag {
name: "frame_rate_category_mrr"
@@ -85,6 +104,28 @@
} # local_tonemap_screenshots
flag {
+ name: "single_hop_screenshot"
+ namespace: "window_surfaces"
+ description: "Only access SF main thread once during a screenshot"
+ bug: "285553970"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+ } # single_hop_screenshot
+
+ flag {
+ name: "override_trusted_overlay"
+ namespace: "window_surfaces"
+ description: "Allow child to disable trusted overlay set by a parent layer"
+ bug: "339701674"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+} # override_trusted_overlay
+
+flag {
name: "vrr_bugfix_24q4"
namespace: "core_graphics"
description: "bug fixes for VRR"
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 0ddddbd..08973de 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -205,7 +205,8 @@
CaptureArgs::UNSET_UID, {}, visitor);
};
- auto getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers);
+ // TODO: Use SurfaceFlinger::getLayerSnapshotsForScreenshots instead of this legacy function
+ auto getLayerSnapshotsFn = RenderArea::fromTraverseLayersLambda(traverseLayers);
const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
@@ -215,7 +216,7 @@
HAL_PIXEL_FORMAT_RGBA_8888, 1,
usage);
- auto future = mFlinger.renderScreenImpl(std::move(renderArea), getLayerSnapshots,
+ auto future = mFlinger.renderScreenImpl(mDisplay, std::move(renderArea), getLayerSnapshotsFn,
mCaptureScreenBuffer, regionSampling);
ASSERT_TRUE(future.valid());
const auto fenceResult = future.get();
diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp
index 2b333f4..b79bdb4 100644
--- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp
@@ -777,4 +777,28 @@
EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expected);
}
+// (b/343901186)
+TEST_F(LayerHierarchyTest, cleanUpDanglingMirrorLayer) {
+ LayerHierarchyBuilder hierarchyBuilder;
+ hierarchyBuilder.update(mLifecycleManager);
+ mirrorLayer(/*layer*/ 14, /*parent*/ 1, /*layerToMirror*/ 2);
+ UPDATE_AND_VERIFY(hierarchyBuilder);
+
+ std::vector<uint32_t> expectedTraversalPath = {1, 11, 111, 12, 121, 122, 1221, 13, 14, 2, 2};
+ EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+ EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+ expectedTraversalPath = {};
+ EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);
+
+ // destroy layer handle
+ reparentLayer(2, UNASSIGNED_LAYER_ID);
+ destroyLayerHandle(2);
+ UPDATE_AND_VERIFY(hierarchyBuilder);
+ expectedTraversalPath = {1, 11, 111, 12, 121, 122, 1221, 13, 14};
+ EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+ EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+ expectedTraversalPath = {};
+ EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);
+}
+
} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
index fd15eef..8b3303c 100644
--- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
+++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
@@ -494,14 +494,14 @@
mLifecycleManager.applyTransactions(transactions);
}
- void setTrustedOverlay(uint32_t id, bool isTrustedOverlay) {
+ void setTrustedOverlay(uint32_t id, gui::TrustedOverlay trustedOverlay) {
std::vector<TransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
transactions.back().states.front().state.what = layer_state_t::eTrustedOverlayChanged;
transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.isTrustedOverlay = isTrustedOverlay;
+ transactions.back().states.front().state.trustedOverlay = trustedOverlay;
mLifecycleManager.applyTransactions(transactions);
}
diff --git a/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
index cfc8e99..97bd79f 100644
--- a/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
@@ -592,4 +592,41 @@
mLifecycleManager.commitChanges();
}
+TEST_F(LayerLifecycleManagerTest, isSimpleBufferUpdate) {
+ auto layer = rootLayer(1);
+
+ // no buffer changes
+ EXPECT_FALSE(layer->isSimpleBufferUpdate({}));
+
+ {
+ layer_state_t state;
+ state.what = layer_state_t::eBufferChanged;
+ EXPECT_TRUE(layer->isSimpleBufferUpdate(state));
+ }
+
+ {
+ layer_state_t state;
+ state.what = layer_state_t::eReparent | layer_state_t::eBufferChanged;
+ EXPECT_FALSE(layer->isSimpleBufferUpdate(state));
+ }
+
+ {
+ layer_state_t state;
+ state.what = layer_state_t::ePositionChanged | layer_state_t::eBufferChanged;
+ state.x = 9;
+ state.y = 10;
+ EXPECT_FALSE(layer->isSimpleBufferUpdate(state));
+ }
+
+ {
+ layer->x = 9;
+ layer->y = 10;
+ layer_state_t state;
+ state.what = layer_state_t::ePositionChanged | layer_state_t::eBufferChanged;
+ state.x = 9;
+ state.y = 10;
+ EXPECT_TRUE(layer->isSimpleBufferUpdate(state));
+ }
+}
+
} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
index 6b26459..bd0accd 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -1152,7 +1152,7 @@
TEST_F(LayerSnapshotTest, setTrustedOverlayForNonVisibleInput) {
hideLayer(1);
- setTrustedOverlay(1, true);
+ setTrustedOverlay(1, gui::TrustedOverlay::ENABLED);
Region touch{Rect{0, 0, 1000, 1000}};
setTouchableRegion(1, touch);
@@ -1333,4 +1333,85 @@
EXPECT_EQ(getSnapshot({.id = 111})->geomLayerTransform.ty(), 220);
}
+TEST_F(LayerSnapshotTest, overrideParentTrustedOverlayState) {
+ SET_FLAG_FOR_TEST(flags::override_trusted_overlay, true);
+ hideLayer(1);
+ setTrustedOverlay(1, gui::TrustedOverlay::ENABLED);
+
+ Region touch{Rect{0, 0, 1000, 1000}};
+ setTouchableRegion(1, touch);
+ setTouchableRegion(11, touch);
+ setTouchableRegion(111, touch);
+
+ UPDATE_AND_VERIFY(mSnapshotBuilder, {2});
+ EXPECT_TRUE(getSnapshot(1)->inputInfo.inputConfig.test(
+ gui::WindowInfo::InputConfig::TRUSTED_OVERLAY));
+ EXPECT_TRUE(getSnapshot(11)->inputInfo.inputConfig.test(
+ gui::WindowInfo::InputConfig::TRUSTED_OVERLAY));
+ EXPECT_TRUE(getSnapshot(111)->inputInfo.inputConfig.test(
+ gui::WindowInfo::InputConfig::TRUSTED_OVERLAY));
+
+ // disable trusted overlay and override parent state
+ setTrustedOverlay(11, gui::TrustedOverlay::DISABLED);
+ UPDATE_AND_VERIFY(mSnapshotBuilder, {2});
+ EXPECT_TRUE(getSnapshot(1)->inputInfo.inputConfig.test(
+ gui::WindowInfo::InputConfig::TRUSTED_OVERLAY));
+ EXPECT_FALSE(getSnapshot(11)->inputInfo.inputConfig.test(
+ gui::WindowInfo::InputConfig::TRUSTED_OVERLAY));
+ EXPECT_FALSE(getSnapshot(111)->inputInfo.inputConfig.test(
+ gui::WindowInfo::InputConfig::TRUSTED_OVERLAY));
+
+ // unset state and go back to default behavior of inheriting
+ // state
+ setTrustedOverlay(11, gui::TrustedOverlay::UNSET);
+ UPDATE_AND_VERIFY(mSnapshotBuilder, {2});
+ EXPECT_TRUE(getSnapshot(1)->inputInfo.inputConfig.test(
+ gui::WindowInfo::InputConfig::TRUSTED_OVERLAY));
+ EXPECT_TRUE(getSnapshot(11)->inputInfo.inputConfig.test(
+ gui::WindowInfo::InputConfig::TRUSTED_OVERLAY));
+ EXPECT_TRUE(getSnapshot(111)->inputInfo.inputConfig.test(
+ gui::WindowInfo::InputConfig::TRUSTED_OVERLAY));
+}
+
+TEST_F(LayerSnapshotTest, doNotOverrideParentTrustedOverlayState) {
+ SET_FLAG_FOR_TEST(flags::override_trusted_overlay, false);
+ hideLayer(1);
+ setTrustedOverlay(1, gui::TrustedOverlay::ENABLED);
+
+ Region touch{Rect{0, 0, 1000, 1000}};
+ setTouchableRegion(1, touch);
+ setTouchableRegion(11, touch);
+ setTouchableRegion(111, touch);
+
+ UPDATE_AND_VERIFY(mSnapshotBuilder, {2});
+ EXPECT_TRUE(getSnapshot(1)->inputInfo.inputConfig.test(
+ gui::WindowInfo::InputConfig::TRUSTED_OVERLAY));
+ EXPECT_TRUE(getSnapshot(11)->inputInfo.inputConfig.test(
+ gui::WindowInfo::InputConfig::TRUSTED_OVERLAY));
+ EXPECT_TRUE(getSnapshot(111)->inputInfo.inputConfig.test(
+ gui::WindowInfo::InputConfig::TRUSTED_OVERLAY));
+
+ // disable trusted overlay but flag is disabled so this behaves
+ // as UNSET
+ setTrustedOverlay(11, gui::TrustedOverlay::DISABLED);
+ UPDATE_AND_VERIFY(mSnapshotBuilder, {2});
+ EXPECT_TRUE(getSnapshot(1)->inputInfo.inputConfig.test(
+ gui::WindowInfo::InputConfig::TRUSTED_OVERLAY));
+ EXPECT_TRUE(getSnapshot(11)->inputInfo.inputConfig.test(
+ gui::WindowInfo::InputConfig::TRUSTED_OVERLAY));
+ EXPECT_TRUE(getSnapshot(111)->inputInfo.inputConfig.test(
+ gui::WindowInfo::InputConfig::TRUSTED_OVERLAY));
+
+ // unset state and go back to default behavior of inheriting
+ // state
+ setTrustedOverlay(11, gui::TrustedOverlay::UNSET);
+ UPDATE_AND_VERIFY(mSnapshotBuilder, {2});
+ EXPECT_TRUE(getSnapshot(1)->inputInfo.inputConfig.test(
+ gui::WindowInfo::InputConfig::TRUSTED_OVERLAY));
+ EXPECT_TRUE(getSnapshot(11)->inputInfo.inputConfig.test(
+ gui::WindowInfo::InputConfig::TRUSTED_OVERLAY));
+ EXPECT_TRUE(getSnapshot(111)->inputInfo.inputConfig.test(
+ gui::WindowInfo::InputConfig::TRUSTED_OVERLAY));
+}
+
} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 265f804..8c72a7d 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -485,23 +485,28 @@
return mFlinger->setPowerModeInternal(display, mode);
}
- auto renderScreenImpl(std::unique_ptr<const RenderArea> renderArea,
- SurfaceFlinger::GetLayerSnapshotsFunction traverseLayers,
+ auto renderScreenImpl(const sp<DisplayDevice> display,
+ std::unique_ptr<const RenderArea> renderArea,
+ SurfaceFlinger::GetLayerSnapshotsFunction getLayerSnapshotsFn,
const std::shared_ptr<renderengine::ExternalTexture>& buffer,
bool regionSampling) {
+ Mutex::Autolock lock(mFlinger->mStateLock);
+ ftl::FakeGuard guard(kMainThreadContext);
+
ScreenCaptureResults captureResults;
- return FTL_FAKE_GUARD(kMainThreadContext,
- mFlinger->renderScreenImpl(std::move(renderArea), traverseLayers,
- buffer, regionSampling,
- false /* grayscale */,
- false /* isProtected */, captureResults));
+ auto displayState = std::optional{display->getCompositionDisplay()->getState()};
+ auto layers = getLayerSnapshotsFn();
+ auto layerFEs = mFlinger->extractLayerFEs(layers);
+
+ return mFlinger->renderScreenImpl(std::move(renderArea), buffer, regionSampling,
+ false /* grayscale */, false /* isProtected */,
+ captureResults, displayState, layers, layerFEs);
}
auto traverseLayersInLayerStack(ui::LayerStack layerStack, int32_t uid,
std::unordered_set<uint32_t> excludeLayerIds,
const LayerVector::Visitor& visitor) {
- return mFlinger->SurfaceFlinger::traverseLayersInLayerStack(layerStack, uid,
- excludeLayerIds, visitor);
+ return mFlinger->traverseLayersInLayerStack(layerStack, uid, excludeLayerIds, visitor);
}
auto getDisplayNativePrimaries(const sp<IBinder>& displayToken,
diff --git a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
index eafba0a..5109ea6 100644
--- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
@@ -535,6 +535,28 @@
}
}
+TEST_F(VSyncPredictorTest, isVSyncInPhaseWithRenderRate) {
+ SET_FLAG_FOR_TEST(flags::vrr_bugfix_24q4, true);
+ auto last = mNow;
+ for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(last + mPeriod));
+ mNow += mPeriod;
+ last = mNow;
+ tracker.addVsyncTimestamp(mNow);
+ }
+
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + mPeriod));
+ EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + mPeriod), Eq(mNow + 2 * mPeriod));
+
+ const auto renderRateFps = Fps::fromPeriodNsecs(mPeriod * 2);
+ tracker.setRenderRate(renderRateFps, /*applyImmediately*/ true);
+
+ EXPECT_FALSE(tracker.isVSyncInPhase(mNow, renderRateFps));
+ EXPECT_TRUE(tracker.isVSyncInPhase(mNow + mPeriod, renderRateFps));
+ EXPECT_FALSE(tracker.isVSyncInPhase(mNow + 2 * mPeriod, renderRateFps));
+ EXPECT_TRUE(tracker.isVSyncInPhase(mNow + 3 * mPeriod, renderRateFps));
+}
+
TEST_F(VSyncPredictorTest, isVSyncInPhaseForDivisors) {
auto last = mNow;
for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 7ea98f5..3f89960 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -964,14 +964,20 @@
PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
const ProcHook* hook = GetProcHook(pName);
+ PFN_vkVoidFunction drv_func = GetData(device).driver.GetDeviceProcAddr(device, pName);
+
if (!hook)
- return GetData(device).driver.GetDeviceProcAddr(device, pName);
+ return drv_func;
if (hook->type != ProcHook::DEVICE) {
ALOGE("internal vkGetDeviceProcAddr called for %s", pName);
return nullptr;
}
+ // Don't hook if we don't have a device entry function below for the core function.
+ if (!drv_func && (hook->extension >= ProcHook::EXTENSION_CORE_1_0))
+ return nullptr;
+
return (GetData(device).hook_extensions[hook->extension]) ? hook->proc
: nullptr;
}
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 74d3d9d..9e67725 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -1174,7 +1174,8 @@
pSurfaceFormat);
if (surfaceCompressionProps &&
- driver.GetPhysicalDeviceImageFormatProperties2KHR) {
+ (driver.GetPhysicalDeviceImageFormatProperties2KHR ||
+ driver.GetPhysicalDeviceImageFormatProperties2)) {
VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = {};
imageFormatInfo.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2;
@@ -1205,7 +1206,7 @@
imageFormatProps.pNext = &compressionProps;
VkResult compressionRes =
- driver.GetPhysicalDeviceImageFormatProperties2KHR(
+ GetPhysicalDeviceImageFormatProperties2(
physicalDevice, &imageFormatInfo,
&imageFormatProps);
if (compressionRes == VK_SUCCESS) {
diff --git a/vulkan/scripts/driver_generator.py b/vulkan/scripts/driver_generator.py
index 78b550c..48c0ae9 100644
--- a/vulkan/scripts/driver_generator.py
+++ b/vulkan/scripts/driver_generator.py
@@ -239,6 +239,8 @@
f.write(gencom.indent(2) + gencom.base_ext_name(ext) + ',\n')
f.write('\n')
+ # EXTENSION_CORE_xxx API list must be the last set of enums after the extensions.
+ # This allows to easily identify "a" core function hook
for version in gencom.version_code_list:
f.write(gencom.indent(2) + 'EXTENSION_CORE_' + version + ',\n')