Merge "SF: Add composition strategy prediction stats" into tm-dev
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 1c5aa4f..397d432 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -473,7 +473,8 @@
StringPrintf("%smisc/installd/using_project_ids", android_data_dir.c_str());
sUsingProjectIdsFlag = access(using_project_ids.c_str(), F_OK) == 0;
});
- return sUsingProjectIdsFlag;
+ // return sUsingProjectIdsFlag;
+ return false;
}
static int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid, gid_t gid,
@@ -632,8 +633,9 @@
}
static binder::Status createAppDataDirs(const std::string& path, int32_t uid, int32_t gid,
- int32_t* previousUid, int32_t cacheGid,
- const std::string& seInfo, mode_t targetMode) {
+ int32_t previousUid, int32_t cacheGid,
+ const std::string& seInfo, mode_t targetMode,
+ long projectIdApp, long projectIdCache) {
struct stat st{};
bool parent_dir_exists = (stat(path.c_str(), &st) == 0);
@@ -643,25 +645,17 @@
bool code_cache_exists = (access(code_cache_path.c_str(), F_OK) == 0);
if (parent_dir_exists) {
- if (*previousUid < 0) {
- // If previousAppId is -1 in CreateAppDataArgs, we will assume the current owner
- // of the directory as previousUid. This is required because it is not always possible
- // to chown app data during app upgrade (e.g. secondary users' CE storage not unlocked)
- *previousUid = st.st_uid;
- }
- if (*previousUid != uid) {
- if (!chown_app_dir(path, uid, *previousUid, cacheGid)) {
+ if (previousUid > 0 && previousUid != uid) {
+ if (!chown_app_dir(path, uid, previousUid, cacheGid)) {
return error("Failed to chown " + path);
}
}
}
// Prepare only the parent app directory
- long project_id_app = get_project_id(uid, PROJECT_ID_APP_START);
- long project_id_cache_app = get_project_id(uid, PROJECT_ID_APP_CACHE_START);
- if (prepare_app_dir(path, targetMode, uid, gid, project_id_app) ||
- prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid, project_id_cache_app) ||
- prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid, project_id_cache_app)) {
+ if (prepare_app_dir(path, targetMode, uid, gid, projectIdApp) ||
+ prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid, projectIdCache) ||
+ prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid, projectIdCache)) {
return error("Failed to prepare " + path);
}
@@ -702,12 +696,9 @@
int32_t uid = multiuser_get_uid(userId, appId);
- // If previousAppId < 0, we will use the existing app data owner as previousAppUid
- // If previousAppId == 0, we use uid as previousUid (no data migration will happen)
- // if previousAppId > 0, an app is upgrading and changing its app ID
- int32_t previousUid = previousAppId > 0
- ? (int32_t) multiuser_get_uid(userId, previousAppId)
- : (previousAppId == 0 ? uid : -1);
+ // If previousAppId > 0, an app is changing its app ID
+ int32_t previousUid =
+ previousAppId > 0 ? (int32_t)multiuser_get_uid(userId, previousAppId) : -1;
int32_t cacheGid = multiuser_get_cache_gid(userId, appId);
mode_t targetMode = targetSdkVersion >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751;
@@ -717,10 +708,14 @@
cacheGid = uid;
}
+ long projectIdApp = get_project_id(uid, PROJECT_ID_APP_START);
+ long projectIdCache = get_project_id(uid, PROJECT_ID_APP_CACHE_START);
+
if (flags & FLAG_STORAGE_CE) {
auto path = create_data_user_ce_package_path(uuid_, userId, pkgname);
- auto status = createAppDataDirs(path, uid, uid, &previousUid, cacheGid, seInfo, targetMode);
+ auto status = createAppDataDirs(path, uid, uid, previousUid, cacheGid, seInfo, targetMode,
+ projectIdApp, projectIdCache);
if (!status.isOk()) {
return status;
}
@@ -745,11 +740,12 @@
if (flags & FLAG_STORAGE_DE) {
auto path = create_data_user_de_package_path(uuid_, userId, pkgname);
- auto status = createAppDataDirs(path, uid, uid, &previousUid, cacheGid, seInfo, targetMode);
+ auto status = createAppDataDirs(path, uid, uid, previousUid, cacheGid, seInfo, targetMode,
+ projectIdApp, projectIdCache);
if (!status.isOk()) {
return status;
}
- if (previousUid != uid) {
+ if (previousUid > 0 && previousUid != uid) {
chown_app_profile_dir(packageName, appId, userId);
}
@@ -945,8 +941,12 @@
}
const int32_t sandboxUid = multiuser_get_sdk_sandbox_uid(userId, appId);
int32_t previousSandboxUid = multiuser_get_sdk_sandbox_uid(userId, previousAppId);
- auto status = createAppDataDirs(path, sandboxUid, AID_NOBODY, &previousSandboxUid,
- cacheGid, seInfo, 0700 | S_ISGID);
+ int32_t appUid = multiuser_get_uid(userId, appId);
+ long projectIdApp = get_project_id(appUid, PROJECT_ID_APP_START);
+ long projectIdCache = get_project_id(appUid, PROJECT_ID_APP_CACHE_START);
+ auto status =
+ createAppDataDirs(path, sandboxUid, AID_NOBODY, previousSandboxUid, cacheGid,
+ seInfo, 0700 | S_ISGID, projectIdApp, projectIdCache);
if (!status.isOk()) {
res = status;
continue;
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
index 162e668..f86f1d5 100644
--- a/cmds/installd/tests/installd_service_test.cpp
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -509,97 +509,7 @@
system(removeCommand.c_str());
}
}
-TEST_F(ServiceTest, GetAppSizeProjectID_UID) {
- struct stat s;
- std::string externalPicDir =
- StringPrintf("%s/Pictures", create_data_media_path(nullptr, 0).c_str());
- if (stat(externalPicDir.c_str(), &s) == 0) {
- // fetch the appId from the uid of the external storage owning app
- int32_t externalStorageAppId = multiuser_get_app_id(s.st_uid);
- // Fetch Package Name for the external storage owning app uid
- std::string pkg = get_package_name(s.st_uid);
- std::vector<int64_t> externalStorageSize, externalStorageSizeAfterAddingCacheFile;
- std::vector<int64_t> ceDataInodes;
-
- std::vector<std::string> codePaths;
- std::vector<std::string> packageNames;
- // set up parameters
- packageNames.push_back(pkg);
- ceDataInodes.push_back(0);
- // initialise the mounts
- service->invalidateMounts();
- auto using_project_ids =
- StringPrintf("%smisc/installd/using_project_ids", android_data_dir.c_str());
- bool usingProjectIds = access(using_project_ids.c_str(), F_OK) == 0;
- if (!usingProjectIds) {
- service->setFirstBoot();
- }
-
- if (access(using_project_ids.c_str(), F_OK) != 0) {
- // projectids is not used, so check that ioctl features should be absent
- auto temp_path = StringPrintf("%smisc/installd/ioctl_check", android_data_dir.c_str());
-
- if (access(temp_path.c_str(), F_OK) != 0) {
- open(temp_path.c_str(), O_CREAT | O_TRUNC | O_RDWR | O_CLOEXEC, 0644);
- bool result = set_quota_project_id(temp_path, 0, false) == 0;
- // delete the temp file
- // remove the external file
- remove(temp_path.c_str());
- // since using_project_ids file is not present, so ioctl settings should be absent
- // that is denoted by the result of setting project id flag as false
- ASSERT_FALSE(result);
- }
- }
- // call the getAppSize to get the current size of the external storage owning app
- service->getAppSize(std::nullopt, packageNames, 0, InstalldNativeService::FLAG_USE_QUOTA,
- externalStorageAppId, ceDataInodes, codePaths, &externalStorageSize);
- // add a file with 20MB size to the external storage
- std::string externalStorageCacheDir =
- StringPrintf("%s/%s/cache", create_data_user_ce_path(nullptr, 0).c_str(),
- pkg.c_str());
- std::string cacheFileLocation =
- StringPrintf("%s/%s", externalStorageCacheDir.c_str(), "External.jpg");
- std::string externalFileContentCommand =
- StringPrintf("dd if=/dev/zero of=%s bs=1M count=20", cacheFileLocation.c_str());
- system(externalFileContentCommand.c_str());
- // call the getAppSize again to get the new size of the external storage owning app
- service->getAppSize(std::nullopt, packageNames, 0, InstalldNativeService::FLAG_USE_QUOTA,
- externalStorageAppId, ceDataInodes, codePaths,
- &externalStorageSizeAfterAddingCacheFile);
- // check that the size of cache and data increases when cache file is added
- int64_t sizeDiffData = externalStorageSizeAfterAddingCacheFile[1] - externalStorageSize[1];
- int64_t sizeDiffCache = externalStorageSizeAfterAddingCacheFile[2] - externalStorageSize[2];
- ASSERT_TRUE(sizeDiffData == sizeDiffCache);
- // remove the external file
- std::string removeCommand = StringPrintf("rm -f %s", cacheFileLocation.c_str());
- system(removeCommand.c_str());
- // remove the setFirstBoot setting
- std::string removeCommand2 = "rm -f /data/misc/installd/using_project_ids";
- system(removeCommand2.c_str());
- // Do now without project id
- std::vector<int64_t> sizeWithUID, sizeWithUIDAfterAddingCacheFile;
- // call the getAppSize to get the current size of the external storage owning app
- service->getAppSize(std::nullopt, packageNames, 0, InstalldNativeService::FLAG_USE_QUOTA,
- externalStorageAppId, ceDataInodes, codePaths, &sizeWithUID);
- // add a file with 20MB size to the external storage
- system(externalFileContentCommand.c_str());
- // call the getAppSize again to get the new size of the external storage owning app
- service->getAppSize(std::nullopt, packageNames, 0, InstalldNativeService::FLAG_USE_QUOTA,
- externalStorageAppId, ceDataInodes, codePaths,
- &sizeWithUIDAfterAddingCacheFile);
- // check that the size of cache and data increases when cache file is added
- sizeDiffData = sizeWithUIDAfterAddingCacheFile[1] - sizeWithUID[1];
- sizeDiffCache = sizeWithUIDAfterAddingCacheFile[2] - sizeWithUID[2];
- ASSERT_TRUE(sizeDiffData == sizeDiffCache);
- // remove the external file
- system(removeCommand.c_str());
- // reset the using_project_id if it was initially set
- if (usingProjectIds) {
- service->setFirstBoot();
- }
- }
-}
TEST_F(ServiceTest, GetAppSizeWrongSizes) {
int32_t externalStorageAppId = -1;
std::vector<int64_t> externalStorageSize;
diff --git a/include/android/sensor.h b/include/android/sensor.h
index c714b05..6112d5f 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -213,6 +213,13 @@
*/
ASENSOR_TYPE_HEART_BEAT = 31,
/**
+ * A constant describing a dynamic sensor meta event sensor.
+ *
+ * A sensor event of this type is received when a dynamic sensor is added to or removed from
+ * the system. This sensor type should always use special trigger report mode.
+ */
+ ASENSOR_TYPE_DYNAMIC_SENSOR_META = 32,
+ /**
* This sensor type is for delivering additional sensor information aside
* from sensor event data.
*
@@ -761,6 +768,10 @@
* Each time this is called, the previously returned list is deallocated and
* must no longer be used.
*
+ * Clients should call this if they receive a sensor update from
+ * {@link ASENSOR_TYPE_DYNAMIC_SENSOR_META} indicating the sensors have changed.
+ * If this happens, previously received lists from this method will be stale.
+ *
* Available since API level 33.
*
* \param manager the {@link ASensorManager} instance obtained from
diff --git a/libs/binder/ndk/include_platform/android/binder_stability.h b/libs/binder/ndk/include_platform/android/binder_stability.h
index f113ba8..d0cd11f 100644
--- a/libs/binder/ndk/include_platform/android/binder_stability.h
+++ b/libs/binder/ndk/include_platform/android/binder_stability.h
@@ -97,6 +97,10 @@
*
* This interface has system<->vendor stability
*/
+// b/227835797 - can't use __INTRODUCED_IN(30) because old targets load this code
+#if __ANDROID_MIN_SDK_VERSION__ < 30
+__attribute__((weak))
+#endif // __ANDROID_MIN_SDK_VERSION__ < 30
void AIBinder_markVintfStability(AIBinder* binder);
__END_DECLS
diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs
index e3e4730..4df557b 100644
--- a/libs/binder/rust/src/proxy.rs
+++ b/libs/binder/rust/src/proxy.rs
@@ -575,6 +575,20 @@
cookie_decr_refcount: unsafe extern "C" fn(*mut c_void),
}
+/// # Safety
+///
+/// A `DeathRecipient` is a wrapper around `AIBinder_DeathRecipient` and a pointer
+/// to a `Fn` which is `Sync` and `Send` (the cookie field). As
+/// `AIBinder_DeathRecipient` is threadsafe, this structure is too.
+unsafe impl Send for DeathRecipient {}
+
+/// # Safety
+///
+/// A `DeathRecipient` is a wrapper around `AIBinder_DeathRecipient` and a pointer
+/// to a `Fn` which is `Sync` and `Send` (the cookie field). As
+/// `AIBinder_DeathRecipient` is threadsafe, this structure is too.
+unsafe impl Sync for DeathRecipient {}
+
impl DeathRecipient {
/// Create a new death recipient that will call the given callback when its
/// associated object dies.
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 2da48b8..24d39fe 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -226,26 +226,6 @@
return result;
}
- void setPowerMode(const sp<IBinder>& display, int mode) override {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- data.writeStrongBinder(display);
- data.writeInt32(mode);
- remote()->transact(BnSurfaceComposer::SET_POWER_MODE, data, &reply);
- }
-
- status_t getDisplayState(const sp<IBinder>& display, ui::DisplayState* state) override {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- data.writeStrongBinder(display);
- remote()->transact(BnSurfaceComposer::GET_DISPLAY_STATE, data, &reply);
- const status_t result = reply.readInt32();
- if (result == NO_ERROR) {
- memcpy(state, reply.readInplace(sizeof(ui::DisplayState)), sizeof(ui::DisplayState));
- }
- return result;
- }
-
status_t getStaticDisplayInfo(const sp<IBinder>& display,
ui::StaticDisplayInfo* info) override {
Parcel data, reply;
@@ -268,20 +248,6 @@
return reply.read(*info);
}
- status_t getDisplayStats(const sp<IBinder>& display, DisplayStatInfo* stats) override {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- data.writeStrongBinder(display);
- remote()->transact(BnSurfaceComposer::GET_DISPLAY_STATS, data, &reply);
- status_t result = reply.readInt32();
- if (result == NO_ERROR) {
- memcpy(stats,
- reply.readInplace(sizeof(DisplayStatInfo)),
- sizeof(DisplayStatInfo));
- }
- return result;
- }
-
status_t getDisplayNativePrimaries(const sp<IBinder>& display,
ui::DisplayPrimaries& primaries) override {
Parcel data, reply;
@@ -333,29 +299,6 @@
return static_cast<status_t>(reply.readInt32());
}
- // TODO(b/213909104) : Add unit tests to verify surface flinger boot time APIs
- status_t getBootDisplayModeSupport(bool* outSupport) const override {
- Parcel data, reply;
- status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (error != NO_ERROR) {
- ALOGE("getBootDisplayModeSupport: failed to write interface token: %d", error);
- return error;
- }
- error = remote()->transact(BnSurfaceComposer::GET_BOOT_DISPLAY_MODE_SUPPORT, data, &reply);
- if (error != NO_ERROR) {
- ALOGE("getBootDisplayModeSupport: failed to transact: %d", error);
- return error;
- }
- bool support;
- error = reply.readBool(&support);
- if (error != NO_ERROR) {
- ALOGE("getBootDisplayModeSupport: failed to read support: %d", error);
- return error;
- }
- *outSupport = support;
- return NO_ERROR;
- }
-
status_t setBootDisplayMode(const sp<IBinder>& display,
ui::DisplayModeId displayModeId) override {
Parcel data, reply;
@@ -381,73 +324,6 @@
return result;
}
- status_t clearBootDisplayMode(const sp<IBinder>& display) override {
- Parcel data, reply;
- status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (result != NO_ERROR) {
- ALOGE("clearBootDisplayMode failed to writeInterfaceToken: %d", result);
- return result;
- }
- result = data.writeStrongBinder(display);
- if (result != NO_ERROR) {
- ALOGE("clearBootDisplayMode failed to writeStrongBinder: %d", result);
- return result;
- }
- result = remote()->transact(BnSurfaceComposer::CLEAR_BOOT_DISPLAY_MODE, data, &reply);
- if (result != NO_ERROR) {
- ALOGE("clearBootDisplayMode failed to transact: %d", result);
- }
- return result;
- }
-
- void setAutoLowLatencyMode(const sp<IBinder>& display, bool on) override {
- Parcel data, reply;
- status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (result != NO_ERROR) {
- ALOGE("setAutoLowLatencyMode failed to writeInterfaceToken: %d", result);
- return;
- }
-
- result = data.writeStrongBinder(display);
- if (result != NO_ERROR) {
- ALOGE("setAutoLowLatencyMode failed to writeStrongBinder: %d", result);
- return;
- }
- result = data.writeBool(on);
- if (result != NO_ERROR) {
- ALOGE("setAutoLowLatencyMode failed to writeBool: %d", result);
- return;
- }
- result = remote()->transact(BnSurfaceComposer::SET_AUTO_LOW_LATENCY_MODE, data, &reply);
- if (result != NO_ERROR) {
- ALOGE("setAutoLowLatencyMode failed to transact: %d", result);
- return;
- }
- }
-
- void setGameContentType(const sp<IBinder>& display, bool on) override {
- Parcel data, reply;
- status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (result != NO_ERROR) {
- ALOGE("setGameContentType failed to writeInterfaceToken: %d", result);
- return;
- }
- result = data.writeStrongBinder(display);
- if (result != NO_ERROR) {
- ALOGE("setGameContentType failed to writeStrongBinder: %d", result);
- return;
- }
- result = data.writeBool(on);
- if (result != NO_ERROR) {
- ALOGE("setGameContentType failed to writeBool: %d", result);
- return;
- }
- result = remote()->transact(BnSurfaceComposer::SET_GAME_CONTENT_TYPE, data, &reply);
- if (result != NO_ERROR) {
- ALOGE("setGameContentType failed to transact: %d", result);
- }
- }
-
status_t clearAnimationFrameStats() override {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
@@ -722,26 +598,6 @@
return error;
}
- status_t isWideColorDisplay(const sp<IBinder>& token,
- bool* outIsWideColorDisplay) const override {
- Parcel data, reply;
- status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (error != NO_ERROR) {
- return error;
- }
- error = data.writeStrongBinder(token);
- if (error != NO_ERROR) {
- return error;
- }
-
- error = remote()->transact(BnSurfaceComposer::IS_WIDE_COLOR_DISPLAY, data, &reply);
- if (error != NO_ERROR) {
- return error;
- }
- error = reply.readBool(outIsWideColorDisplay);
- return error;
- }
-
status_t addRegionSamplingListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle,
const sp<IRegionSamplingListener>& listener) override {
Parcel data, reply;
@@ -974,109 +830,6 @@
return reply.readInt32();
}
- status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken,
- bool* outSupport) const override {
- Parcel data, reply;
- status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (error != NO_ERROR) {
- ALOGE("getDisplayBrightnessSupport: failed to write interface token: %d", error);
- return error;
- }
- error = data.writeStrongBinder(displayToken);
- if (error != NO_ERROR) {
- ALOGE("getDisplayBrightnessSupport: failed to write display token: %d", error);
- return error;
- }
- error = remote()->transact(BnSurfaceComposer::GET_DISPLAY_BRIGHTNESS_SUPPORT, data, &reply);
- if (error != NO_ERROR) {
- ALOGE("getDisplayBrightnessSupport: failed to transact: %d", error);
- return error;
- }
- bool support;
- error = reply.readBool(&support);
- if (error != NO_ERROR) {
- ALOGE("getDisplayBrightnessSupport: failed to read support: %d", error);
- return error;
- }
- *outSupport = support;
- return NO_ERROR;
- }
-
- status_t setDisplayBrightness(const sp<IBinder>& displayToken,
- const gui::DisplayBrightness& brightness) override {
- Parcel data, reply;
- status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (error != NO_ERROR) {
- ALOGE("setDisplayBrightness: failed to write interface token: %d", error);
- return error;
- }
- error = data.writeStrongBinder(displayToken);
- if (error != NO_ERROR) {
- ALOGE("setDisplayBrightness: failed to write display token: %d", error);
- return error;
- }
- error = data.writeParcelable(brightness);
- if (error != NO_ERROR) {
- ALOGE("setDisplayBrightness: failed to write brightness: %d", error);
- return error;
- }
- error = remote()->transact(BnSurfaceComposer::SET_DISPLAY_BRIGHTNESS, data, &reply);
- if (error != NO_ERROR) {
- ALOGE("setDisplayBrightness: failed to transact: %d", error);
- return error;
- }
- return NO_ERROR;
- }
-
- status_t addHdrLayerInfoListener(const sp<IBinder>& displayToken,
- const sp<gui::IHdrLayerInfoListener>& listener) override {
- Parcel data, reply;
- SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor());
- SAFE_PARCEL(data.writeStrongBinder, displayToken);
- SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(listener));
- const status_t error =
- remote()->transact(BnSurfaceComposer::ADD_HDR_LAYER_INFO_LISTENER, data, &reply);
- if (error != OK) {
- ALOGE("addHdrLayerInfoListener: Failed to transact; error = %d", error);
- }
- return error;
- }
-
- status_t removeHdrLayerInfoListener(const sp<IBinder>& displayToken,
- const sp<gui::IHdrLayerInfoListener>& listener) override {
- Parcel data, reply;
- SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor());
- SAFE_PARCEL(data.writeStrongBinder, displayToken);
- SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(listener));
- const status_t error =
- remote()->transact(BnSurfaceComposer::REMOVE_HDR_LAYER_INFO_LISTENER, data, &reply);
- if (error != OK) {
- ALOGE("removeHdrLayerInfoListener: Failed to transact; error = %d", error);
- }
- return error;
- }
-
- status_t notifyPowerBoost(int32_t boostId) override {
- Parcel data, reply;
- status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (error != NO_ERROR) {
- ALOGE("notifyPowerBoost: failed to write interface token: %d", error);
- return error;
- }
- error = data.writeInt32(boostId);
- if (error != NO_ERROR) {
- ALOGE("notifyPowerBoost: failed to write boostId: %d", error);
- return error;
- }
- error = remote()->transact(BnSurfaceComposer::NOTIFY_POWER_BOOST, data, &reply,
- IBinder::FLAG_ONEWAY);
- if (error != NO_ERROR) {
- ALOGE("notifyPowerBoost: failed to transact: %d", error);
- return error;
- }
- return NO_ERROR;
- }
-
status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor,
float lightPosY, float lightPosZ, float lightRadius) override {
Parcel data, reply;
@@ -1392,18 +1145,6 @@
reply->writeStrongBinder(IInterface::asBinder(connection));
return NO_ERROR;
}
- case GET_DISPLAY_STATE: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- ui::DisplayState state;
- const sp<IBinder> display = data.readStrongBinder();
- const status_t result = getDisplayState(display, &state);
- reply->writeInt32(result);
- if (result == NO_ERROR) {
- memcpy(reply->writeInplace(sizeof(ui::DisplayState)), &state,
- sizeof(ui::DisplayState));
- }
- return NO_ERROR;
- }
case GET_STATIC_DISPLAY_INFO: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
ui::StaticDisplayInfo info;
@@ -1424,18 +1165,6 @@
SAFE_PARCEL(reply->write, info);
return NO_ERROR;
}
- case GET_DISPLAY_STATS: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- DisplayStatInfo stats;
- sp<IBinder> display = data.readStrongBinder();
- status_t result = getDisplayStats(display, &stats);
- reply->writeInt32(result);
- if (result == NO_ERROR) {
- memcpy(reply->writeInplace(sizeof(DisplayStatInfo)),
- &stats, sizeof(DisplayStatInfo));
- }
- return NO_ERROR;
- }
case GET_DISPLAY_NATIVE_PRIMARIES: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
ui::DisplayPrimaries primaries;
@@ -1475,15 +1204,6 @@
result = reply->writeInt32(result);
return result;
}
- case GET_BOOT_DISPLAY_MODE_SUPPORT: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- bool support = false;
- status_t result = getBootDisplayModeSupport(&support);
- if (result == NO_ERROR) {
- reply->writeBool(support);
- }
- return result;
- }
case SET_BOOT_DISPLAY_MODE: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IBinder> display = nullptr;
@@ -1500,50 +1220,6 @@
}
return setBootDisplayMode(display, displayModeId);
}
- case CLEAR_BOOT_DISPLAY_MODE: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> display = nullptr;
- status_t result = data.readStrongBinder(&display);
- if (result != NO_ERROR) {
- ALOGE("clearBootDisplayMode failed to readStrongBinder: %d", result);
- return result;
- }
- return clearBootDisplayMode(display);
- }
- case SET_AUTO_LOW_LATENCY_MODE: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> display = nullptr;
- status_t result = data.readStrongBinder(&display);
- if (result != NO_ERROR) {
- ALOGE("setAutoLowLatencyMode failed to readStrongBinder: %d", result);
- return result;
- }
- bool setAllm = false;
- result = data.readBool(&setAllm);
- if (result != NO_ERROR) {
- ALOGE("setAutoLowLatencyMode failed to readBool: %d", result);
- return result;
- }
- setAutoLowLatencyMode(display, setAllm);
- return result;
- }
- case SET_GAME_CONTENT_TYPE: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> display = nullptr;
- status_t result = data.readStrongBinder(&display);
- if (result != NO_ERROR) {
- ALOGE("setGameContentType failed to readStrongBinder: %d", result);
- return result;
- }
- bool setGameContentTypeOn = false;
- result = data.readBool(&setGameContentTypeOn);
- if (result != NO_ERROR) {
- ALOGE("setGameContentType failed to readBool: %d", result);
- return result;
- }
- setGameContentType(display, setGameContentTypeOn);
- return result;
- }
case CLEAR_ANIMATION_FRAME_STATS: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
status_t result = clearAnimationFrameStats();
@@ -1558,13 +1234,6 @@
reply->writeInt32(result);
return NO_ERROR;
}
- case SET_POWER_MODE: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> display = data.readStrongBinder();
- int32_t mode = data.readInt32();
- setPowerMode(display, mode);
- return NO_ERROR;
- }
case ENABLE_VSYNC_INJECTIONS: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
bool enable = false;
@@ -1714,20 +1383,6 @@
}
return error;
}
- case IS_WIDE_COLOR_DISPLAY: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> display = nullptr;
- status_t error = data.readStrongBinder(&display);
- if (error != NO_ERROR) {
- return error;
- }
- bool result;
- error = isWideColorDisplay(display, &result);
- if (error == NO_ERROR) {
- reply->writeBool(result);
- }
- return error;
- }
case ADD_REGION_SAMPLING_LISTENER: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
Rect samplingArea;
@@ -1925,77 +1580,6 @@
reply->writeInt32(result);
return result;
}
- case GET_DISPLAY_BRIGHTNESS_SUPPORT: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> displayToken;
- status_t error = data.readNullableStrongBinder(&displayToken);
- if (error != NO_ERROR) {
- ALOGE("getDisplayBrightnessSupport: failed to read display token: %d", error);
- return error;
- }
- bool support = false;
- error = getDisplayBrightnessSupport(displayToken, &support);
- reply->writeBool(support);
- return error;
- }
- case SET_DISPLAY_BRIGHTNESS: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> displayToken;
- status_t error = data.readNullableStrongBinder(&displayToken);
- if (error != NO_ERROR) {
- ALOGE("setDisplayBrightness: failed to read display token: %d", error);
- return error;
- }
- gui::DisplayBrightness brightness;
- error = data.readParcelable(&brightness);
- if (error != NO_ERROR) {
- ALOGE("setDisplayBrightness: failed to read brightness: %d", error);
- return error;
- }
- return setDisplayBrightness(displayToken, brightness);
- }
- case ADD_HDR_LAYER_INFO_LISTENER: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> displayToken;
- status_t error = data.readNullableStrongBinder(&displayToken);
- if (error != NO_ERROR) {
- ALOGE("addHdrLayerInfoListener: Failed to read display token");
- return error;
- }
- sp<gui::IHdrLayerInfoListener> listener;
- error = data.readNullableStrongBinder(&listener);
- if (error != NO_ERROR) {
- ALOGE("addHdrLayerInfoListener: Failed to read listener");
- return error;
- }
- return addHdrLayerInfoListener(displayToken, listener);
- }
- case REMOVE_HDR_LAYER_INFO_LISTENER: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> displayToken;
- status_t error = data.readNullableStrongBinder(&displayToken);
- if (error != NO_ERROR) {
- ALOGE("removeHdrLayerInfoListener: Failed to read display token");
- return error;
- }
- sp<gui::IHdrLayerInfoListener> listener;
- error = data.readNullableStrongBinder(&listener);
- if (error != NO_ERROR) {
- ALOGE("removeHdrLayerInfoListener: Failed to read listener");
- return error;
- }
- return removeHdrLayerInfoListener(displayToken, listener);
- }
- case NOTIFY_POWER_BOOST: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- int32_t boostId;
- status_t error = data.readInt32(&boostId);
- if (error != NO_ERROR) {
- ALOGE("notifyPowerBoost: failed to read boostId: %d", error);
- return error;
- }
- return notifyPowerBoost(boostId);
- }
case SET_GLOBAL_SHADOW_SETTINGS: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index ff8f529..54b6d6a 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -27,13 +27,13 @@
#include <inttypes.h>
+#include <android/gui/DisplayStatInfo.h>
#include <android/native_window.h>
#include <utils/Log.h>
#include <utils/Trace.h>
#include <utils/NativeHandle.h>
-#include <ui/DisplayStatInfo.h>
#include <ui/DynamicDisplayInfo.h>
#include <ui/Fence.h>
#include <ui/GraphicBuffer.h>
@@ -126,6 +126,10 @@
return ComposerService::getComposerService();
}
+sp<gui::ISurfaceComposer> Surface::composerServiceAIDL() const {
+ return ComposerServiceAIDL::getComposerService();
+}
+
nsecs_t Surface::now() const {
return systemTime();
}
@@ -175,10 +179,10 @@
status_t Surface::getDisplayRefreshCycleDuration(nsecs_t* outRefreshDuration) {
ATRACE_CALL();
- DisplayStatInfo stats;
- status_t result = composerService()->getDisplayStats(nullptr, &stats);
- if (result != NO_ERROR) {
- return result;
+ gui::DisplayStatInfo stats;
+ binder::Status status = composerServiceAIDL()->getDisplayStats(nullptr, &stats);
+ if (!status.isOk()) {
+ return status.transactionError();
}
*outRefreshDuration = stats.vsyncPeriod;
@@ -350,8 +354,8 @@
}
*supported = false;
- status_t error = composerService()->isWideColorDisplay(display, supported);
- return error;
+ binder::Status status = composerServiceAIDL()->isWideColorDisplay(display, supported);
+ return status.transactionError();
}
status_t Surface::getHdrSupport(bool* supported) {
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index ec7a948..7a63af0 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -19,6 +19,7 @@
#include <stdint.h>
#include <sys/types.h>
+#include <android/gui/DisplayState.h>
#include <android/gui/IWindowInfosListener.h>
#include <utils/Errors.h>
#include <utils/Log.h>
@@ -43,6 +44,7 @@
#include <gui/WindowInfo.h>
#include <private/gui/ParcelUtils.h>
#include <ui/DisplayMode.h>
+#include <ui/DisplayState.h>
#include <ui/DynamicDisplayInfo.h>
#include <private/gui/ComposerService.h>
@@ -206,12 +208,14 @@
}
sp<TransactionCompletedListener> TransactionCompletedListener::sInstance = nullptr;
+static std::mutex sListenerInstanceMutex;
void TransactionCompletedListener::setInstance(const sp<TransactionCompletedListener>& listener) {
sInstance = listener;
}
sp<TransactionCompletedListener> TransactionCompletedListener::getInstance() {
+ std::lock_guard<std::mutex> lock(sListenerInstanceMutex);
if (sInstance == nullptr) {
sInstance = new TransactionCompletedListener;
}
@@ -2127,7 +2131,16 @@
status_t SurfaceComposerClient::getDisplayState(const sp<IBinder>& display,
ui::DisplayState* state) {
- return ComposerService::getComposerService()->getDisplayState(display, state);
+ gui::DisplayState ds;
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->getDisplayState(display, &ds);
+ if (status.isOk()) {
+ state->layerStack = ui::LayerStack::fromValue(ds.layerStack);
+ state->orientation = static_cast<ui::Rotation>(ds.orientation);
+ state->layerStackSpaceRect =
+ ui::Size(ds.layerStackSpaceRect.width, ds.layerStackSpaceRect.height);
+ }
+ return status.transactionError();
}
status_t SurfaceComposerClient::getStaticDisplayInfo(const sp<IBinder>& display,
@@ -2191,7 +2204,9 @@
}
status_t SurfaceComposerClient::getBootDisplayModeSupport(bool* support) {
- return ComposerService::getComposerService()->getBootDisplayModeSupport(support);
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->getBootDisplayModeSupport(support);
+ return status.transactionError();
}
status_t SurfaceComposerClient::setBootDisplayMode(const sp<IBinder>& display,
@@ -2200,7 +2215,9 @@
}
status_t SurfaceComposerClient::clearBootDisplayMode(const sp<IBinder>& display) {
- return ComposerService::getComposerService()->clearBootDisplayMode(display);
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->clearBootDisplayMode(display);
+ return status.transactionError();
}
status_t SurfaceComposerClient::setOverrideFrameRate(uid_t uid, float frameRate) {
@@ -2208,16 +2225,16 @@
}
void SurfaceComposerClient::setAutoLowLatencyMode(const sp<IBinder>& display, bool on) {
- ComposerService::getComposerService()->setAutoLowLatencyMode(display, on);
+ ComposerServiceAIDL::getComposerService()->setAutoLowLatencyMode(display, on);
}
void SurfaceComposerClient::setGameContentType(const sp<IBinder>& display, bool on) {
- ComposerService::getComposerService()->setGameContentType(display, on);
+ ComposerServiceAIDL::getComposerService()->setGameContentType(display, on);
}
void SurfaceComposerClient::setDisplayPowerMode(const sp<IBinder>& token,
int mode) {
- ComposerService::getComposerService()->setPowerMode(token, mode);
+ ComposerServiceAIDL::getComposerService()->setPowerMode(token, mode);
}
status_t SurfaceComposerClient::getCompositionPreference(
@@ -2278,8 +2295,10 @@
status_t SurfaceComposerClient::isWideColorDisplay(const sp<IBinder>& display,
bool* outIsWideColorDisplay) {
- return ComposerService::getComposerService()->isWideColorDisplay(display,
- outIsWideColorDisplay);
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->isWideColorDisplay(display,
+ outIsWideColorDisplay);
+ return status.transactionError();
}
status_t SurfaceComposerClient::addRegionSamplingListener(
@@ -2316,28 +2335,39 @@
bool SurfaceComposerClient::getDisplayBrightnessSupport(const sp<IBinder>& displayToken) {
bool support = false;
- ComposerService::getComposerService()->getDisplayBrightnessSupport(displayToken, &support);
- return support;
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->getDisplayBrightnessSupport(displayToken,
+ &support);
+ return status.isOk() ? support : false;
}
status_t SurfaceComposerClient::setDisplayBrightness(const sp<IBinder>& displayToken,
const gui::DisplayBrightness& brightness) {
- return ComposerService::getComposerService()->setDisplayBrightness(displayToken, brightness);
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->setDisplayBrightness(displayToken,
+ brightness);
+ return status.transactionError();
}
status_t SurfaceComposerClient::addHdrLayerInfoListener(
const sp<IBinder>& displayToken, const sp<gui::IHdrLayerInfoListener>& listener) {
- return ComposerService::getComposerService()->addHdrLayerInfoListener(displayToken, listener);
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->addHdrLayerInfoListener(displayToken,
+ listener);
+ return status.transactionError();
}
status_t SurfaceComposerClient::removeHdrLayerInfoListener(
const sp<IBinder>& displayToken, const sp<gui::IHdrLayerInfoListener>& listener) {
- return ComposerService::getComposerService()->removeHdrLayerInfoListener(displayToken,
- listener);
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->removeHdrLayerInfoListener(displayToken,
+ listener);
+ return status.transactionError();
}
status_t SurfaceComposerClient::notifyPowerBoost(int32_t boostId) {
- return ComposerService::getComposerService()->notifyPowerBoost(boostId);
+ binder::Status status = ComposerServiceAIDL::getComposerService()->notifyPowerBoost(boostId);
+ return status.transactionError();
}
status_t SurfaceComposerClient::setGlobalShadowSettings(const half4& ambientColor,
diff --git a/libs/gui/aidl/android/gui/DisplayStatInfo.aidl b/libs/gui/aidl/android/gui/DisplayStatInfo.aidl
new file mode 100644
index 0000000..68f3942
--- /dev/null
+++ b/libs/gui/aidl/android/gui/DisplayStatInfo.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2022 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;
+
+/** @hide */
+parcelable DisplayStatInfo {
+ long vsyncTime;
+ long vsyncPeriod;
+}
diff --git a/libs/gui/aidl/android/gui/DisplayState.aidl b/libs/gui/aidl/android/gui/DisplayState.aidl
new file mode 100644
index 0000000..9589ab6
--- /dev/null
+++ b/libs/gui/aidl/android/gui/DisplayState.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2022 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;
+
+import android.gui.Rotation;
+import android.gui.Size;
+
+/** @hide */
+parcelable DisplayState {
+ int layerStack;
+ Rotation orientation = Rotation.Rotation0;
+ Size layerStackSpaceRect;
+}
diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
index 345c47d..a9977b0 100644
--- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
+++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
@@ -17,6 +17,10 @@
package android.gui;
import android.gui.DisplayCaptureArgs;
+import android.gui.DisplayBrightness;
+import android.gui.DisplayState;
+import android.gui.DisplayStatInfo;
+import android.gui.IHdrLayerInfoListener;
import android.gui.LayerCaptureArgs;
import android.gui.IScreenCaptureListener;
@@ -44,6 +48,57 @@
*/
@nullable IBinder getPhysicalDisplayToken(long displayId);
+ /* set display power mode. depending on the mode, it can either trigger
+ * screen on, off or low power mode and wait for it to complete.
+ * requires ACCESS_SURFACE_FLINGER permission.
+ */
+ void setPowerMode(IBinder display, int mode);
+
+ /* returns display statistics for a given display
+ * intended to be used by the media framework to properly schedule
+ * video frames */
+ DisplayStatInfo getDisplayStats(IBinder display);
+
+ /**
+ * Get transactional state of given display.
+ */
+ DisplayState getDisplayState(IBinder display);
+
+ /**
+ * Clears the user-preferred display mode. The device should now boot in system preferred
+ * display mode.
+ */
+ void clearBootDisplayMode(IBinder display);
+
+ /**
+ * Gets whether boot time display mode operations are supported on the device.
+ *
+ * outSupport
+ * An output parameter for whether boot time display mode operations are supported.
+ *
+ * Returns NO_ERROR upon success. Otherwise,
+ * NAME_NOT_FOUND if the display is invalid, or
+ * BAD_VALUE if the output parameter is invalid.
+ */
+ // TODO(b/213909104) : Add unit tests to verify surface flinger boot time APIs
+ boolean getBootDisplayModeSupport();
+
+ /**
+ * Switches Auto Low Latency Mode on/off on the connected display, if it is
+ * available. This should only be called if the display supports Auto Low
+ * Latency Mode as reported in #getDynamicDisplayInfo.
+ * For more information, see the HDMI 2.1 specification.
+ */
+ void setAutoLowLatencyMode(IBinder display, boolean on);
+
+ /**
+ * This will start sending infoframes to the connected display with
+ * ContentType=Game (if on=true). This should only be called if the display
+ * Game Content Type as reported in #getDynamicDisplayInfo.
+ * For more information, see the HDMI 1.4 specification.
+ */
+ void setGameContentType(IBinder display, boolean on);
+
/**
* Capture the specified screen. This requires READ_FRAME_BUFFER
* permission. This function will fail if there is a secure window on
@@ -61,4 +116,67 @@
* is a secure window on screen
*/
void captureLayers(in LayerCaptureArgs args, IScreenCaptureListener listener);
+
+ /*
+ * Queries whether the given display is a wide color display.
+ * Requires the ACCESS_SURFACE_FLINGER permission.
+ */
+ boolean isWideColorDisplay(IBinder token);
+
+ /*
+ * Gets whether brightness operations are supported on a display.
+ *
+ * displayToken
+ * The token of the display.
+ * outSupport
+ * An output parameter for whether brightness operations are supported.
+ *
+ * Returns NO_ERROR upon success. Otherwise,
+ * NAME_NOT_FOUND if the display is invalid, or
+ * BAD_VALUE if the output parameter is invalid.
+ */
+ boolean getDisplayBrightnessSupport(IBinder displayToken);
+
+ /*
+ * Sets the brightness of a display.
+ *
+ * displayToken
+ * The token of the display whose brightness is set.
+ * brightness
+ * The DisplayBrightness info to set on the desired display.
+ *
+ * Returns NO_ERROR upon success. Otherwise,
+ * NAME_NOT_FOUND if the display is invalid, or
+ * BAD_VALUE if the brightness is invalid, or
+ * INVALID_OPERATION if brightness operations are not supported.
+ */
+ void setDisplayBrightness(IBinder displayToken, in DisplayBrightness brightness);
+
+ /*
+ * Adds a listener that receives HDR layer information. This is used in combination
+ * with setDisplayBrightness to adjust the display brightness depending on factors such
+ * as whether or not HDR is in use.
+ *
+ * Returns NO_ERROR upon success or NAME_NOT_FOUND if the display is invalid.
+ */
+ void addHdrLayerInfoListener(IBinder displayToken, IHdrLayerInfoListener listener);
+
+ /*
+ * Removes a listener that was added with addHdrLayerInfoListener.
+ *
+ * Returns NO_ERROR upon success, NAME_NOT_FOUND if the display is invalid, and BAD_VALUE if
+ * the listener wasn't registered.
+ *
+ */
+ void removeHdrLayerInfoListener(IBinder displayToken, IHdrLayerInfoListener listener);
+
+ /*
+ * Sends a power boost to the composer. This function is asynchronous.
+ *
+ * boostId
+ * boost id according to android::hardware::power::Boost
+ *
+ * Returns NO_ERROR upon success.
+ */
+ void notifyPowerBoost(int boostId);
}
diff --git a/libs/gui/aidl/android/gui/Rect.aidl b/libs/gui/aidl/android/gui/Rect.aidl
new file mode 100644
index 0000000..1b13761
--- /dev/null
+++ b/libs/gui/aidl/android/gui/Rect.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2022 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;
+
+// copied from libs/arect/include/android/rect.h
+// TODO(b/221473398):
+// use hardware/interfaces/graphics/common/aidl/android/hardware/graphics/common/Rect.aidl
+/** @hide */
+parcelable Rect {
+ /// Minimum X coordinate of the rectangle.
+ int left;
+
+ /// Minimum Y coordinate of the rectangle.
+ int top;
+
+ /// Maximum X coordinate of the rectangle.
+ int right;
+
+ /// Maximum Y coordinate of the rectangle.
+ int bottom;
+}
diff --git a/libs/gui/aidl/android/gui/Rotation.aidl b/libs/gui/aidl/android/gui/Rotation.aidl
new file mode 100644
index 0000000..451ff45
--- /dev/null
+++ b/libs/gui/aidl/android/gui/Rotation.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2022 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;
+
+/** @hide */
+@Backing(type="int")
+enum Rotation {
+ Rotation0 = 0,
+ Rotation90 = 1,
+ Rotation180 = 2,
+ Rotation270 = 3
+}
diff --git a/libs/gui/aidl/android/gui/Size.aidl b/libs/gui/aidl/android/gui/Size.aidl
new file mode 100644
index 0000000..415fa36
--- /dev/null
+++ b/libs/gui/aidl/android/gui/Size.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2022 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;
+
+/** @hide */
+parcelable Size {
+ int width = -1;
+ int height = -1;
+}
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 91d44da..a610e94 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -161,24 +161,6 @@
virtual status_t getSupportedFrameTimestamps(
std::vector<FrameEvent>* outSupported) const = 0;
- /* set display power mode. depending on the mode, it can either trigger
- * screen on, off or low power mode and wait for it to complete.
- * requires ACCESS_SURFACE_FLINGER permission.
- */
- virtual void setPowerMode(const sp<IBinder>& display, int mode) = 0;
-
-
- /* returns display statistics for a given display
- * intended to be used by the media framework to properly schedule
- * video frames */
- virtual status_t getDisplayStats(const sp<IBinder>& display,
- DisplayStatInfo* stats) = 0;
-
- /**
- * Get transactional state of given display.
- */
- virtual status_t getDisplayState(const sp<IBinder>& display, ui::DisplayState*) = 0;
-
/**
* Gets immutable information about given physical display.
*/
@@ -199,40 +181,6 @@
*/
virtual status_t setBootDisplayMode(const sp<IBinder>& display, ui::DisplayModeId) = 0;
- /**
- * Clears the user-preferred display mode. The device should now boot in system preferred
- * display mode.
- */
- virtual status_t clearBootDisplayMode(const sp<IBinder>& display) = 0;
-
- /**
- * Gets whether boot time display mode operations are supported on the device.
- *
- * outSupport
- * An output parameter for whether boot time display mode operations are supported.
- *
- * Returns NO_ERROR upon success. Otherwise,
- * NAME_NOT_FOUND if the display is invalid, or
- * BAD_VALUE if the output parameter is invalid.
- */
- virtual status_t getBootDisplayModeSupport(bool* outSupport) const = 0;
-
- /**
- * Switches Auto Low Latency Mode on/off on the connected display, if it is
- * available. This should only be called if the display supports Auto Low
- * Latency Mode as reported in #getDynamicDisplayInfo.
- * For more information, see the HDMI 2.1 specification.
- */
- virtual void setAutoLowLatencyMode(const sp<IBinder>& display, bool on) = 0;
-
- /**
- * This will start sending infoframes to the connected display with
- * ContentType=Game (if on=true). This should only be called if the display
- * Game Content Type as reported in #getDynamicDisplayInfo.
- * For more information, see the HDMI 1.4 specification.
- */
- virtual void setGameContentType(const sp<IBinder>& display, bool on) = 0;
-
/* Clears the frame statistics for animations.
*
* Requires the ACCESS_SURFACE_FLINGER permission.
@@ -311,13 +259,6 @@
*/
virtual status_t getProtectedContentSupport(bool* outSupported) const = 0;
- /*
- * Queries whether the given display is a wide color display.
- * Requires the ACCESS_SURFACE_FLINGER permission.
- */
- virtual status_t isWideColorDisplay(const sp<IBinder>& token,
- bool* outIsWideColorDisplay) const = 0;
-
/* Registers a listener to stream median luma updates from SurfaceFlinger.
*
* The sampling area is bounded by both samplingArea and the given stopLayerHandle
@@ -398,65 +339,6 @@
float* outPrimaryRefreshRateMax,
float* outAppRequestRefreshRateMin,
float* outAppRequestRefreshRateMax) = 0;
- /*
- * Gets whether brightness operations are supported on a display.
- *
- * displayToken
- * The token of the display.
- * outSupport
- * An output parameter for whether brightness operations are supported.
- *
- * Returns NO_ERROR upon success. Otherwise,
- * NAME_NOT_FOUND if the display is invalid, or
- * BAD_VALUE if the output parameter is invalid.
- */
- virtual status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken,
- bool* outSupport) const = 0;
-
- /*
- * Sets the brightness of a display.
- *
- * displayToken
- * The token of the display whose brightness is set.
- * brightness
- * The DisplayBrightness info to set on the desired display.
- *
- * Returns NO_ERROR upon success. Otherwise,
- * NAME_NOT_FOUND if the display is invalid, or
- * BAD_VALUE if the brightness is invalid, or
- * INVALID_OPERATION if brightness operations are not supported.
- */
- virtual status_t setDisplayBrightness(const sp<IBinder>& displayToken,
- const gui::DisplayBrightness& brightness) = 0;
-
- /*
- * Adds a listener that receives HDR layer information. This is used in combination
- * with setDisplayBrightness to adjust the display brightness depending on factors such
- * as whether or not HDR is in use.
- *
- * Returns NO_ERROR upon success or NAME_NOT_FOUND if the display is invalid.
- */
- virtual status_t addHdrLayerInfoListener(const sp<IBinder>& displayToken,
- const sp<gui::IHdrLayerInfoListener>& listener) = 0;
- /*
- * Removes a listener that was added with addHdrLayerInfoListener.
- *
- * Returns NO_ERROR upon success, NAME_NOT_FOUND if the display is invalid, and BAD_VALUE if
- * the listener wasn't registered.
- *
- */
- virtual status_t removeHdrLayerInfoListener(const sp<IBinder>& displayToken,
- const sp<gui::IHdrLayerInfoListener>& listener) = 0;
-
- /*
- * Sends a power boost to the composer. This function is asynchronous.
- *
- * boostId
- * boost id according to android::hardware::power::Boost
- *
- * Returns NO_ERROR upon success.
- */
- virtual status_t notifyPowerBoost(int32_t boostId) = 0;
/*
* Sets the global configuration for all the shadows drawn by SurfaceFlinger. Shadow follows
@@ -576,7 +458,7 @@
CAPTURE_LAYERS, // Deprecated. Autogenerated by .aidl now.
CLEAR_ANIMATION_FRAME_STATS,
GET_ANIMATION_FRAME_STATS,
- SET_POWER_MODE,
+ SET_POWER_MODE, // Deprecated. Autogenerated by .aidl now.
GET_DISPLAY_STATS,
GET_HDR_CAPABILITIES, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
GET_DISPLAY_COLOR_MODES, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
@@ -591,22 +473,22 @@
SET_DISPLAY_CONTENT_SAMPLING_ENABLED,
GET_DISPLAYED_CONTENT_SAMPLE,
GET_PROTECTED_CONTENT_SUPPORT,
- IS_WIDE_COLOR_DISPLAY,
+ IS_WIDE_COLOR_DISPLAY, // Deprecated. Autogenerated by .aidl now.
GET_DISPLAY_NATIVE_PRIMARIES,
GET_PHYSICAL_DISPLAY_IDS, // Deprecated. Autogenerated by .aidl now.
ADD_REGION_SAMPLING_LISTENER,
REMOVE_REGION_SAMPLING_LISTENER,
SET_DESIRED_DISPLAY_MODE_SPECS,
GET_DESIRED_DISPLAY_MODE_SPECS,
- GET_DISPLAY_BRIGHTNESS_SUPPORT,
- SET_DISPLAY_BRIGHTNESS,
- CAPTURE_DISPLAY_BY_ID, // Deprecated. Autogenerated by .aidl now.
- NOTIFY_POWER_BOOST,
+ GET_DISPLAY_BRIGHTNESS_SUPPORT, // Deprecated. Autogenerated by .aidl now.
+ SET_DISPLAY_BRIGHTNESS, // Deprecated. Autogenerated by .aidl now.
+ CAPTURE_DISPLAY_BY_ID, // Deprecated. Autogenerated by .aidl now.
+ NOTIFY_POWER_BOOST, // Deprecated. Autogenerated by .aidl now.
SET_GLOBAL_SHADOW_SETTINGS,
GET_AUTO_LOW_LATENCY_MODE_SUPPORT, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
- SET_AUTO_LOW_LATENCY_MODE,
- GET_GAME_CONTENT_TYPE_SUPPORT, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
- SET_GAME_CONTENT_TYPE,
+ SET_AUTO_LOW_LATENCY_MODE, // Deprecated. Autogenerated by .aidl now.
+ GET_GAME_CONTENT_TYPE_SUPPORT, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
+ SET_GAME_CONTENT_TYPE, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
SET_FRAME_RATE,
// Deprecated. Use DisplayManager.setShouldAlwaysRespectAppRequestedMode(true);
ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN,
@@ -618,8 +500,8 @@
ADD_FPS_LISTENER,
REMOVE_FPS_LISTENER,
OVERRIDE_HDR_TYPES,
- ADD_HDR_LAYER_INFO_LISTENER,
- REMOVE_HDR_LAYER_INFO_LISTENER,
+ ADD_HDR_LAYER_INFO_LISTENER, // Deprecated. Autogenerated by .aidl now.
+ REMOVE_HDR_LAYER_INFO_LISTENER, // Deprecated. Autogenerated by .aidl now.
ON_PULL_ATOM,
ADD_TUNNEL_MODE_ENABLED_LISTENER,
REMOVE_TUNNEL_MODE_ENABLED_LISTENER,
@@ -627,9 +509,9 @@
REMOVE_WINDOW_INFOS_LISTENER,
GET_PRIMARY_PHYSICAL_DISPLAY_ID, // Deprecated. Autogenerated by .aidl now.
GET_DISPLAY_DECORATION_SUPPORT,
- GET_BOOT_DISPLAY_MODE_SUPPORT,
+ GET_BOOT_DISPLAY_MODE_SUPPORT, // Deprecated. Autogenerated by .aidl now.
SET_BOOT_DISPLAY_MODE,
- CLEAR_BOOT_DISPLAY_MODE,
+ CLEAR_BOOT_DISPLAY_MODE, // Deprecated. Autogenerated by .aidl now.
SET_OVERRIDE_FRAME_RATE,
// Always append new enum to the end.
};
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 5fe308c..ab9ebaa 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -35,6 +35,10 @@
namespace android {
+namespace gui {
+class ISurfaceComposer;
+} // namespace gui
+
class ISurfaceComposer;
/* This is the same as ProducerListener except that onBuffersDiscarded is
@@ -196,6 +200,7 @@
// Virtual for testing.
virtual sp<ISurfaceComposer> composerService() const;
+ virtual sp<gui::ISurfaceComposer> composerServiceAIDL() const;
virtual nsecs_t now() const;
private:
diff --git a/libs/gui/include/private/gui/ComposerServiceAIDL.h b/libs/gui/include/private/gui/ComposerServiceAIDL.h
index b32cf2a..9a96976 100644
--- a/libs/gui/include/private/gui/ComposerServiceAIDL.h
+++ b/libs/gui/include/private/gui/ComposerServiceAIDL.h
@@ -68,7 +68,8 @@
if (!displayId) return nullptr;
sp<IBinder> display;
binder::Status status =
- mComposerService->getPhysicalDisplayToken(displayId->value, &display);
+ mComposerService->getPhysicalDisplayToken(static_cast<int64_t>(displayId->value),
+ &display);
return status.isOk() ? display : nullptr;
}
};
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 07ac2d4..065cd7a 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -20,6 +20,7 @@
#include <SurfaceFlingerProperties.h>
#include <android/gui/IDisplayEventConnection.h>
+#include <android/gui/ISurfaceComposer.h>
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <binder/ProcessState.h>
#include <configstore/Utils.h>
@@ -732,7 +733,6 @@
return NO_ERROR;
}
- void setPowerMode(const sp<IBinder>& /*display*/, int /*mode*/) override {}
status_t getStaticDisplayInfo(const sp<IBinder>& /*display*/, ui::StaticDisplayInfo*) override {
return NO_ERROR;
}
@@ -740,24 +740,16 @@
ui::DynamicDisplayInfo*) override {
return NO_ERROR;
}
- status_t getDisplayState(const sp<IBinder>& /*display*/, ui::DisplayState*) override {
- return NO_ERROR;
- }
- status_t getDisplayStats(const sp<IBinder>& /*display*/,
- DisplayStatInfo* /*stats*/) override { return NO_ERROR; }
status_t getDisplayNativePrimaries(const sp<IBinder>& /*display*/,
ui::DisplayPrimaries& /*primaries*/) override {
return NO_ERROR;
}
- status_t setActiveColorMode(const sp<IBinder>& /*display*/,
- ColorMode /*colorMode*/) override { return NO_ERROR; }
- status_t getBootDisplayModeSupport(bool* /*outSupport*/) const override { return NO_ERROR; }
+ status_t setActiveColorMode(const sp<IBinder>& /*display*/, ColorMode /*colorMode*/) override {
+ return NO_ERROR;
+ }
status_t setBootDisplayMode(const sp<IBinder>& /*display*/, ui::DisplayModeId /*id*/) override {
return NO_ERROR;
}
- status_t clearBootDisplayMode(const sp<IBinder>& /*display*/) override { return NO_ERROR; }
- void setAutoLowLatencyMode(const sp<IBinder>& /*display*/, bool /*on*/) override {}
- void setGameContentType(const sp<IBinder>& /*display*/, bool /*on*/) override {}
status_t clearAnimationFrameStats() override { return NO_ERROR; }
status_t getAnimationFrameStats(FrameStats* /*outStats*/) const override {
@@ -804,26 +796,6 @@
status_t getColorManagement(bool* /*outGetColorManagement*/) const override { return NO_ERROR; }
status_t getProtectedContentSupport(bool* /*outSupported*/) const override { return NO_ERROR; }
- status_t isWideColorDisplay(const sp<IBinder>&, bool*) const override { return NO_ERROR; }
- status_t getDisplayBrightnessSupport(const sp<IBinder>& /*displayToken*/,
- bool* /*outSupport*/) const override {
- return NO_ERROR;
- }
- status_t setDisplayBrightness(const sp<IBinder>& /*displayToken*/,
- const gui::DisplayBrightness& /*brightness*/) override {
- return NO_ERROR;
- }
-
- status_t addHdrLayerInfoListener(const sp<IBinder>&,
- const sp<gui::IHdrLayerInfoListener>&) override {
- return NO_ERROR;
- }
-
- status_t removeHdrLayerInfoListener(const sp<IBinder>&,
- const sp<gui::IHdrLayerInfoListener>&) override {
- return NO_ERROR;
- }
-
status_t addRegionSamplingListener(const Rect& /*samplingArea*/,
const sp<IBinder>& /*stopLayerHandle*/,
const sp<IRegionSamplingListener>& /*listener*/) override {
@@ -865,7 +837,6 @@
float* /*outAppRequestRefreshRateMax*/) override {
return NO_ERROR;
};
- status_t notifyPowerBoost(int32_t /*boostId*/) override { return NO_ERROR; }
status_t setGlobalShadowSettings(const half4& /*ambientColor*/, const half4& /*spotColor*/,
float /*lightPosY*/, float /*lightPosZ*/,
@@ -917,6 +888,114 @@
bool mSupportsPresent{true};
};
+class FakeSurfaceComposerAIDL : public gui::ISurfaceComposer {
+public:
+ ~FakeSurfaceComposerAIDL() override {}
+
+ void setSupportsPresent(bool supportsPresent) { mSupportsPresent = supportsPresent; }
+
+ binder::Status createDisplay(const std::string& /*displayName*/, bool /*secure*/,
+ sp<IBinder>* /*outDisplay*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status destroyDisplay(const sp<IBinder>& /*display*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getPhysicalDisplayIds(std::vector<int64_t>* /*outDisplayIds*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getPrimaryPhysicalDisplayId(int64_t* /*outDisplayId*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getPhysicalDisplayToken(int64_t /*displayId*/,
+ sp<IBinder>* /*outDisplay*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status setPowerMode(const sp<IBinder>& /*display*/, int /*mode*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getDisplayStats(const sp<IBinder>& /*display*/,
+ gui::DisplayStatInfo* /*outStatInfo*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getDisplayState(const sp<IBinder>& /*display*/,
+ gui::DisplayState* /*outState*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status clearBootDisplayMode(const sp<IBinder>& /*display*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getBootDisplayModeSupport(bool* /*outMode*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status setAutoLowLatencyMode(const sp<IBinder>& /*display*/, bool /*on*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status setGameContentType(const sp<IBinder>& /*display*/, bool /*on*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status captureDisplay(const DisplayCaptureArgs&,
+ const sp<IScreenCaptureListener>&) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status captureDisplayById(int64_t, const sp<IScreenCaptureListener>&) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status captureLayers(const LayerCaptureArgs&,
+ const sp<IScreenCaptureListener>&) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status isWideColorDisplay(const sp<IBinder>& /*token*/,
+ bool* /*outIsWideColorDisplay*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getDisplayBrightnessSupport(const sp<IBinder>& /*displayToken*/,
+ bool* /*outSupport*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status setDisplayBrightness(const sp<IBinder>& /*displayToken*/,
+ const gui::DisplayBrightness& /*brightness*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status addHdrLayerInfoListener(
+ const sp<IBinder>& /*displayToken*/,
+ const sp<gui::IHdrLayerInfoListener>& /*listener*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status removeHdrLayerInfoListener(
+ const sp<IBinder>& /*displayToken*/,
+ const sp<gui::IHdrLayerInfoListener>& /*listener*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status notifyPowerBoost(int /*boostId*/) override { return binder::Status::ok(); }
+
+protected:
+ IBinder* onAsBinder() override { return nullptr; }
+
+private:
+ bool mSupportsPresent{true};
+};
+
class FakeProducerFrameEventHistory : public ProducerFrameEventHistory {
public:
explicit FakeProducerFrameEventHistory(FenceToFenceTimeMap* fenceMap) : mFenceMap(fenceMap) {}
diff --git a/libs/input/android/os/InputEventInjectionResult.aidl b/libs/input/android/os/InputEventInjectionResult.aidl
index 34f10ec..3bc7068 100644
--- a/libs/input/android/os/InputEventInjectionResult.aidl
+++ b/libs/input/android/os/InputEventInjectionResult.aidl
@@ -29,9 +29,8 @@
/* Injection succeeded. */
SUCCEEDED = 0,
- /* Injection failed because the injector did not have permission to inject
- * into the application with input focus. */
- PERMISSION_DENIED = 1,
+ /* Injection failed because the injected event did not target the appropriate window. */
+ TARGET_MISMATCH = 1,
/* Injection failed because there were no available input targets. */
FAILED = 2,
diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
index 32eec29..a2e60c4 100644
--- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
+++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
@@ -31,11 +31,11 @@
namespace android::inputdispatcher {
// An arbitrary device id.
-static const int32_t DEVICE_ID = 1;
+constexpr int32_t DEVICE_ID = 1;
-// An arbitrary injector pid / uid pair that has permission to inject events.
-static const int32_t INJECTOR_PID = 999;
-static const int32_t INJECTOR_UID = 1001;
+// The default pid and uid for windows created by the test.
+constexpr int32_t WINDOW_PID = 999;
+constexpr int32_t WINDOW_UID = 1001;
static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 5s;
static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 100ms;
@@ -108,8 +108,6 @@
void pokeUserActivity(nsecs_t, int32_t, int32_t) override {}
- bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override { return false; }
-
void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {}
void setPointerCapture(const PointerCaptureRequest&) override {}
@@ -196,8 +194,8 @@
mInfo.globalScaleFactor = 1.0;
mInfo.touchableRegion.clear();
mInfo.addTouchableRegion(mFrame);
- mInfo.ownerPid = INJECTOR_PID;
- mInfo.ownerUid = INJECTOR_UID;
+ mInfo.ownerPid = WINDOW_PID;
+ mInfo.ownerUid = WINDOW_UID;
mInfo.displayId = ADISPLAY_ID_DEFAULT;
}
@@ -310,14 +308,14 @@
for (auto _ : state) {
MotionEvent event = generateMotionEvent();
// Send ACTION_DOWN
- dispatcher.injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
- InputEventInjectionSync::NONE, INJECT_EVENT_TIMEOUT,
+ dispatcher.injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
+ INJECT_EVENT_TIMEOUT,
POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
// Send ACTION_UP
event.setAction(AMOTION_EVENT_ACTION_UP);
- dispatcher.injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
- InputEventInjectionSync::NONE, INJECT_EVENT_TIMEOUT,
+ dispatcher.injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
+ INJECT_EVENT_TIMEOUT,
POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
window->consumeEvent();
diff --git a/services/inputflinger/dispatcher/InjectionState.cpp b/services/inputflinger/dispatcher/InjectionState.cpp
index c8024a6..c2d3ad6 100644
--- a/services/inputflinger/dispatcher/InjectionState.cpp
+++ b/services/inputflinger/dispatcher/InjectionState.cpp
@@ -20,10 +20,9 @@
namespace android::inputdispatcher {
-InjectionState::InjectionState(int32_t injectorPid, int32_t injectorUid)
+InjectionState::InjectionState(const std::optional<int32_t>& targetUid)
: refCount(1),
- injectorPid(injectorPid),
- injectorUid(injectorUid),
+ targetUid(targetUid),
injectionResult(android::os::InputEventInjectionResult::PENDING),
injectionIsAsync(false),
pendingForegroundDispatches(0) {}
diff --git a/services/inputflinger/dispatcher/InjectionState.h b/services/inputflinger/dispatcher/InjectionState.h
index 0bfafb1..90cf150 100644
--- a/services/inputflinger/dispatcher/InjectionState.h
+++ b/services/inputflinger/dispatcher/InjectionState.h
@@ -27,13 +27,12 @@
struct InjectionState {
mutable int32_t refCount;
- int32_t injectorPid;
- int32_t injectorUid;
+ std::optional<int32_t> targetUid;
android::os::InputEventInjectionResult injectionResult; // initially PENDING
bool injectionIsAsync; // set to true if injection is not waiting for the result
int32_t pendingForegroundDispatches; // the number of foreground dispatches in progress
- InjectionState(int32_t injectorPid, int32_t injectorUid);
+ explicit InjectionState(const std::optional<int32_t>& targetUid);
void release();
private:
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 6bab349..f3d0b65 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -567,6 +567,38 @@
return !info.inputConfig.test(gui::WindowInfo::InputConfig::NOT_TOUCHABLE) && !info.isSpy();
}
+bool isWindowOwnedBy(const sp<WindowInfoHandle>& windowHandle, int32_t pid, int32_t uid) {
+ if (windowHandle == nullptr) {
+ return false;
+ }
+ const WindowInfo* windowInfo = windowHandle->getInfo();
+ if (pid == windowInfo->ownerPid && uid == windowInfo->ownerUid) {
+ return true;
+ }
+ return false;
+}
+
+// Checks targeted injection using the window's owner's uid.
+// Returns an empty string if an entry can be sent to the given window, or an error message if the
+// entry is a targeted injection whose uid target doesn't match the window owner.
+std::optional<std::string> verifyTargetedInjection(const sp<WindowInfoHandle>& window,
+ const EventEntry& entry) {
+ if (entry.injectionState == nullptr || !entry.injectionState->targetUid) {
+ // The event was not injected, or the injected event does not target a window.
+ return {};
+ }
+ const int32_t uid = *entry.injectionState->targetUid;
+ if (window == nullptr) {
+ return StringPrintf("No valid window target for injection into uid %d.", uid);
+ }
+ if (entry.injectionState->targetUid != window->getInfo()->ownerUid) {
+ return StringPrintf("Injected event targeted at uid %d would be dispatched to window '%s' "
+ "owned by uid %d.",
+ uid, window->getName().c_str(), window->getInfo()->ownerUid);
+ }
+ return {};
+}
+
} // namespace
// --- InputDispatcher ---
@@ -1025,6 +1057,8 @@
switch (entry.type) {
case EventEntry::Type::KEY: {
+ LOG_ALWAYS_FATAL_IF((entry.policyFlags & POLICY_FLAG_TRUSTED) == 0,
+ "Unexpected untrusted event.");
// Optimize app switch latency.
// If the application takes too long to catch up then we drop all events preceding
// the app switch key.
@@ -1062,6 +1096,8 @@
}
case EventEntry::Type::MOTION: {
+ LOG_ALWAYS_FATAL_IF((entry.policyFlags & POLICY_FLAG_TRUSTED) == 0,
+ "Unexpected untrusted event.");
if (shouldPruneInboundQueueLocked(static_cast<MotionEntry&>(entry))) {
mNextUnblockedEvent = mInboundQueue.back();
needWake = true;
@@ -1707,8 +1743,7 @@
}
setInjectionResult(*entry, injectionResult);
- if (injectionResult == InputEventInjectionResult::PERMISSION_DENIED) {
- ALOGW("Permission denied, dropping the motion (isPointer=%s)", toString(isPointerEvent));
+ if (injectionResult == InputEventInjectionResult::TARGET_MISMATCH) {
return true;
}
if (injectionResult != InputEventInjectionResult::SUCCEEDED) {
@@ -1965,9 +2000,10 @@
// we have a valid, non-null focused window
resetNoFocusedWindowTimeoutLocked();
- // Check permissions.
- if (!checkInjectionPermission(focusedWindowHandle, entry.injectionState)) {
- return InputEventInjectionResult::PERMISSION_DENIED;
+ // Verify targeted injection.
+ if (const auto err = verifyTargetedInjection(focusedWindowHandle, entry); err) {
+ ALOGW("Dropping injected event: %s", (*err).c_str());
+ return InputEventInjectionResult::TARGET_MISMATCH;
}
if (focusedWindowHandle->getInfo()->inputConfig.test(
@@ -2033,11 +2069,6 @@
nsecs_t currentTime, const MotionEntry& entry, std::vector<InputTarget>& inputTargets,
nsecs_t* nextWakeupTime, bool* outConflictingPointerActions) {
ATRACE_CALL();
- enum InjectionPermission {
- INJECTION_PERMISSION_UNKNOWN,
- INJECTION_PERMISSION_GRANTED,
- INJECTION_PERMISSION_DENIED
- };
// For security reasons, we defer updating the touch state until we are sure that
// event injection will be allowed.
@@ -2047,7 +2078,6 @@
// Update the touch state as needed based on the properties of the touch event.
InputEventInjectionResult injectionResult = InputEventInjectionResult::PENDING;
- InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
sp<WindowInfoHandle> newHoverWindowHandle(mLastHoverWindowHandle);
sp<WindowInfoHandle> newTouchedWindowHandle;
@@ -2096,7 +2126,7 @@
"in display %" PRId32,
displayId);
// TODO: test multiple simultaneous input streams.
- injectionResult = InputEventInjectionResult::PERMISSION_DENIED;
+ injectionResult = InputEventInjectionResult::FAILED;
switchedDevice = false;
wrongDevice = true;
goto Failed;
@@ -2129,6 +2159,14 @@
newTouchedWindowHandle = tempTouchState.getFirstForegroundWindowHandle();
}
+ // Verify targeted injection.
+ if (const auto err = verifyTargetedInjection(newTouchedWindowHandle, entry); err) {
+ ALOGW("Dropping injected touch event: %s", (*err).c_str());
+ injectionResult = os::InputEventInjectionResult::TARGET_MISMATCH;
+ newTouchedWindowHandle = nullptr;
+ goto Failed;
+ }
+
// Figure out whether splitting will be allowed for this window.
if (newTouchedWindowHandle != nullptr) {
if (newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
@@ -2172,6 +2210,11 @@
for (const sp<WindowInfoHandle>& windowHandle : newTouchedWindows) {
const WindowInfo& info = *windowHandle->getInfo();
+ // Skip spy window targets that are not valid for targeted injection.
+ if (const auto err = verifyTargetedInjection(windowHandle, entry); err) {
+ continue;
+ }
+
if (info.inputConfig.test(WindowInfo::InputConfig::PAUSE_DISPATCHING)) {
ALOGI("Not sending touch event to %s because it is paused",
windowHandle->getName().c_str());
@@ -2265,6 +2308,14 @@
newTouchedWindowHandle =
findTouchedWindowAtLocked(displayId, x, y, &tempTouchState, isStylus);
+ // Verify targeted injection.
+ if (const auto err = verifyTargetedInjection(newTouchedWindowHandle, entry); err) {
+ ALOGW("Dropping injected event: %s", (*err).c_str());
+ injectionResult = os::InputEventInjectionResult::TARGET_MISMATCH;
+ newTouchedWindowHandle = nullptr;
+ goto Failed;
+ }
+
// Drop touch events if requested by input feature
if (newTouchedWindowHandle != nullptr &&
shouldDropInput(entry, newTouchedWindowHandle)) {
@@ -2356,19 +2407,26 @@
goto Failed;
}
- // Check permission to inject into all touched foreground windows.
- if (std::any_of(tempTouchState.windows.begin(), tempTouchState.windows.end(),
- [this, &entry](const TouchedWindow& touchedWindow) {
- return (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) != 0 &&
- !checkInjectionPermission(touchedWindow.windowHandle,
- entry.injectionState);
- })) {
- injectionResult = InputEventInjectionResult::PERMISSION_DENIED;
- injectionPermission = INJECTION_PERMISSION_DENIED;
- goto Failed;
+ // Ensure that all touched windows are valid for injection.
+ if (entry.injectionState != nullptr) {
+ std::string errs;
+ for (const TouchedWindow& touchedWindow : tempTouchState.windows) {
+ if (touchedWindow.targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
+ // Allow ACTION_OUTSIDE events generated by targeted injection to be
+ // dispatched to any uid, since the coords will be zeroed out later.
+ continue;
+ }
+ const auto err = verifyTargetedInjection(touchedWindow.windowHandle, entry);
+ if (err) errs += "\n - " + *err;
+ }
+ if (!errs.empty()) {
+ ALOGW("Dropping targeted injection: At least one touched window is not owned by uid "
+ "%d:%s",
+ *entry.injectionState->targetUid, errs.c_str());
+ injectionResult = InputEventInjectionResult::TARGET_MISMATCH;
+ goto Failed;
+ }
}
- // Permission granted to inject into all touched foreground windows.
- injectionPermission = INJECTION_PERMISSION_GRANTED;
// Check whether windows listening for outside touches are owned by the same UID. If it is
// set the policy flag that we will not reveal coordinate information to this window.
@@ -2434,19 +2492,6 @@
tempTouchState.filterNonAsIsTouchWindows();
Failed:
- // Check injection permission once and for all.
- if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
- if (checkInjectionPermission(nullptr, entry.injectionState)) {
- injectionPermission = INJECTION_PERMISSION_GRANTED;
- } else {
- injectionPermission = INJECTION_PERMISSION_DENIED;
- }
- }
-
- if (injectionPermission != INJECTION_PERMISSION_GRANTED) {
- return injectionResult;
- }
-
// Update final pieces of touch state if the injector had permission.
if (!wrongDevice) {
if (switchedDevice) {
@@ -2644,26 +2689,6 @@
}
}
-bool InputDispatcher::checkInjectionPermission(const sp<WindowInfoHandle>& windowHandle,
- const InjectionState* injectionState) {
- if (injectionState &&
- (windowHandle == nullptr ||
- windowHandle->getInfo()->ownerUid != injectionState->injectorUid) &&
- !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) {
- if (windowHandle != nullptr) {
- ALOGW("Permission denied: injecting event from pid %d uid %d to window %s "
- "owned by uid %d",
- injectionState->injectorPid, injectionState->injectorUid,
- windowHandle->getName().c_str(), windowHandle->getInfo()->ownerUid);
- } else {
- ALOGW("Permission denied: injecting event from pid %d uid %d",
- injectionState->injectorPid, injectionState->injectorUid);
- }
- return false;
- }
- return true;
-}
-
/**
* Indicate whether one window handle should be considered as obscuring
* another window handle. We only check a few preconditions. Actually
@@ -4182,20 +4207,20 @@
}
}
-InputEventInjectionResult InputDispatcher::injectInputEvent(
- const InputEvent* event, int32_t injectorPid, int32_t injectorUid,
- InputEventInjectionSync syncMode, std::chrono::milliseconds timeout, uint32_t policyFlags) {
+InputEventInjectionResult InputDispatcher::injectInputEvent(const InputEvent* event,
+ std::optional<int32_t> targetUid,
+ InputEventInjectionSync syncMode,
+ std::chrono::milliseconds timeout,
+ uint32_t policyFlags) {
if (DEBUG_INBOUND_EVENT_DETAILS) {
- ALOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
- "syncMode=%d, timeout=%lld, policyFlags=0x%08x",
- event->getType(), injectorPid, injectorUid, syncMode, timeout.count(), policyFlags);
+ ALOGD("injectInputEvent - eventType=%d, targetUid=%s, syncMode=%d, timeout=%lld, "
+ "policyFlags=0x%08x",
+ event->getType(), targetUid ? std::to_string(*targetUid).c_str() : "none", syncMode,
+ timeout.count(), policyFlags);
}
nsecs_t endTime = now() + std::chrono::duration_cast<std::chrono::nanoseconds>(timeout).count();
- policyFlags |= POLICY_FLAG_INJECTED;
- if (hasInjectionPermission(injectorPid, injectorUid)) {
- policyFlags |= POLICY_FLAG_TRUSTED;
- }
+ policyFlags |= POLICY_FLAG_INJECTED | POLICY_FLAG_TRUSTED;
// For all injected events, set device id = VIRTUAL_KEYBOARD_ID. The only exception is events
// that have gone through the InputFilter. If the event passed through the InputFilter, assign
@@ -4336,7 +4361,7 @@
return InputEventInjectionResult::FAILED;
}
- InjectionState* injectionState = new InjectionState(injectorPid, injectorUid);
+ InjectionState* injectionState = new InjectionState(targetUid);
if (syncMode == InputEventInjectionSync::NONE) {
injectionState->injectionIsAsync = true;
}
@@ -4408,8 +4433,7 @@
} // release lock
if (DEBUG_INJECTION) {
- ALOGD("injectInputEvent - Finished with result %d. injectorPid=%d, injectorUid=%d",
- injectionResult, injectorPid, injectorUid);
+ ALOGD("injectInputEvent - Finished with result %d.", injectionResult);
}
return injectionResult;
@@ -4448,19 +4472,12 @@
return result;
}
-bool InputDispatcher::hasInjectionPermission(int32_t injectorPid, int32_t injectorUid) {
- return injectorUid == 0 ||
- mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid);
-}
-
void InputDispatcher::setInjectionResult(EventEntry& entry,
InputEventInjectionResult injectionResult) {
InjectionState* injectionState = entry.injectionState;
if (injectionState) {
if (DEBUG_INJECTION) {
- ALOGD("Setting input event injection result to %d. "
- "injectorPid=%d, injectorUid=%d",
- injectionResult, injectionState->injectorPid, injectionState->injectorUid);
+ ALOGD("Setting input event injection result to %d.", injectionResult);
}
if (injectionState->injectionIsAsync && !(entry.policyFlags & POLICY_FLAG_FILTERED)) {
@@ -4469,12 +4486,12 @@
case InputEventInjectionResult::SUCCEEDED:
ALOGV("Asynchronous input event injection succeeded.");
break;
+ case InputEventInjectionResult::TARGET_MISMATCH:
+ ALOGV("Asynchronous input event injection target mismatch.");
+ break;
case InputEventInjectionResult::FAILED:
ALOGW("Asynchronous input event injection failed.");
break;
- case InputEventInjectionResult::PERMISSION_DENIED:
- ALOGW("Asynchronous input event injection permission denied.");
- break;
case InputEventInjectionResult::TIMED_OUT:
ALOGW("Asynchronous input event injection timed out.");
break;
@@ -4990,21 +5007,11 @@
toString(mInTouchMode), toString(inTouchMode), pid, uid, toString(hasPermission));
}
if (!hasPermission) {
- const sp<IBinder> focusedToken =
- mFocusResolver.getFocusedWindowToken(mFocusedDisplayId);
-
- // TODO(b/218541064): if no window is currently focused, then we need to check the last
- // interacted window (within 1 second timeout). We should allow touch mode change
- // if the last interacted window owner's pid/uid match the calling ones.
- if (focusedToken == nullptr) {
- return false;
- }
- const sp<WindowInfoHandle> windowHandle = getWindowHandleLocked(focusedToken);
- if (windowHandle == nullptr) {
- return false;
- }
- const WindowInfo* windowInfo = windowHandle->getInfo();
- if (pid != windowInfo->ownerPid || uid != windowInfo->ownerUid) {
+ if (!focusedWindowIsOwnedByLocked(pid, uid) &&
+ !recentWindowsAreOwnedByLocked(pid, uid)) {
+ ALOGD("Touch mode switch rejected, caller (pid=%d, uid=%d) doesn't own the focused "
+ "window nor none of the previously interacted window",
+ pid, uid);
return false;
}
}
@@ -5022,6 +5029,24 @@
return true;
}
+bool InputDispatcher::focusedWindowIsOwnedByLocked(int32_t pid, int32_t uid) {
+ const sp<IBinder> focusedToken = mFocusResolver.getFocusedWindowToken(mFocusedDisplayId);
+ if (focusedToken == nullptr) {
+ return false;
+ }
+ sp<WindowInfoHandle> windowHandle = getWindowHandleLocked(focusedToken);
+ return isWindowOwnedBy(windowHandle, pid, uid);
+}
+
+bool InputDispatcher::recentWindowsAreOwnedByLocked(int32_t pid, int32_t uid) {
+ return std::find_if(mInteractionConnectionTokens.begin(), mInteractionConnectionTokens.end(),
+ [&](const sp<IBinder>& connectionToken) REQUIRES(mLock) {
+ const sp<WindowInfoHandle> windowHandle =
+ getWindowHandleLocked(connectionToken);
+ return isWindowOwnedBy(windowHandle, pid, uid);
+ }) != mInteractionConnectionTokens.end();
+}
+
void InputDispatcher::setMaximumObscuringOpacityForTouch(float opacity) {
if (opacity < 0 || opacity > 1) {
LOG_ALWAYS_FATAL("Maximum obscuring opacity for touch should be >= 0 and <= 1");
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 3c79c98..a9fb5c6 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -104,7 +104,7 @@
void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override;
android::os::InputEventInjectionResult injectInputEvent(
- const InputEvent* event, int32_t injectorPid, int32_t injectorUid,
+ const InputEvent* event, std::optional<int32_t> targetUid,
android::os::InputEventInjectionSync syncMode, std::chrono::milliseconds timeout,
uint32_t policyFlags) override;
@@ -275,7 +275,6 @@
// Event injection and synchronization.
std::condition_variable mInjectionResultAvailable;
- bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid);
void setInjectionResult(EventEntry& entry,
android::os::InputEventInjectionResult injectionResult);
void transformMotionEntryForInjectionLocked(MotionEntry&,
@@ -433,7 +432,8 @@
// Dispatcher state at time of last ANR.
std::string mLastAnrState GUARDED_BY(mLock);
- // The connection tokens of the channels that the user last interacted, for debugging
+ // The connection tokens of the channels that the user last interacted (used for debugging and
+ // when switching touch mode state).
std::unordered_set<sp<IBinder>, StrongPointerHash<IBinder>> mInteractionConnectionTokens
GUARDED_BY(mLock);
void updateInteractionTokensLocked(const EventEntry& entry,
@@ -550,8 +550,6 @@
void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets, int32_t displayId)
REQUIRES(mLock);
void pokeUserActivityLocked(const EventEntry& eventEntry) REQUIRES(mLock);
- bool checkInjectionPermission(const sp<android::gui::WindowInfoHandle>& windowHandle,
- const InjectionState* injectionState);
// Enqueue a drag event if needed, and update the touch state.
// Uses findTouchedWindowTargetsLocked to make the decision
void addDragEventLocked(const MotionEntry& entry) REQUIRES(mLock);
@@ -677,6 +675,10 @@
void traceOutboundQueueLength(const Connection& connection);
void traceWaitQueueLength(const Connection& connection);
+ // Check window ownership
+ bool focusedWindowIsOwnedByLocked(int32_t pid, int32_t uid) REQUIRES(mLock);
+ bool recentWindowsAreOwnedByLocked(int32_t pid, int32_t uid) REQUIRES(mLock);
+
sp<InputReporterInterface> mReporter;
};
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index 67e1b6f..100bd18 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -68,10 +68,16 @@
* input injection to proceed.
* Returns one of the INPUT_EVENT_INJECTION_XXX constants.
*
- * This method may be called on any thread (usually by the input manager).
+ * If a targetUid is provided, InputDispatcher will only consider injecting the input event into
+ * windows owned by the provided uid. If the input event is targeted at a window that is not
+ * owned by the provided uid, input injection will fail. If no targetUid is provided, the input
+ * event will be dispatched as-is.
+ *
+ * This method may be called on any thread (usually by the input manager). The caller must
+ * perform all necessary permission checks prior to injecting events.
*/
virtual android::os::InputEventInjectionResult injectInputEvent(
- const InputEvent* event, int32_t injectorPid, int32_t injectorUid,
+ const InputEvent* event, std::optional<int32_t> targetUid,
android::os::InputEventInjectionSync syncMode, std::chrono::milliseconds timeout,
uint32_t policyFlags) = 0;
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
index de0b6da..575b3d7 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
@@ -125,15 +125,6 @@
/* Poke user activity for an event dispatched to a window. */
virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) = 0;
- /* Checks whether a given application pid/uid has permission to inject input events
- * into other applications.
- *
- * This method is special in that its implementation promises to be non-reentrant and
- * is safe to call while holding other locks. (Most other methods make no such guarantees!)
- */
- virtual bool checkInjectEventsPermissionNonReentrant(int32_t injectorPid,
- int32_t injectorUid) = 0;
-
/* Notifies the policy that a pointer down event has occurred outside the current focused
* window.
*
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 8641287..f15ed9e 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -45,10 +45,10 @@
using namespace ftl::flag_operators;
// An arbitrary time value.
-static const nsecs_t ARBITRARY_TIME = 1234;
+static constexpr nsecs_t ARBITRARY_TIME = 1234;
// An arbitrary device id.
-static const int32_t DEVICE_ID = 1;
+static constexpr int32_t DEVICE_ID = 1;
// An arbitrary display id.
static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
@@ -56,12 +56,17 @@
static constexpr int32_t POINTER_1_DOWN =
AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+static constexpr int32_t POINTER_2_DOWN =
+ AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
static constexpr int32_t POINTER_1_UP =
AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
-// An arbitrary injector pid / uid pair that has permission to inject events.
-static const int32_t INJECTOR_PID = 999;
-static const int32_t INJECTOR_UID = 1001;
+// The default pid and uid for windows created by the test.
+static constexpr int32_t WINDOW_PID = 999;
+static constexpr int32_t WINDOW_UID = 1001;
+
+// The default policy flags to use for event injection by tests.
+static constexpr uint32_t DEFAULT_POLICY_FLAGS = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
// An arbitrary pid of the gesture monitor window
static constexpr int32_t MONITOR_PID = 2001;
@@ -470,10 +475,6 @@
void pokeUserActivity(nsecs_t, int32_t, int32_t) override {}
- bool checkInjectEventsPermissionNonReentrant(int32_t pid, int32_t uid) override {
- return pid == INJECTOR_PID && uid == INJECTOR_UID;
- }
-
void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
std::scoped_lock lock(mLock);
mOnPointerDownToken = newToken;
@@ -558,8 +559,8 @@
/*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
ARBITRARY_TIME);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
- InputEventInjectionSync::NONE, 0ms, 0))
+ mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
+ 0ms, 0))
<< "Should reject key events with undefined action.";
// Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
@@ -567,8 +568,8 @@
INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
ARBITRARY_TIME, ARBITRARY_TIME);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
- InputEventInjectionSync::NONE, 0ms, 0))
+ mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
+ 0ms, 0))
<< "Should reject key events with ACTION_MULTIPLE.";
}
@@ -597,8 +598,8 @@
ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
- InputEventInjectionSync::NONE, 0ms, 0))
+ mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
+ 0ms, 0))
<< "Should reject motion events with undefined action.";
// Rejects pointer down with invalid index.
@@ -609,8 +610,8 @@
ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
- InputEventInjectionSync::NONE, 0ms, 0))
+ mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
+ 0ms, 0))
<< "Should reject motion events with pointer down index too large.";
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
@@ -621,8 +622,8 @@
identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
- InputEventInjectionSync::NONE, 0ms, 0))
+ mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
+ 0ms, 0))
<< "Should reject motion events with pointer down index too small.";
// Rejects pointer up with invalid index.
@@ -633,8 +634,8 @@
ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
- InputEventInjectionSync::NONE, 0ms, 0))
+ mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
+ 0ms, 0))
<< "Should reject motion events with pointer up index too large.";
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
@@ -645,8 +646,8 @@
identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
- InputEventInjectionSync::NONE, 0ms, 0))
+ mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
+ 0ms, 0))
<< "Should reject motion events with pointer up index too small.";
// Rejects motion events with invalid number of pointers.
@@ -657,8 +658,8 @@
ARBITRARY_TIME,
/*pointerCount*/ 0, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
- InputEventInjectionSync::NONE, 0ms, 0))
+ mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
+ 0ms, 0))
<< "Should reject motion events with 0 pointers.";
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
@@ -668,8 +669,8 @@
ARBITRARY_TIME,
/*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
- InputEventInjectionSync::NONE, 0ms, 0))
+ mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
+ 0ms, 0))
<< "Should reject motion events with more than MAX_POINTERS pointers.";
// Rejects motion events with invalid pointer ids.
@@ -681,8 +682,8 @@
ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
- InputEventInjectionSync::NONE, 0ms, 0))
+ mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
+ 0ms, 0))
<< "Should reject motion events with pointer ids less than 0.";
pointerProperties[0].id = MAX_POINTER_ID + 1;
@@ -693,8 +694,8 @@
ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
- InputEventInjectionSync::NONE, 0ms, 0))
+ mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
+ 0ms, 0))
<< "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
// Rejects motion events with duplicate pointer ids.
@@ -707,8 +708,8 @@
ARBITRARY_TIME,
/*pointerCount*/ 2, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
- InputEventInjectionSync::NONE, 0ms, 0))
+ mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
+ 0ms, 0))
<< "Should reject motion events with duplicate pointer ids.";
}
@@ -1011,8 +1012,8 @@
mInfo.globalScaleFactor = 1.0;
mInfo.touchableRegion.clear();
mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
- mInfo.ownerPid = INJECTOR_PID;
- mInfo.ownerUid = INJECTOR_UID;
+ mInfo.ownerPid = WINDOW_PID;
+ mInfo.ownerUid = WINDOW_UID;
mInfo.displayId = displayId;
mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
}
@@ -1294,7 +1295,8 @@
int32_t displayId = ADISPLAY_ID_NONE,
InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
- bool allowKeyRepeat = true) {
+ bool allowKeyRepeat = true, std::optional<int32_t> targetUid = {},
+ uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
KeyEvent event;
nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -1303,13 +1305,11 @@
INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
repeatCount, currentTime, currentTime);
- int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
if (!allowKeyRepeat) {
policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
}
// Inject event until dispatch out.
- return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, syncMode,
- injectionTimeout, policyFlags);
+ return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
}
static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
@@ -1452,10 +1452,10 @@
static InputEventInjectionResult injectMotionEvent(
const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
- InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT) {
- return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
- injectionTimeout,
- POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
+ InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
+ std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
+ return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
+ policyFlags);
}
static InputEventInjectionResult injectMotionEvent(
@@ -1465,7 +1465,8 @@
AMOTION_EVENT_INVALID_CURSOR_POSITION},
std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
- nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC)) {
+ nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
+ std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
MotionEvent event = MotionEventBuilder(action, source)
.displayId(displayId)
.eventTime(eventTime)
@@ -1477,7 +1478,8 @@
.build();
// Inject event until dispatch out.
- return injectMotionEvent(dispatcher, event, injectionTimeout, injectionMode);
+ return injectMotionEvent(dispatcher, event, injectionTimeout, injectionMode, targetUid,
+ policyFlags);
}
static InputEventInjectionResult injectMotionDown(
@@ -2245,6 +2247,53 @@
}
/**
+ * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
+ * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
+ * ACTION_OUTSIDE event is sent per gesture.
+ */
+TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
+ // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> window =
+ new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
+ window->setWatchOutsideTouch(true);
+ window->setFrame(Rect{0, 0, 100, 100});
+ sp<FakeWindowHandle> secondWindow =
+ new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
+ secondWindow->setFrame(Rect{100, 100, 200, 200});
+ sp<FakeWindowHandle> thirdWindow =
+ new FakeWindowHandle(application, mDispatcher, "Third Window", ADISPLAY_ID_DEFAULT);
+ thirdWindow->setFrame(Rect{200, 200, 300, 300});
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
+
+ // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
+ NotifyMotionArgs motionArgs =
+ generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT, {PointF{-10, -10}});
+ mDispatcher->notifyMotion(&motionArgs);
+ window->assertNoEvents();
+ secondWindow->assertNoEvents();
+
+ // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
+ // Now, `window` should get ACTION_OUTSIDE.
+ motionArgs = generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {PointF{-10, -10}, PointF{105, 105}});
+ mDispatcher->notifyMotion(&motionArgs);
+ window->consumeMotionOutside();
+ secondWindow->consumeMotionDown();
+ thirdWindow->assertNoEvents();
+
+ // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
+ // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
+ motionArgs = generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}});
+ mDispatcher->notifyMotion(&motionArgs);
+ window->assertNoEvents();
+ secondWindow->consumeMotionMove();
+ thirdWindow->consumeMotionDown();
+}
+
+/**
* Ensure the correct coordinate spaces are used by InputDispatcher.
*
* InputDispatcher works in the display space, so its coordinate system is relative to the display
@@ -3466,8 +3515,8 @@
* FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
*/
TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
- constexpr int32_t SLIPPERY_PID = INJECTOR_PID + 1;
- constexpr int32_t SLIPPERY_UID = INJECTOR_UID + 1;
+ constexpr int32_t SLIPPERY_PID = WINDOW_PID + 1;
+ constexpr int32_t SLIPPERY_UID = WINDOW_UID + 1;
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
@@ -3994,7 +4043,7 @@
const int32_t additionalPolicyFlags =
POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
- mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ mDispatcher->injectInputEvent(&event, {} /*targetUid*/,
InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
policyFlags | additionalPolicyFlags));
@@ -4029,7 +4078,7 @@
const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
- mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ mDispatcher->injectInputEvent(&event, {} /*targetUid*/,
InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
policyFlags | additionalPolicyFlags));
@@ -4536,7 +4585,7 @@
const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
InputEventInjectionResult result =
- mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ mDispatcher->injectInputEvent(&event, {} /* targetUid */,
InputEventInjectionSync::WAIT_FOR_RESULT,
INJECT_EVENT_TIMEOUT, policyFlags);
ASSERT_EQ(InputEventInjectionResult::FAILED, result)
@@ -6336,8 +6385,11 @@
mWindow->consumeFocusEvent(true);
// Set initial touch mode to InputDispatcher::kDefaultInTouchMode.
- mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, INJECTOR_PID,
- INJECTOR_UID, /* hasPermission */ true);
+ if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
+ WINDOW_UID, /* hasPermission */ true)) {
+ mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
+ mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
+ }
}
void changeAndVerifyTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission) {
@@ -6382,6 +6434,23 @@
mSecondWindow->assertNoEvents();
}
+TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
+ // Interact with the window first.
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
+ << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
+ mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
+
+ // Then remove focus.
+ mWindow->setFocusable(false);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
+
+ // Assert that caller can switch touch mode by owning one of the last interacted window.
+ const WindowInfo& windowInfo = *mWindow->getInfo();
+ ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
+ windowInfo.ownerPid, windowInfo.ownerUid,
+ /* hasPermission= */ false));
+}
+
class InputDispatcherSpyWindowTest : public InputDispatcherTest {
public:
sp<FakeWindowHandle> createSpy() {
@@ -6666,9 +6735,7 @@
// Third finger goes down outside all windows, so injection should fail.
const MotionEvent thirdFingerDownEvent =
- MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
- (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- AINPUT_SOURCE_TOUCHSCREEN)
+ MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
.displayId(ADISPLAY_ID_DEFAULT)
.eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
.pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
@@ -6950,4 +7017,149 @@
window->assertNoEvents();
}
+struct User {
+ int32_t mPid;
+ int32_t mUid;
+ uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
+ std::unique_ptr<InputDispatcher>& mDispatcher;
+
+ User(std::unique_ptr<InputDispatcher>& dispatcher, int32_t pid, int32_t uid)
+ : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
+
+ InputEventInjectionResult injectTargetedMotion(int32_t action) const {
+ return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT, {100, 200},
+ {AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION},
+ INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
+ systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
+ }
+
+ InputEventInjectionResult injectTargetedKey(int32_t action) const {
+ return inputdispatcher::injectKey(mDispatcher, action, 0 /* repeatCount*/, ADISPLAY_ID_NONE,
+ InputEventInjectionSync::WAIT_FOR_RESULT,
+ INJECT_EVENT_TIMEOUT, false /*allowKeyRepeat*/, {mUid},
+ mPolicyFlags);
+ }
+
+ sp<FakeWindowHandle> createWindow() const {
+ std::shared_ptr<FakeApplicationHandle> overlayApplication =
+ std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> window = new FakeWindowHandle(overlayApplication, mDispatcher,
+ "Owned Window", ADISPLAY_ID_DEFAULT);
+ window->setOwnerInfo(mPid, mUid);
+ return window;
+ }
+};
+
+using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
+
+TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
+ auto owner = User(mDispatcher, 10, 11);
+ auto window = owner.createWindow();
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
+
+ EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
+ owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
+ window->consumeMotionDown();
+
+ setFocusedWindow(window);
+ window->consumeFocusEvent(true);
+
+ EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
+ owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
+ window->consumeKeyDown(ADISPLAY_ID_NONE);
+}
+
+TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
+ auto owner = User(mDispatcher, 10, 11);
+ auto window = owner.createWindow();
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
+
+ auto rando = User(mDispatcher, 20, 21);
+ EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
+ rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
+
+ setFocusedWindow(window);
+ window->consumeFocusEvent(true);
+
+ EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
+ rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
+ window->assertNoEvents();
+}
+
+TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
+ auto owner = User(mDispatcher, 10, 11);
+ auto window = owner.createWindow();
+ auto spy = owner.createWindow();
+ spy->setSpy(true);
+ spy->setTrustedOverlay(true);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
+
+ EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
+ owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
+ spy->consumeMotionDown();
+ window->consumeMotionDown();
+}
+
+TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
+ auto owner = User(mDispatcher, 10, 11);
+ auto window = owner.createWindow();
+
+ auto rando = User(mDispatcher, 20, 21);
+ auto randosSpy = rando.createWindow();
+ randosSpy->setSpy(true);
+ randosSpy->setTrustedOverlay(true);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
+
+ // The event is targeted at owner's window, so injection should succeed, but the spy should
+ // not receive the event.
+ EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
+ owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
+ randosSpy->assertNoEvents();
+ window->consumeMotionDown();
+}
+
+TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
+ auto owner = User(mDispatcher, 10, 11);
+ auto window = owner.createWindow();
+
+ auto rando = User(mDispatcher, 20, 21);
+ auto randosSpy = rando.createWindow();
+ randosSpy->setSpy(true);
+ randosSpy->setTrustedOverlay(true);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
+
+ // A user that has injection permission can inject into any window.
+ EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT));
+ randosSpy->consumeMotionDown();
+ window->consumeMotionDown();
+
+ setFocusedWindow(randosSpy);
+ randosSpy->consumeFocusEvent(true);
+
+ EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
+ randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
+ window->assertNoEvents();
+}
+
+TEST_F(InputDispatcherTargetedInjectionTest, CanGenerateActionOutsideToOtherUids) {
+ auto owner = User(mDispatcher, 10, 11);
+ auto window = owner.createWindow();
+
+ auto rando = User(mDispatcher, 20, 21);
+ auto randosWindow = rando.createWindow();
+ randosWindow->setFrame(Rect{-10, -10, -5, -5});
+ randosWindow->setWatchOutsideTouch(true);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
+
+ // We allow generation of ACTION_OUTSIDE events into windows owned by different uids.
+ EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
+ owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
+ window->consumeMotionDown();
+ randosWindow->consumeMotionOutside();
+}
+
} // namespace android::inputdispatcher
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 5ba8a1b..cbea77e 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -346,6 +346,12 @@
VsyncEventData EventThread::getLatestVsyncEventData(
const sp<EventThreadConnection>& connection) const {
+ // Resync so that the vsync is accurate with hardware. getLatestVsyncEventData is an alternate
+ // way to get vsync data (instead of posting callbacks to Choreographer).
+ if (connection->resyncCallback) {
+ connection->resyncCallback();
+ }
+
VsyncEventData vsyncEventData;
nsecs_t frameInterval = mGetVsyncPeriodFunction(connection->mOwnerUid);
vsyncEventData.frameInterval = frameInterval;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ec6d38d..8850c76 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -5471,20 +5471,14 @@
case SET_DESIRED_DISPLAY_MODE_SPECS:
case GET_DESIRED_DISPLAY_MODE_SPECS:
case SET_ACTIVE_COLOR_MODE:
- case GET_BOOT_DISPLAY_MODE_SUPPORT:
case SET_BOOT_DISPLAY_MODE:
- case CLEAR_BOOT_DISPLAY_MODE:
case GET_AUTO_LOW_LATENCY_MODE_SUPPORT:
- case SET_AUTO_LOW_LATENCY_MODE:
case GET_GAME_CONTENT_TYPE_SUPPORT:
- case SET_GAME_CONTENT_TYPE:
- case SET_POWER_MODE:
case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES:
case SET_DISPLAY_CONTENT_SAMPLING_ENABLED:
case GET_DISPLAYED_CONTENT_SAMPLE:
case ADD_TUNNEL_MODE_ENABLED_LISTENER:
case REMOVE_TUNNEL_MODE_ENABLED_LISTENER:
- case NOTIFY_POWER_BOOST:
case SET_GLOBAL_SHADOW_SETTINGS:
case ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN: {
// OVERRIDE_HDR_TYPES is used by CTS tests, which acquire the necessary
@@ -5521,8 +5515,6 @@
case GET_STATIC_DISPLAY_INFO:
case GET_DYNAMIC_DISPLAY_INFO:
case GET_DISPLAY_MODES:
- case GET_DISPLAY_STATE:
- case GET_DISPLAY_STATS:
case GET_SUPPORTED_FRAME_TIMESTAMPS:
// Calling setTransactionState is safe, because you need to have been
// granted a reference to Client* and Handle* to do anything with it.
@@ -5531,11 +5523,9 @@
case GET_COLOR_MANAGEMENT:
case GET_COMPOSITION_PREFERENCE:
case GET_PROTECTED_CONTENT_SUPPORT:
- case IS_WIDE_COLOR_DISPLAY:
// setFrameRate() is deliberately available for apps to call without any
// special permissions.
case SET_FRAME_RATE:
- case GET_DISPLAY_BRIGHTNESS_SUPPORT:
case GET_DISPLAY_DECORATION_SUPPORT:
case SET_FRAME_TIMELINE_INFO:
case GET_GPU_CONTEXT_PRIORITY:
@@ -5543,19 +5533,6 @@
// This is not sensitive information, so should not require permission control.
return OK;
}
- case SET_DISPLAY_BRIGHTNESS:
- case ADD_HDR_LAYER_INFO_LISTENER:
- case REMOVE_HDR_LAYER_INFO_LISTENER: {
- IPCThreadState* ipc = IPCThreadState::self();
- const int pid = ipc->getCallingPid();
- const int uid = ipc->getCallingUid();
- if ((uid != AID_GRAPHICS) &&
- !PermissionCache::checkPermission(sControlDisplayBrightness, pid, uid)) {
- ALOGE("Permission Denial: can't control brightness pid=%d, uid=%d", pid, uid);
- return PERMISSION_DENIED;
- }
- return OK;
- }
case ADD_FPS_LISTENER:
case REMOVE_FPS_LISTENER:
case ADD_REGION_SAMPLING_LISTENER:
@@ -5606,9 +5583,22 @@
case GET_PRIMARY_PHYSICAL_DISPLAY_ID:
case GET_PHYSICAL_DISPLAY_IDS:
case GET_PHYSICAL_DISPLAY_TOKEN:
+ case SET_POWER_MODE:
+ case GET_DISPLAY_STATE:
+ case GET_DISPLAY_STATS:
+ case CLEAR_BOOT_DISPLAY_MODE:
+ case GET_BOOT_DISPLAY_MODE_SUPPORT:
+ case SET_AUTO_LOW_LATENCY_MODE:
+ case SET_GAME_CONTENT_TYPE:
case CAPTURE_LAYERS:
case CAPTURE_DISPLAY:
case CAPTURE_DISPLAY_BY_ID:
+ case IS_WIDE_COLOR_DISPLAY:
+ case GET_DISPLAY_BRIGHTNESS_SUPPORT:
+ case SET_DISPLAY_BRIGHTNESS:
+ case ADD_HDR_LAYER_INFO_LISTENER:
+ case REMOVE_HDR_LAYER_INFO_LISTENER:
+ case NOTIFY_POWER_BOOST:
LOG_FATAL("Deprecated opcode: %d, migrated to AIDL", code);
return PERMISSION_DENIED;
}
@@ -7367,6 +7357,70 @@
return binder::Status::ok();
}
+binder::Status SurfaceComposerAIDL::setPowerMode(const sp<IBinder>& display, int mode) {
+ status_t status = checkAccessPermission();
+ if (status != OK) return binder::Status::fromStatusT(status);
+
+ mFlinger->setPowerMode(display, mode);
+ return binder::Status::ok();
+}
+
+binder::Status SurfaceComposerAIDL::getDisplayStats(const sp<IBinder>& display,
+ gui::DisplayStatInfo* outStatInfo) {
+ DisplayStatInfo statInfo;
+ status_t status = mFlinger->getDisplayStats(display, &statInfo);
+ if (status == NO_ERROR) {
+ outStatInfo->vsyncTime = static_cast<long>(statInfo.vsyncTime);
+ outStatInfo->vsyncPeriod = static_cast<long>(statInfo.vsyncPeriod);
+ }
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getDisplayState(const sp<IBinder>& display,
+ gui::DisplayState* outState) {
+ ui::DisplayState state;
+ status_t status = mFlinger->getDisplayState(display, &state);
+ if (status == NO_ERROR) {
+ outState->layerStack = state.layerStack.id;
+ outState->orientation = static_cast<gui::Rotation>(state.orientation);
+ outState->layerStackSpaceRect.width = state.layerStackSpaceRect.width;
+ outState->layerStackSpaceRect.height = state.layerStackSpaceRect.height;
+ }
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::clearBootDisplayMode(const sp<IBinder>& display) {
+ status_t status = checkAccessPermission();
+ if (status != OK) return binder::Status::fromStatusT(status);
+
+ status = mFlinger->clearBootDisplayMode(display);
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getBootDisplayModeSupport(bool* outMode) {
+ status_t status = checkAccessPermission();
+ if (status != OK) return binder::Status::fromStatusT(status);
+
+ status = mFlinger->getBootDisplayModeSupport(outMode);
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::setAutoLowLatencyMode(const sp<IBinder>& display, bool on) {
+ status_t status = checkAccessPermission();
+ if (status != OK) return binder::Status::fromStatusT(status);
+
+ mFlinger->setAutoLowLatencyMode(display, on);
+ return binder::Status::ok();
+}
+
+binder::Status SurfaceComposerAIDL::setGameContentType(const sp<IBinder>& display, bool on) {
+ status_t status = checkAccessPermission();
+ if (status != OK) return binder::Status::fromStatusT(status);
+
+ mFlinger->setGameContentType(display, on);
+ return binder::Status::ok();
+}
+
binder::Status SurfaceComposerAIDL::captureDisplay(
const DisplayCaptureArgs& args, const sp<IScreenCaptureListener>& captureListener) {
status_t status = mFlinger->captureDisplay(args, captureListener);
@@ -7393,6 +7447,53 @@
return binder::Status::fromStatusT(status);
}
+binder::Status SurfaceComposerAIDL::isWideColorDisplay(const sp<IBinder>& token,
+ bool* outIsWideColorDisplay) {
+ status_t status = mFlinger->isWideColorDisplay(token, outIsWideColorDisplay);
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getDisplayBrightnessSupport(const sp<IBinder>& displayToken,
+ bool* outSupport) {
+ status_t status = mFlinger->getDisplayBrightnessSupport(displayToken, outSupport);
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::setDisplayBrightness(const sp<IBinder>& displayToken,
+ const gui::DisplayBrightness& brightness) {
+ status_t status = checkControlDisplayBrightnessPermission();
+ if (status != OK) return binder::Status::fromStatusT(status);
+
+ status = mFlinger->setDisplayBrightness(displayToken, brightness);
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::addHdrLayerInfoListener(
+ const sp<IBinder>& displayToken, const sp<gui::IHdrLayerInfoListener>& listener) {
+ status_t status = checkControlDisplayBrightnessPermission();
+ if (status != OK) return binder::Status::fromStatusT(status);
+
+ status = mFlinger->addHdrLayerInfoListener(displayToken, listener);
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::removeHdrLayerInfoListener(
+ const sp<IBinder>& displayToken, const sp<gui::IHdrLayerInfoListener>& listener) {
+ status_t status = checkControlDisplayBrightnessPermission();
+ if (status != OK) return binder::Status::fromStatusT(status);
+
+ status = mFlinger->removeHdrLayerInfoListener(displayToken, listener);
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::notifyPowerBoost(int boostId) {
+ status_t status = checkAccessPermission();
+ if (status != OK) return binder::Status::fromStatusT(status);
+
+ status = mFlinger->notifyPowerBoost(boostId);
+ return binder::Status::fromStatusT(status);
+}
+
status_t SurfaceComposerAIDL::checkAccessPermission(bool usePermissionCache) {
if (!mFlinger->callingThreadHasUnscopedSurfaceFlingerAccess(usePermissionCache)) {
IPCThreadState* ipc = IPCThreadState::self();
@@ -7403,6 +7504,18 @@
return OK;
}
+status_t SurfaceComposerAIDL::checkControlDisplayBrightnessPermission() {
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+ if ((uid != AID_GRAPHICS) &&
+ !PermissionCache::checkPermission(sControlDisplayBrightness, pid, uid)) {
+ ALOGE("Permission Denial: can't control brightness pid=%d, uid=%d", pid, uid);
+ return PERMISSION_DENIED;
+ }
+ return OK;
+}
+
} // namespace android
#if defined(__gl_h_)
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 273cb91..ea2e71a 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -7,7 +7,6 @@
*
* 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
@@ -24,6 +23,8 @@
#include <android-base/thread_annotations.h>
#include <android/gui/BnSurfaceComposer.h>
+#include <android/gui/DisplayStatInfo.h>
+#include <android/gui/DisplayState.h>
#include <cutils/atomic.h>
#include <cutils/compiler.h>
#include <gui/BufferQueue.h>
@@ -568,9 +569,9 @@
status_t captureDisplay(DisplayId, const sp<IScreenCaptureListener>&);
status_t captureLayers(const LayerCaptureArgs&, const sp<IScreenCaptureListener>&);
- status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats) override;
+ status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats);
status_t getDisplayState(const sp<IBinder>& displayToken, ui::DisplayState*)
- EXCLUDES(mStateLock) override;
+ EXCLUDES(mStateLock);
status_t getStaticDisplayInfo(const sp<IBinder>& displayToken, ui::StaticDisplayInfo*)
EXCLUDES(mStateLock) override;
status_t getDynamicDisplayInfo(const sp<IBinder>& displayToken, ui::DynamicDisplayInfo*)
@@ -578,12 +579,12 @@
status_t getDisplayNativePrimaries(const sp<IBinder>& displayToken,
ui::DisplayPrimaries&) override;
status_t setActiveColorMode(const sp<IBinder>& displayToken, ui::ColorMode colorMode) override;
- status_t getBootDisplayModeSupport(bool* outSupport) const override;
+ status_t getBootDisplayModeSupport(bool* outSupport) const;
status_t setBootDisplayMode(const sp<IBinder>& displayToken, ui::DisplayModeId id) override;
- status_t clearBootDisplayMode(const sp<IBinder>& displayToken) override;
- void setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on) override;
- void setGameContentType(const sp<IBinder>& displayToken, bool on) override;
- void setPowerMode(const sp<IBinder>& displayToken, int mode) override;
+ status_t clearBootDisplayMode(const sp<IBinder>& displayToken);
+ void setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on);
+ void setGameContentType(const sp<IBinder>& displayToken, bool on);
+ void setPowerMode(const sp<IBinder>& displayToken, int mode);
status_t clearAnimationFrameStats() override;
status_t getAnimationFrameStats(FrameStats* outStats) const override;
status_t overrideHdrTypes(const sp<IBinder>& displayToken,
@@ -606,8 +607,7 @@
uint64_t timestamp,
DisplayedFrameStats* outStats) const override;
status_t getProtectedContentSupport(bool* outSupported) const override;
- status_t isWideColorDisplay(const sp<IBinder>& displayToken,
- bool* outIsWideColorDisplay) const override;
+ status_t isWideColorDisplay(const sp<IBinder>& displayToken, bool* outIsWideColorDisplay) const;
status_t addRegionSamplingListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle,
const sp<IRegionSamplingListener>& listener) override;
status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) override;
@@ -629,15 +629,14 @@
float* outPrimaryRefreshRateMax,
float* outAppRequestRefreshRateMin,
float* outAppRequestRefreshRateMax) override;
- status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken,
- bool* outSupport) const override;
+ status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken, bool* outSupport) const;
status_t setDisplayBrightness(const sp<IBinder>& displayToken,
- const gui::DisplayBrightness& brightness) override;
+ const gui::DisplayBrightness& brightness);
status_t addHdrLayerInfoListener(const sp<IBinder>& displayToken,
- const sp<gui::IHdrLayerInfoListener>& listener) override;
+ const sp<gui::IHdrLayerInfoListener>& listener);
status_t removeHdrLayerInfoListener(const sp<IBinder>& displayToken,
- const sp<gui::IHdrLayerInfoListener>& listener) override;
- status_t notifyPowerBoost(int32_t boostId) override;
+ const sp<gui::IHdrLayerInfoListener>& listener);
+ status_t notifyPowerBoost(int32_t boostId);
status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor,
float lightPosY, float lightPosZ, float lightRadius) override;
status_t getDisplayDecorationSupport(
@@ -1462,16 +1461,37 @@
binder::Status getPhysicalDisplayIds(std::vector<int64_t>* outDisplayIds) override;
binder::Status getPrimaryPhysicalDisplayId(int64_t* outDisplayId) override;
binder::Status getPhysicalDisplayToken(int64_t displayId, sp<IBinder>* outDisplay) override;
-
+ binder::Status setPowerMode(const sp<IBinder>& display, int mode) override;
+ binder::Status getDisplayStats(const sp<IBinder>& display,
+ gui::DisplayStatInfo* outStatInfo) override;
+ binder::Status getDisplayState(const sp<IBinder>& display,
+ gui::DisplayState* outState) override;
+ binder::Status clearBootDisplayMode(const sp<IBinder>& display) override;
+ binder::Status getBootDisplayModeSupport(bool* outMode) override;
+ binder::Status setAutoLowLatencyMode(const sp<IBinder>& display, bool on) override;
+ binder::Status setGameContentType(const sp<IBinder>& display, bool on) override;
binder::Status captureDisplay(const DisplayCaptureArgs&,
const sp<IScreenCaptureListener>&) override;
binder::Status captureDisplayById(int64_t, const sp<IScreenCaptureListener>&) override;
binder::Status captureLayers(const LayerCaptureArgs&,
const sp<IScreenCaptureListener>&) override;
+ binder::Status isWideColorDisplay(const sp<IBinder>& token,
+ bool* outIsWideColorDisplay) override;
+ binder::Status getDisplayBrightnessSupport(const sp<IBinder>& displayToken,
+ bool* outSupport) override;
+ binder::Status setDisplayBrightness(const sp<IBinder>& displayToken,
+ const gui::DisplayBrightness& brightness) override;
+ binder::Status addHdrLayerInfoListener(const sp<IBinder>& displayToken,
+ const sp<gui::IHdrLayerInfoListener>& listener) override;
+ binder::Status removeHdrLayerInfoListener(
+ const sp<IBinder>& displayToken,
+ const sp<gui::IHdrLayerInfoListener>& listener) override;
+ binder::Status notifyPowerBoost(int boostId) override;
private:
static const constexpr bool kUsePermissionCache = true;
status_t checkAccessPermission(bool usePermissionCache = kUsePermissionCache);
+ status_t checkControlDisplayBrightnessPermission();
private:
sp<SurfaceFlinger> mFlinger;
diff --git a/services/surfaceflinger/tests/BootDisplayMode_test.cpp b/services/surfaceflinger/tests/BootDisplayMode_test.cpp
index abdb16d..d70908e 100644
--- a/services/surfaceflinger/tests/BootDisplayMode_test.cpp
+++ b/services/surfaceflinger/tests/BootDisplayMode_test.cpp
@@ -20,28 +20,33 @@
#include <gui/SurfaceComposerClient.h>
#include <private/gui/ComposerService.h>
+#include <private/gui/ComposerServiceAIDL.h>
#include <chrono>
namespace android {
TEST(BootDisplayModeTest, setBootDisplayMode) {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ sp<gui::ISurfaceComposer> sf_aidl(ComposerServiceAIDL::getComposerService());
auto displayToken = SurfaceComposerClient::getInternalDisplayToken();
bool bootModeSupport = false;
- ASSERT_NO_FATAL_FAILURE(sf->getBootDisplayModeSupport(&bootModeSupport));
+ binder::Status status = sf_aidl->getBootDisplayModeSupport(&bootModeSupport);
+ ASSERT_NO_FATAL_FAILURE(status.transactionError());
if (bootModeSupport) {
ASSERT_EQ(NO_ERROR, sf->setBootDisplayMode(displayToken, 0));
}
}
TEST(BootDisplayModeTest, clearBootDisplayMode) {
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
auto displayToken = SurfaceComposerClient::getInternalDisplayToken();
bool bootModeSupport = false;
- ASSERT_NO_FATAL_FAILURE(sf->getBootDisplayModeSupport(&bootModeSupport));
+ binder::Status status = sf->getBootDisplayModeSupport(&bootModeSupport);
+ ASSERT_NO_FATAL_FAILURE(status.transactionError());
if (bootModeSupport) {
- ASSERT_EQ(NO_ERROR, sf->clearBootDisplayMode(displayToken));
+ status = sf->clearBootDisplayMode(displayToken);
+ ASSERT_EQ(NO_ERROR, status.transactionError());
}
}
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index fa36d9c..c033af8 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -415,6 +415,10 @@
EXPECT_CALL(*mVSyncSource, getLatestVSyncData()).WillOnce(Return(preferredData));
VsyncEventData vsyncEventData = mThread->getLatestVsyncEventData(mConnection);
+
+ // Check EventThread immediately requested a resync.
+ EXPECT_TRUE(mResyncCallRecorder.waitForCall().has_value());
+
EXPECT_GT(vsyncEventData.frameTimelines[0].deadlineTimestamp, now)
<< "Deadline timestamp should be greater than frame time";
for (size_t i = 0; i < VsyncEventData::kFrameTimelinesLength; i++) {