Merge "SF: Add composition strategy prediction stats" into tm-dev
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index e7bde21..3d4ba6f 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -723,10 +723,10 @@
}
// TODO(b/220095381): Due to boot time regression, we have omitted call to
- // createAppDirectoryForSupplementalData from here temporarily (unless it's for testing)
+ // createSdkSandboxDataDirectory from here temporarily (unless it's for testing)
if (uuid_ != nullptr && strcmp(uuid_, "TEST") == 0) {
- auto status = createAppDirectoryForSupplementalData(uuid, packageName, userId, appId,
- previousAppId, seInfo, flags);
+ auto status = createSdkSandboxDataDirectory(uuid, packageName, userId, appId, previousAppId,
+ seInfo, flags);
if (!status.isOk()) {
return status;
}
@@ -736,15 +736,15 @@
}
/**
- * Responsible for creating /data/user/0/supplemental/<app-name> directory and other
+ * Responsible for creating /data/misc_{ce|de}/user/0/sdksandbox/<app-name> directory and other
* app level sub directories, such as ./shared
*/
-binder::Status InstalldNativeService::createAppDirectoryForSupplementalData(
+binder::Status InstalldNativeService::createSdkSandboxDataDirectory(
const std::optional<std::string>& uuid, const std::string& packageName, int32_t userId,
int32_t appId, int32_t previousAppId, const std::string& seInfo, int32_t flags) {
- int32_t supplementalUid = multiuser_get_supplemental_uid(userId, appId);
- if (supplementalUid == -1) {
- // There no valid supplemental process for this app. Skip creation of data directory
+ int32_t sdkSandboxUid = multiuser_get_sdk_sandbox_uid(userId, appId);
+ if (sdkSandboxUid == -1) {
+ // There no valid sdk sandbox process for this app. Skip creation of data directory
return ok();
}
@@ -759,35 +759,35 @@
}
bool isCeData = (currentFlag == FLAG_STORAGE_CE);
- // /data/misc_{ce,de}/<user-id>/supplemental directory gets created by vold
+ // /data/misc_{ce,de}/<user-id>/sdksandbox directory gets created by vold
// during user creation
// Prepare the app directory
- auto appPath = create_data_misc_supplemental_package_path(uuid_, isCeData, userId,
- packageName.c_str());
+ auto appPath = create_data_misc_sdk_sandbox_package_path(uuid_, isCeData, userId,
+ packageName.c_str());
if (prepare_app_dir(appPath, 0751, AID_SYSTEM)) {
return error("Failed to prepare " + appPath);
}
// Now prepare the shared directory which will be accessible by all codes
- auto sharedPath = create_data_misc_supplemental_shared_path(uuid_, isCeData, userId,
- packageName.c_str());
+ auto sharedPath = create_data_misc_sdk_sandbox_shared_path(uuid_, isCeData, userId,
+ packageName.c_str());
- int32_t previousSupplementalUid = multiuser_get_supplemental_uid(userId, previousAppId);
+ int32_t previousSdkSandboxUid = multiuser_get_sdk_sandbox_uid(userId, previousAppId);
int32_t cacheGid = multiuser_get_cache_gid(userId, appId);
if (cacheGid == -1) {
return exception(binder::Status::EX_ILLEGAL_STATE,
- StringPrintf("cacheGid cannot be -1 for supplemental data"));
+ StringPrintf("cacheGid cannot be -1 for sdksandbox data"));
}
- auto status = createAppDataDirs(sharedPath, supplementalUid, &previousSupplementalUid,
- cacheGid, seInfo, 0700);
+ auto status = createAppDataDirs(sharedPath, sdkSandboxUid, &previousSdkSandboxUid, cacheGid,
+ seInfo, 0700);
if (!status.isOk()) {
return status;
}
// TODO(b/211763739): We also need to handle art profile creations
- // TODO(b/211763739): And return the CE inode of the supplemental root directory and
+ // TODO(b/211763739): And return the CE inode of the sdksandbox root directory and
// app directory under it so we can clear contents while CE storage is locked
}
@@ -2084,6 +2084,10 @@
const std::vector<std::string>& codePaths, std::vector<int64_t>* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
+ if (packageNames.size() != ceDataInodes.size()) {
+ return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
+ "packageNames/ceDataInodes size mismatch.");
+ }
for (const auto& packageName : packageNames) {
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
}
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 6b4ba1f..c9a4d50 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -205,11 +205,10 @@
const std::string& seInfo, int32_t targetSdkVersion,
int64_t* _aidl_return);
- binder::Status createAppDirectoryForSupplementalData(const std::optional<std::string>& uuid,
- const std::string& packageName,
- int32_t userId, int32_t appId,
- int32_t previousAppId,
- const std::string& seInfo, int32_t flags);
+ binder::Status createSdkSandboxDataDirectory(const std::optional<std::string>& uuid,
+ const std::string& packageName, int32_t userId,
+ int32_t appId, int32_t previousAppId,
+ const std::string& seInfo, int32_t flags);
};
} // namespace installd
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
index 703a096..21ab5b8 100644
--- a/cmds/installd/tests/installd_service_test.cpp
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -81,7 +81,7 @@
static constexpr const uid_t kTestAppId = 19999;
const gid_t kTestAppUid = multiuser_get_uid(kTestUserId, kTestAppId);
-const uid_t kTestAppSupplementalUid = multiuser_get_supplemental_uid(kTestUserId, kTestAppId);
+const uid_t kTestSdkSandboxUid = multiuser_get_sdk_sandbox_uid(kTestUserId, kTestAppId);
#define FLAG_FORCE InstalldNativeService::FLAG_FORCE
@@ -491,6 +491,19 @@
system(removeCommand.c_str());
}
}
+TEST_F(ServiceTest, GetAppSizeWrongSizes) {
+ int32_t externalStorageAppId = -1;
+ std::vector<int64_t> externalStorageSize;
+
+ std::vector<std::string> codePaths;
+ std::vector<std::string> packageNames = {"package1", "package2"};
+ std::vector<int64_t> ceDataInodes = {0};
+
+ EXPECT_BINDER_FAIL(service->getAppSize(std::nullopt, packageNames, 0,
+ InstalldNativeService::FLAG_USE_QUOTA,
+ externalStorageAppId, ceDataInodes, codePaths,
+ &externalStorageSize));
+}
static bool mkdirs(const std::string& path, mode_t mode) {
struct stat sb;
if (stat(path.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode)) {
@@ -936,7 +949,7 @@
"com.foo", 10000, "", 0, 41, FLAG_STORAGE_DE));
}
-class AppSupplementalDataTest : public testing::Test {
+class SdkSandboxDataTest : public testing::Test {
public:
void CheckFileAccess(const std::string& path, uid_t uid, mode_t mode) {
const auto fullPath = "/data/local/tmp/" + path;
@@ -973,8 +986,8 @@
clearAppData();
ASSERT_TRUE(mkdirs("/data/local/tmp/user/0", 0700));
ASSERT_TRUE(mkdirs("/data/local/tmp/user_de/0", 0700));
- ASSERT_TRUE(mkdirs("/data/local/tmp/misc_ce/0/supplemental", 0700));
- ASSERT_TRUE(mkdirs("/data/local/tmp/misc_de/0/supplemental", 0700));
+ ASSERT_TRUE(mkdirs("/data/local/tmp/misc_ce/0/sdksandbox", 0700));
+ ASSERT_TRUE(mkdirs("/data/local/tmp/misc_de/0/sdksandbox", 0700));
init_globals_from_data_and_root();
}
@@ -993,7 +1006,7 @@
}
};
-TEST_F(AppSupplementalDataTest, CreateAppData_CreatesSupplementalAppData) {
+TEST_F(SdkSandboxDataTest, CreateAppData_CreatesSupplementalAppData) {
android::os::CreateAppDataResult result;
android::os::CreateAppDataArgs args = createAppDataArgs();
args.packageName = "com.foo";
@@ -1002,24 +1015,22 @@
// Create the app user data.
ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
- CheckFileAccess("misc_ce/0/supplemental/com.foo", kSystemUid, S_IFDIR | 0751);
- CheckFileAccess("misc_ce/0/supplemental/com.foo/shared", kTestAppSupplementalUid,
- S_IFDIR | 0700);
- CheckFileAccess("misc_ce/0/supplemental/com.foo/shared/cache", kTestAppSupplementalUid,
+ CheckFileAccess("misc_ce/0/sdksandbox/com.foo", kSystemUid, S_IFDIR | 0751);
+ CheckFileAccess("misc_ce/0/sdksandbox/com.foo/shared", kTestSdkSandboxUid, S_IFDIR | 0700);
+ CheckFileAccess("misc_ce/0/sdksandbox/com.foo/shared/cache", kTestSdkSandboxUid,
S_IFDIR | S_ISGID | 0771);
- CheckFileAccess("misc_ce/0/supplemental/com.foo/shared/code_cache", kTestAppSupplementalUid,
+ CheckFileAccess("misc_ce/0/sdksandbox/com.foo/shared/code_cache", kTestSdkSandboxUid,
S_IFDIR | S_ISGID | 0771);
- CheckFileAccess("misc_de/0/supplemental/com.foo", kSystemUid, S_IFDIR | 0751);
- CheckFileAccess("misc_de/0/supplemental/com.foo/shared", kTestAppSupplementalUid,
- S_IFDIR | 0700);
- CheckFileAccess("misc_de/0/supplemental/com.foo/shared/cache", kTestAppSupplementalUid,
+ CheckFileAccess("misc_de/0/sdksandbox/com.foo", kSystemUid, S_IFDIR | 0751);
+ CheckFileAccess("misc_de/0/sdksandbox/com.foo/shared", kTestSdkSandboxUid, S_IFDIR | 0700);
+ CheckFileAccess("misc_de/0/sdksandbox/com.foo/shared/cache", kTestSdkSandboxUid,
S_IFDIR | S_ISGID | 0771);
- CheckFileAccess("misc_de/0/supplemental/com.foo/shared/code_cache", kTestAppSupplementalUid,
+ CheckFileAccess("misc_de/0/sdksandbox/com.foo/shared/code_cache", kTestSdkSandboxUid,
S_IFDIR | S_ISGID | 0771);
}
-TEST_F(AppSupplementalDataTest, CreateAppData_CreatesSupplementalAppData_WithoutDeFlag) {
+TEST_F(SdkSandboxDataTest, CreateAppData_CreatesSupplementalAppData_WithoutDeFlag) {
android::os::CreateAppDataResult result;
android::os::CreateAppDataArgs args = createAppDataArgs();
args.packageName = "com.foo";
@@ -1029,13 +1040,13 @@
ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
// Only CE paths should exist
- CheckFileAccess("misc_ce/0/supplemental/com.foo", kSystemUid, S_IFDIR | 0751);
+ CheckFileAccess("misc_ce/0/sdksandbox/com.foo", kSystemUid, S_IFDIR | 0751);
// DE paths should not exist
- ASSERT_FALSE(exists("/data/local/tmp/misc_de/0/supplemental/com.foo"));
+ ASSERT_FALSE(exists("/data/local/tmp/misc_de/0/sdksandbox/com.foo"));
}
-TEST_F(AppSupplementalDataTest, CreateAppData_CreatesSupplementalAppData_WithoutCeFlag) {
+TEST_F(SdkSandboxDataTest, CreateAppData_CreatesSupplementalAppData_WithoutCeFlag) {
android::os::CreateAppDataResult result;
android::os::CreateAppDataArgs args = createAppDataArgs();
args.packageName = "com.foo";
@@ -1045,10 +1056,10 @@
ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
// CE paths should not exist
- ASSERT_FALSE(exists("/data/local/tmp/misc_ce/0/supplemental/com.foo"));
+ ASSERT_FALSE(exists("/data/local/tmp/misc_ce/0/sdksandbox/com.foo"));
// Only DE paths should exist
- CheckFileAccess("misc_de/0/supplemental/com.foo", kSystemUid, S_IFDIR | 0751);
+ CheckFileAccess("misc_de/0/sdksandbox/com.foo", kSystemUid, S_IFDIR | 0751);
}
} // namespace installd
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 8d1ccdc..17802a3 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -658,38 +658,36 @@
ASSERT_NE(0, create_dir_if_needed("/data/local/tmp/user/0/bar/baz", 0700));
}
-TEST_F(UtilsTest, TestSupplementalDataPaths) {
+TEST_F(UtilsTest, TestSdkSandboxDataPaths) {
// Ce data paths
- EXPECT_EQ("/data/misc_ce/0/supplemental",
- create_data_misc_supplemental_path(nullptr, /*isCeData=*/true, 0));
- EXPECT_EQ("/data/misc_ce/10/supplemental",
- create_data_misc_supplemental_path(nullptr, true, 10));
+ EXPECT_EQ("/data/misc_ce/0/sdksandbox",
+ create_data_misc_sdk_sandbox_path(nullptr, /*isCeData=*/true, 0));
+ EXPECT_EQ("/data/misc_ce/10/sdksandbox", create_data_misc_sdk_sandbox_path(nullptr, true, 10));
- EXPECT_EQ("/data/misc_ce/0/supplemental/com.foo",
- create_data_misc_supplemental_package_path(nullptr, true, 0, "com.foo"));
- EXPECT_EQ("/data/misc_ce/10/supplemental/com.foo",
- create_data_misc_supplemental_package_path(nullptr, true, 10, "com.foo"));
+ EXPECT_EQ("/data/misc_ce/0/sdksandbox/com.foo",
+ create_data_misc_sdk_sandbox_package_path(nullptr, true, 0, "com.foo"));
+ EXPECT_EQ("/data/misc_ce/10/sdksandbox/com.foo",
+ create_data_misc_sdk_sandbox_package_path(nullptr, true, 10, "com.foo"));
- EXPECT_EQ("/data/misc_ce/0/supplemental/com.foo/shared",
- create_data_misc_supplemental_shared_path(nullptr, true, 0, "com.foo"));
- EXPECT_EQ("/data/misc_ce/10/supplemental/com.foo/shared",
- create_data_misc_supplemental_shared_path(nullptr, true, 10, "com.foo"));
+ EXPECT_EQ("/data/misc_ce/0/sdksandbox/com.foo/shared",
+ create_data_misc_sdk_sandbox_shared_path(nullptr, true, 0, "com.foo"));
+ EXPECT_EQ("/data/misc_ce/10/sdksandbox/com.foo/shared",
+ create_data_misc_sdk_sandbox_shared_path(nullptr, true, 10, "com.foo"));
// De data paths
- EXPECT_EQ("/data/misc_de/0/supplemental",
- create_data_misc_supplemental_path(nullptr, /*isCeData=*/false, 0));
- EXPECT_EQ("/data/misc_de/10/supplemental",
- create_data_misc_supplemental_path(nullptr, false, 10));
+ EXPECT_EQ("/data/misc_de/0/sdksandbox",
+ create_data_misc_sdk_sandbox_path(nullptr, /*isCeData=*/false, 0));
+ EXPECT_EQ("/data/misc_de/10/sdksandbox", create_data_misc_sdk_sandbox_path(nullptr, false, 10));
- EXPECT_EQ("/data/misc_de/0/supplemental/com.foo",
- create_data_misc_supplemental_package_path(nullptr, false, 0, "com.foo"));
- EXPECT_EQ("/data/misc_de/10/supplemental/com.foo",
- create_data_misc_supplemental_package_path(nullptr, false, 10, "com.foo"));
+ EXPECT_EQ("/data/misc_de/0/sdksandbox/com.foo",
+ create_data_misc_sdk_sandbox_package_path(nullptr, false, 0, "com.foo"));
+ EXPECT_EQ("/data/misc_de/10/sdksandbox/com.foo",
+ create_data_misc_sdk_sandbox_package_path(nullptr, false, 10, "com.foo"));
- EXPECT_EQ("/data/misc_de/0/supplemental/com.foo/shared",
- create_data_misc_supplemental_shared_path(nullptr, false, 0, "com.foo"));
- EXPECT_EQ("/data/misc_de/10/supplemental/com.foo/shared",
- create_data_misc_supplemental_shared_path(nullptr, false, 10, "com.foo"));
+ EXPECT_EQ("/data/misc_de/0/sdksandbox/com.foo/shared",
+ create_data_misc_sdk_sandbox_shared_path(nullptr, false, 0, "com.foo"));
+ EXPECT_EQ("/data/misc_de/10/sdksandbox/com.foo/shared",
+ create_data_misc_sdk_sandbox_shared_path(nullptr, false, 10, "com.foo"));
}
TEST_F(UtilsTest, WaitChild) {
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 6650b76..992425d 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -198,39 +198,39 @@
}
/**
- * Create the path name where supplemental data for all apps will be stored.
- * E.g. /data/misc_ce/0/supplemental
+ * Create the path name where sdk_sandbox data for all apps will be stored.
+ * E.g. /data/misc_ce/0/sdksandbox
*/
-std::string create_data_misc_supplemental_path(const char* uuid, bool isCeData, userid_t user) {
+std::string create_data_misc_sdk_sandbox_path(const char* uuid, bool isCeData, userid_t user) {
std::string data(create_data_path(uuid));
if (isCeData) {
- return StringPrintf("%s/misc_ce/%d/supplemental", data.c_str(), user);
+ return StringPrintf("%s/misc_ce/%d/sdksandbox", data.c_str(), user);
} else {
- return StringPrintf("%s/misc_de/%d/supplemental", data.c_str(), user);
+ return StringPrintf("%s/misc_de/%d/sdksandbox", data.c_str(), user);
}
}
/**
* Create the path name where code data for all codes in a particular app will be stored.
- * E.g. /data/misc_ce/0/supplemental/<app-name>
+ * E.g. /data/misc_ce/0/sdksandbox/<app-name>
*/
-std::string create_data_misc_supplemental_package_path(const char* volume_uuid, bool isCeData,
- userid_t user, const char* package_name) {
+std::string create_data_misc_sdk_sandbox_package_path(const char* volume_uuid, bool isCeData,
+ userid_t user, const char* package_name) {
check_package_name(package_name);
return StringPrintf("%s/%s",
- create_data_misc_supplemental_path(volume_uuid, isCeData, user).c_str(),
+ create_data_misc_sdk_sandbox_path(volume_uuid, isCeData, user).c_str(),
package_name);
}
/**
* Create the path name where shared code data for a particular app will be stored.
- * E.g. /data/misc_ce/0/supplemental/<app-name>/shared
+ * E.g. /data/misc_ce/0/sdksandbox/<app-name>/shared
*/
-std::string create_data_misc_supplemental_shared_path(const char* volume_uuid, bool isCeData,
- userid_t user, const char* package_name) {
+std::string create_data_misc_sdk_sandbox_shared_path(const char* volume_uuid, bool isCeData,
+ userid_t user, const char* package_name) {
return StringPrintf("%s/shared",
- create_data_misc_supplemental_package_path(volume_uuid, isCeData, user,
- package_name)
+ create_data_misc_sdk_sandbox_package_path(volume_uuid, isCeData, user,
+ package_name)
.c_str());
}
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 2d00845..4b56f99 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -60,12 +60,12 @@
std::string create_data_user_ce_package_path_as_user_link(
const char* volume_uuid, userid_t userid, const char* package_name);
-std::string create_data_misc_supplemental_path(const char* volume_uuid, bool isCeData,
- userid_t userid);
-std::string create_data_misc_supplemental_package_path(const char* volume_uuid, bool isCeData,
- userid_t userid, const char* package_name);
-std::string create_data_misc_supplemental_shared_path(const char* volume_uuid, bool isCeData,
+std::string create_data_misc_sdk_sandbox_path(const char* volume_uuid, bool isCeData,
+ userid_t userid);
+std::string create_data_misc_sdk_sandbox_package_path(const char* volume_uuid, bool isCeData,
userid_t userid, const char* package_name);
+std::string create_data_misc_sdk_sandbox_shared_path(const char* volume_uuid, bool isCeData,
+ userid_t userid, const char* package_name);
std::string create_data_misc_ce_rollback_base_path(const char* volume_uuid, userid_t user);
std::string create_data_misc_de_rollback_base_path(const char* volume_uuid, userid_t user);
diff --git a/include/input/Input.h b/include/input/Input.h
index 2837add..b23a951 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -814,6 +814,8 @@
static vec2 calculateTransformedXY(uint32_t source, const ui::Transform&, const vec2& xy);
static float calculateTransformedAxisValue(int32_t axis, uint32_t source, const ui::Transform&,
const PointerCoords&);
+ static PointerCoords calculateTransformedCoords(uint32_t source, const ui::Transform&,
+ const PointerCoords&);
protected:
int32_t mAction;
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 3073d94..fe1754c 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -846,6 +846,7 @@
return calculateTransformedXYUnchecked(source, transform, xy);
}
+// Keep in sync with calculateTransformedCoords.
float MotionEvent::calculateTransformedAxisValue(int32_t axis, uint32_t source,
const ui::Transform& transform,
const PointerCoords& coords) {
@@ -874,6 +875,34 @@
return coords.getAxisValue(axis);
}
+// Keep in sync with calculateTransformedAxisValue. This is an optimization of
+// calculateTransformedAxisValue for all PointerCoords axes.
+PointerCoords MotionEvent::calculateTransformedCoords(uint32_t source,
+ const ui::Transform& transform,
+ const PointerCoords& coords) {
+ if (shouldDisregardTransformation(source)) {
+ return coords;
+ }
+ PointerCoords out = coords;
+
+ const vec2 xy = calculateTransformedXYUnchecked(source, transform, coords.getXYValue());
+ out.setAxisValue(AMOTION_EVENT_AXIS_X, xy.x);
+ out.setAxisValue(AMOTION_EVENT_AXIS_Y, xy.y);
+
+ const vec2 relativeXy =
+ transformWithoutTranslation(transform,
+ {coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X),
+ coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y)});
+ out.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, relativeXy.x);
+ out.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, relativeXy.y);
+
+ out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION,
+ transformAngle(transform,
+ coords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION)));
+
+ return out;
+}
+
// --- FocusEvent ---
void FocusEvent::initialize(int32_t id, bool hasFocus) {
diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
index cd20a64..9691ad8 100644
--- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
+++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
@@ -61,18 +61,13 @@
ALOGE("There is no focused window for %s", applicationHandle->getName().c_str());
}
- void notifyWindowUnresponsive(const sp<IBinder>& connectionToken,
+ void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<int32_t> pid,
const std::string& reason) override {
ALOGE("Window is not responding: %s", reason.c_str());
}
- void notifyWindowResponsive(const sp<IBinder>& connectionToken) override {}
-
- void notifyMonitorUnresponsive(int32_t pid, const std::string& reason) override {
- ALOGE("Monitor is not responding: %s", reason.c_str());
- }
-
- void notifyMonitorResponsive(int32_t pid) override {}
+ void notifyWindowResponsive(const sp<IBinder>& connectionToken,
+ std::optional<int32_t> pid) override {}
void notifyInputChannelBroken(const sp<IBinder>&) override {}
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 58c9303..32c3a12 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -4426,19 +4426,9 @@
const auto& transformToDisplay = it->second.transform.inverse() * injectedTransform;
for (uint32_t i = 0; i < entry.pointerCount; i++) {
- PointerCoords& pc = entry.pointerCoords[i];
- // Make a copy of the injected coords. We cannot change them in place because some of them
- // are interdependent (for example, X coordinate might depend on the Y coordinate).
- PointerCoords injectedCoords = entry.pointerCoords[i];
-
- BitSet64 bits(injectedCoords.bits);
- while (!bits.isEmpty()) {
- const auto axis = static_cast<int32_t>(bits.clearFirstMarkedBit());
- const float value =
- MotionEvent::calculateTransformedAxisValue(axis, entry.source,
- transformToDisplay, injectedCoords);
- pc.setAxisValue(axis, value);
- }
+ entry.pointerCoords[i] =
+ MotionEvent::calculateTransformedCoords(entry.source, transformToDisplay,
+ entry.pointerCoords[i]);
}
}
@@ -5816,35 +5806,21 @@
}
}
-void InputDispatcher::sendMonitorUnresponsiveCommandLocked(int32_t pid, std::string reason) {
- auto command = [this, pid, reason = std::move(reason)]() REQUIRES(mLock) {
- scoped_unlock unlock(mLock);
- mPolicy->notifyMonitorUnresponsive(pid, reason);
- };
- postCommandLocked(std::move(command));
-}
-
void InputDispatcher::sendWindowUnresponsiveCommandLocked(const sp<IBinder>& token,
+ std::optional<int32_t> pid,
std::string reason) {
- auto command = [this, token, reason = std::move(reason)]() REQUIRES(mLock) {
+ auto command = [this, token, pid, reason = std::move(reason)]() REQUIRES(mLock) {
scoped_unlock unlock(mLock);
- mPolicy->notifyWindowUnresponsive(token, reason);
+ mPolicy->notifyWindowUnresponsive(token, pid, reason);
};
postCommandLocked(std::move(command));
}
-void InputDispatcher::sendMonitorResponsiveCommandLocked(int32_t pid) {
- auto command = [this, pid]() REQUIRES(mLock) {
+void InputDispatcher::sendWindowResponsiveCommandLocked(const sp<IBinder>& token,
+ std::optional<int32_t> pid) {
+ auto command = [this, token, pid]() REQUIRES(mLock) {
scoped_unlock unlock(mLock);
- mPolicy->notifyMonitorResponsive(pid);
- };
- postCommandLocked(std::move(command));
-}
-
-void InputDispatcher::sendWindowResponsiveCommandLocked(const sp<IBinder>& connectionToken) {
- auto command = [this, connectionToken]() REQUIRES(mLock) {
- scoped_unlock unlock(mLock);
- mPolicy->notifyWindowResponsive(connectionToken);
+ mPolicy->notifyWindowResponsive(token, pid);
};
postCommandLocked(std::move(command));
}
@@ -5857,22 +5833,21 @@
void InputDispatcher::processConnectionUnresponsiveLocked(const Connection& connection,
std::string reason) {
const sp<IBinder>& connectionToken = connection.inputChannel->getConnectionToken();
+ std::optional<int32_t> pid;
if (connection.monitor) {
ALOGW("Monitor %s is unresponsive: %s", connection.inputChannel->getName().c_str(),
reason.c_str());
- std::optional<int32_t> pid = findMonitorPidByTokenLocked(connectionToken);
- if (!pid.has_value()) {
- ALOGE("Could not find unresponsive monitor for connection %s",
- connection.inputChannel->getName().c_str());
- return;
+ pid = findMonitorPidByTokenLocked(connectionToken);
+ } else {
+ // The connection is a window
+ ALOGW("Window %s is unresponsive: %s", connection.inputChannel->getName().c_str(),
+ reason.c_str());
+ const sp<WindowInfoHandle> handle = getWindowHandleLocked(connectionToken);
+ if (handle != nullptr) {
+ pid = handle->getInfo()->ownerPid;
}
- sendMonitorUnresponsiveCommandLocked(pid.value(), std::move(reason));
- return;
}
- // If not a monitor, must be a window
- ALOGW("Window %s is unresponsive: %s", connection.inputChannel->getName().c_str(),
- reason.c_str());
- sendWindowUnresponsiveCommandLocked(connectionToken, std::move(reason));
+ sendWindowUnresponsiveCommandLocked(connectionToken, pid, std::move(reason));
}
/**
@@ -5880,18 +5855,17 @@
*/
void InputDispatcher::processConnectionResponsiveLocked(const Connection& connection) {
const sp<IBinder>& connectionToken = connection.inputChannel->getConnectionToken();
+ std::optional<int32_t> pid;
if (connection.monitor) {
- std::optional<int32_t> pid = findMonitorPidByTokenLocked(connectionToken);
- if (!pid.has_value()) {
- ALOGE("Could not find responsive monitor for connection %s",
- connection.inputChannel->getName().c_str());
- return;
+ pid = findMonitorPidByTokenLocked(connectionToken);
+ } else {
+ // The connection is a window
+ const sp<WindowInfoHandle> handle = getWindowHandleLocked(connectionToken);
+ if (handle != nullptr) {
+ pid = handle->getInfo()->ownerPid;
}
- sendMonitorResponsiveCommandLocked(pid.value());
- return;
}
- // If not a monitor, must be a window
- sendWindowResponsiveCommandLocked(connectionToken);
+ sendWindowResponsiveCommandLocked(connectionToken, pid);
}
bool InputDispatcher::afterKeyEventLockedInterruptable(const sp<Connection>& connection,
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index e162c78..d3e171a 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -503,11 +503,11 @@
*/
void processConnectionResponsiveLocked(const Connection& connection) REQUIRES(mLock);
- void sendMonitorUnresponsiveCommandLocked(int32_t pid, std::string reason) REQUIRES(mLock);
- void sendWindowUnresponsiveCommandLocked(const sp<IBinder>& connectionToken, std::string reason)
+ void sendWindowUnresponsiveCommandLocked(const sp<IBinder>& connectionToken,
+ std::optional<int32_t> pid, std::string reason)
REQUIRES(mLock);
- void sendMonitorResponsiveCommandLocked(int32_t pid) REQUIRES(mLock);
- void sendWindowResponsiveCommandLocked(const sp<IBinder>& connectionToken) REQUIRES(mLock);
+ void sendWindowResponsiveCommandLocked(const sp<IBinder>& connectionToken,
+ std::optional<int32_t> pid) REQUIRES(mLock);
// Optimization: AnrTracker is used to quickly find which connection is due for a timeout next.
// AnrTracker must be kept in-sync with all responsive connection.waitQueues.
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
index 3c1e637..de0b6da 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
@@ -51,30 +51,19 @@
const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) = 0;
/* Notifies the system that a window just became unresponsive. This indicates that ANR
- * should be raised for this window. The window is identified via token.
- * The string reason contains information about the input event that we haven't received
- * a response for.
+ * should be raised for this window. The window can be identified via its input token and the
+ * pid of the owner. The string reason contains information about the input event that we
+ * haven't received a response for.
*/
- virtual void notifyWindowUnresponsive(const sp<IBinder>& token, const std::string& reason) = 0;
- /* Notifies the system that a monitor just became unresponsive. This indicates that ANR
- * should be raised for this monitor. The monitor is identified via its pid.
- * The string reason contains information about the input event that we haven't received
- * a response for.
- */
- virtual void notifyMonitorUnresponsive(int32_t pid, const std::string& reason) = 0;
+ virtual void notifyWindowUnresponsive(const sp<IBinder>& token, std::optional<int32_t> pid,
+ const std::string& reason) = 0;
/* Notifies the system that a window just became responsive. This is only called after the
* window was first marked "unresponsive". This indicates that ANR dialog (if any) should
* no longer should be shown to the user. The window is eligible to cause a new ANR in the
* future.
*/
- virtual void notifyWindowResponsive(const sp<IBinder>& token) = 0;
- /* Notifies the system that a monitor just became responsive. This is only called after the
- * monitor was first marked "unresponsive". This indicates that ANR dialog (if any) should
- * no longer should be shown to the user. The monitor is eligible to cause a new ANR in the
- * future.
- */
- virtual void notifyMonitorResponsive(int32_t pid) = 0;
+ virtual void notifyWindowResponsive(const sp<IBinder>& token, std::optional<int32_t> pid) = 0;
/* Notifies the system that an input channel is unrecoverably broken. */
virtual void notifyInputChannelBroken(const sp<IBinder>& token) = 0;
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index ae8358a..b3f51ee 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -88,6 +88,8 @@
class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
InputDispatcherConfiguration mConfig;
+ using AnrResult = std::pair<sp<IBinder>, int32_t /*pid*/>;
+
protected:
virtual ~FakeInputDispatcherPolicy() {}
@@ -161,122 +163,71 @@
void assertNotifyNoFocusedWindowAnrWasCalled(
std::chrono::nanoseconds timeout,
const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
+ std::unique_lock lock(mLock);
+ android::base::ScopedLockAssertion assumeLocked(mLock);
std::shared_ptr<InputApplicationHandle> application;
- { // acquire lock
- std::unique_lock lock(mLock);
- android::base::ScopedLockAssertion assumeLocked(mLock);
- ASSERT_NO_FATAL_FAILURE(
- application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
- } // release lock
+ ASSERT_NO_FATAL_FAILURE(
+ application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
ASSERT_EQ(expectedApplication, application);
}
void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
- const sp<IBinder>& expectedConnectionToken) {
- sp<IBinder> connectionToken = getUnresponsiveWindowToken(timeout);
- ASSERT_EQ(expectedConnectionToken, connectionToken);
+ const sp<WindowInfoHandle>& window) {
+ LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
+ assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
+ window->getInfo()->ownerPid);
}
- void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedConnectionToken) {
- sp<IBinder> connectionToken = getResponsiveWindowToken();
- ASSERT_EQ(expectedConnectionToken, connectionToken);
+ void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
+ const sp<IBinder>& expectedToken,
+ int32_t expectedPid) {
+ std::unique_lock lock(mLock);
+ android::base::ScopedLockAssertion assumeLocked(mLock);
+ AnrResult result;
+ ASSERT_NO_FATAL_FAILURE(result =
+ getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
+ const auto& [token, pid] = result;
+ ASSERT_EQ(expectedToken, token);
+ ASSERT_EQ(expectedPid, pid);
}
- void assertNotifyMonitorUnresponsiveWasCalled(std::chrono::nanoseconds timeout) {
- int32_t pid = getUnresponsiveMonitorPid(timeout);
- ASSERT_EQ(MONITOR_PID, pid);
- }
-
- void assertNotifyMonitorResponsiveWasCalled() {
- int32_t pid = getResponsiveMonitorPid();
- ASSERT_EQ(MONITOR_PID, pid);
- }
-
+ /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
std::unique_lock lock(mLock);
android::base::ScopedLockAssertion assumeLocked(mLock);
- return getAnrTokenLockedInterruptible(timeout, mAnrWindowTokens, lock);
+ AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
+ const auto& [token, _] = result;
+ return token;
}
+ void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
+ int32_t expectedPid) {
+ std::unique_lock lock(mLock);
+ android::base::ScopedLockAssertion assumeLocked(mLock);
+ AnrResult result;
+ ASSERT_NO_FATAL_FAILURE(
+ result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
+ const auto& [token, pid] = result;
+ ASSERT_EQ(expectedToken, token);
+ ASSERT_EQ(expectedPid, pid);
+ }
+
+ /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
sp<IBinder> getResponsiveWindowToken() {
std::unique_lock lock(mLock);
android::base::ScopedLockAssertion assumeLocked(mLock);
- return getAnrTokenLockedInterruptible(0s, mResponsiveWindowTokens, lock);
- }
-
- int32_t getUnresponsiveMonitorPid(std::chrono::nanoseconds timeout) {
- std::unique_lock lock(mLock);
- android::base::ScopedLockAssertion assumeLocked(mLock);
- return getAnrTokenLockedInterruptible(timeout, mAnrMonitorPids, lock);
- }
-
- int32_t getResponsiveMonitorPid() {
- std::unique_lock lock(mLock);
- android::base::ScopedLockAssertion assumeLocked(mLock);
- return getAnrTokenLockedInterruptible(0s, mResponsiveMonitorPids, lock);
- }
-
- // All three ANR-related callbacks behave the same way, so we use this generic function to wait
- // for a specific container to become non-empty. When the container is non-empty, return the
- // first entry from the container and erase it.
- template <class T>
- T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
- std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
- // If there is an ANR, Dispatcher won't be idle because there are still events
- // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
- // before checking if ANR was called.
- // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
- // to provide it some time to act. 100ms seems reasonable.
- std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
- const std::chrono::time_point start = std::chrono::steady_clock::now();
- std::optional<T> token =
- getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
- if (!token.has_value()) {
- ADD_FAILURE() << "Did not receive the ANR callback";
- return {};
- }
-
- const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
- // Ensure that the ANR didn't get raised too early. We can't be too strict here because
- // the dispatcher started counting before this function was called
- if (std::chrono::abs(timeout - waited) > 100ms) {
- ADD_FAILURE() << "ANR was raised too early or too late. Expected "
- << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
- << "ms, but waited "
- << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
- << "ms instead";
- }
- return *token;
- }
-
- template <class T>
- std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
- std::queue<T>& storage,
- std::unique_lock<std::mutex>& lock,
- std::condition_variable& condition)
- REQUIRES(mLock) {
- condition.wait_for(lock, timeout,
- [&storage]() REQUIRES(mLock) { return !storage.empty(); });
- if (storage.empty()) {
- ADD_FAILURE() << "Did not receive the expected callback";
- return std::nullopt;
- }
- T item = storage.front();
- storage.pop();
- return std::make_optional(item);
+ AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
+ const auto& [token, _] = result;
+ return token;
}
void assertNotifyAnrWasNotCalled() {
std::scoped_lock lock(mLock);
ASSERT_TRUE(mAnrApplications.empty());
- ASSERT_TRUE(mAnrWindowTokens.empty());
- ASSERT_TRUE(mAnrMonitorPids.empty());
- ASSERT_TRUE(mResponsiveWindowTokens.empty())
+ ASSERT_TRUE(mAnrWindows.empty());
+ ASSERT_TRUE(mResponsiveWindows.empty())
<< "ANR was not called, but please also consume the 'connection is responsive' "
"signal";
- ASSERT_TRUE(mResponsiveMonitorPids.empty())
- << "Monitor ANR was not called, but please also consume the 'monitor is responsive'"
- " signal";
}
void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
@@ -344,10 +295,8 @@
// ANR handling
std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
- std::queue<sp<IBinder>> mAnrWindowTokens GUARDED_BY(mLock);
- std::queue<sp<IBinder>> mResponsiveWindowTokens GUARDED_BY(mLock);
- std::queue<int32_t> mAnrMonitorPids GUARDED_BY(mLock);
- std::queue<int32_t> mResponsiveMonitorPids GUARDED_BY(mLock);
+ std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
+ std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
std::condition_variable mNotifyAnr;
std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
std::condition_variable mNotifyInputChannelBroken;
@@ -355,32 +304,74 @@
sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
+ // All three ANR-related callbacks behave the same way, so we use this generic function to wait
+ // for a specific container to become non-empty. When the container is non-empty, return the
+ // first entry from the container and erase it.
+ template <class T>
+ T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
+ std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
+ // If there is an ANR, Dispatcher won't be idle because there are still events
+ // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
+ // before checking if ANR was called.
+ // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
+ // to provide it some time to act. 100ms seems reasonable.
+ std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
+ const std::chrono::time_point start = std::chrono::steady_clock::now();
+ std::optional<T> token =
+ getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
+ if (!token.has_value()) {
+ ADD_FAILURE() << "Did not receive the ANR callback";
+ return {};
+ }
+
+ const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
+ // Ensure that the ANR didn't get raised too early. We can't be too strict here because
+ // the dispatcher started counting before this function was called
+ if (std::chrono::abs(timeout - waited) > 100ms) {
+ ADD_FAILURE() << "ANR was raised too early or too late. Expected "
+ << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
+ << "ms, but waited "
+ << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
+ << "ms instead";
+ }
+ return *token;
+ }
+
+ template <class T>
+ std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
+ std::queue<T>& storage,
+ std::unique_lock<std::mutex>& lock,
+ std::condition_variable& condition)
+ REQUIRES(mLock) {
+ condition.wait_for(lock, timeout,
+ [&storage]() REQUIRES(mLock) { return !storage.empty(); });
+ if (storage.empty()) {
+ ADD_FAILURE() << "Did not receive the expected callback";
+ return std::nullopt;
+ }
+ T item = storage.front();
+ storage.pop();
+ return std::make_optional(item);
+ }
+
void notifyConfigurationChanged(nsecs_t when) override {
std::scoped_lock lock(mLock);
mConfigurationChangedTime = when;
}
- void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, const std::string&) override {
+ void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<int32_t> pid,
+ const std::string&) override {
std::scoped_lock lock(mLock);
- mAnrWindowTokens.push(connectionToken);
+ ASSERT_TRUE(pid.has_value());
+ mAnrWindows.push({connectionToken, *pid});
mNotifyAnr.notify_all();
}
- void notifyMonitorUnresponsive(int32_t pid, const std::string&) override {
+ void notifyWindowResponsive(const sp<IBinder>& connectionToken,
+ std::optional<int32_t> pid) override {
std::scoped_lock lock(mLock);
- mAnrMonitorPids.push(pid);
- mNotifyAnr.notify_all();
- }
-
- void notifyWindowResponsive(const sp<IBinder>& connectionToken) override {
- std::scoped_lock lock(mLock);
- mResponsiveWindowTokens.push(connectionToken);
- mNotifyAnr.notify_all();
- }
-
- void notifyMonitorResponsive(int32_t pid) override {
- std::scoped_lock lock(mLock);
- mResponsiveMonitorPids.push(pid);
+ ASSERT_TRUE(pid.has_value());
+ mResponsiveWindows.push({connectionToken, *pid});
mNotifyAnr.notify_all();
}
@@ -1245,6 +1236,8 @@
mInfo.ownerUid = ownerUid;
}
+ int32_t getPid() const { return mInfo.ownerPid; }
+
void destroyReceiver() { mInputReceiver = nullptr; }
int getChannelFd() { return mInputReceiver->getChannelFd(); }
@@ -4364,13 +4357,13 @@
std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
ASSERT_TRUE(sequenceNum);
const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
- mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
+ mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
mWindow->finishEvent(*sequenceNum);
mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
ADISPLAY_ID_DEFAULT, 0 /*flags*/);
ASSERT_TRUE(mDispatcher->waitForIdle());
- mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
+ mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
}
// Send a key to the app and have the app not respond right away.
@@ -4380,7 +4373,7 @@
std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
ASSERT_TRUE(sequenceNum);
const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
- mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
+ mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
ASSERT_TRUE(mDispatcher->waitForIdle());
}
@@ -4485,7 +4478,7 @@
// We have now sent down and up. Let's consume first event and then ANR on the second.
mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
- mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
+ mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
}
// A spy window can receive an ANR
@@ -4500,13 +4493,13 @@
std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
ASSERT_TRUE(sequenceNum);
const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
- mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy->getToken());
+ mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
spy->finishEvent(*sequenceNum);
spy->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
0 /*flags*/);
ASSERT_TRUE(mDispatcher->waitForIdle());
- mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken());
+ mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
}
// If an app is not responding to a key event, spy windows should continue to receive
@@ -4521,7 +4514,7 @@
// Stuck on the ACTION_UP
const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
- mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
+ mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
// New tap will go to the spy window, but not to the window
tapOnWindow();
@@ -4530,7 +4523,7 @@
mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
mDispatcher->waitForIdle();
- mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
+ mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
mWindow->assertNoEvents();
spy->assertNoEvents();
}
@@ -4547,7 +4540,7 @@
mWindow->consumeMotionDown();
// Stuck on the ACTION_UP
const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
- mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
+ mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
// New tap will go to the spy window, but not to the window
tapOnWindow();
@@ -4556,7 +4549,7 @@
mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
mDispatcher->waitForIdle();
- mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
+ mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
mWindow->assertNoEvents();
spy->assertNoEvents();
}
@@ -4574,13 +4567,13 @@
const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
ASSERT_TRUE(consumeSeq);
- mFakePolicy->assertNotifyMonitorUnresponsiveWasCalled(30ms);
+ mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
monitor.finishEvent(*consumeSeq);
monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
ASSERT_TRUE(mDispatcher->waitForIdle());
- mFakePolicy->assertNotifyMonitorResponsiveWasCalled();
+ mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
}
// If a window is unresponsive, then you get anr. if the window later catches up and starts to
@@ -4595,19 +4588,19 @@
mWindow->consumeMotionDown();
// Block on ACTION_UP
const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
- mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
+ mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
mWindow->consumeMotionUp(); // Now the connection should be healthy again
mDispatcher->waitForIdle();
- mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
+ mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
mWindow->assertNoEvents();
tapOnWindow();
mWindow->consumeMotionDown();
- mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
+ mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
mWindow->consumeMotionUp();
mDispatcher->waitForIdle();
- mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
+ mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
mFakePolicy->assertNotifyAnrWasNotCalled();
mWindow->assertNoEvents();
}
@@ -4620,7 +4613,7 @@
WINDOW_LOCATION));
const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
- mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow->getToken());
+ mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
std::this_thread::sleep_for(windowTimeout);
// 'notifyConnectionUnresponsive' should only be called once per connection
mFakePolicy->assertNotifyAnrWasNotCalled();
@@ -4630,7 +4623,7 @@
ADISPLAY_ID_DEFAULT, 0 /*flags*/);
mWindow->assertNoEvents();
mDispatcher->waitForIdle();
- mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
+ mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
mFakePolicy->assertNotifyAnrWasNotCalled();
}
@@ -4792,7 +4785,7 @@
const std::chrono::duration timeout =
mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
- mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
+ mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
// Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
// sequence to make it consistent
mFocusedWindow->consumeMotionCancel();
@@ -4803,7 +4796,8 @@
mFocusedWindow->assertNoEvents();
mUnfocusedWindow->assertNoEvents();
ASSERT_TRUE(mDispatcher->waitForIdle());
- mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
+ mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
+ mFocusedWindow->getPid());
mFakePolicy->assertNotifyAnrWasNotCalled();
}
@@ -4817,8 +4811,9 @@
tapOnFocusedWindow();
// we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
- sp<IBinder> anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms);
- sp<IBinder> anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms);
+ sp<IBinder> anrConnectionToken1, anrConnectionToken2;
+ ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
+ ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
// We don't know which window will ANR first. But both of them should happen eventually.
ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
@@ -4833,8 +4828,9 @@
mFocusedWindow->consumeMotionUp();
mUnfocusedWindow->consumeMotionOutside();
- sp<IBinder> responsiveToken1 = mFakePolicy->getResponsiveWindowToken();
- sp<IBinder> responsiveToken2 = mFakePolicy->getResponsiveWindowToken();
+ sp<IBinder> responsiveToken1, responsiveToken2;
+ ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
+ ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
// Both applications should be marked as responsive, in any order
ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
@@ -4858,7 +4854,7 @@
ASSERT_TRUE(upEventSequenceNum);
const std::chrono::duration timeout =
mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
- mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
+ mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
// Tap once again
// We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
@@ -4879,7 +4875,8 @@
// The second tap did not go to the focused window
mFocusedWindow->assertNoEvents();
// Since all events are finished, connection should be deemed healthy again
- mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
+ mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
+ mFocusedWindow->getPid());
mFakePolicy->assertNotifyAnrWasNotCalled();
}
@@ -4991,7 +4988,7 @@
const std::chrono::duration timeout =
mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
- mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
+ mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
mUnfocusedWindow->consumeMotionDown();
mFocusedWindow->consumeMotionDown();
@@ -5010,7 +5007,8 @@
ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
}
ASSERT_TRUE(mDispatcher->waitForIdle());
- mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
+ mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
+ mFocusedWindow->getPid());
mUnfocusedWindow->assertNoEvents();
mFocusedWindow->assertNoEvents();
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 000a2cb..f6e8ecc 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -124,10 +124,6 @@
},
whole_program_vtables: true, // Requires ThinLTO
afdo: true,
- // TODO(b/131771163): Fix broken fuzzer support with LTO.
- sanitize: {
- fuzzer: false,
- },
}
cc_library_headers {
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Display.h
index 47aacc9..6a3fcb7 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Display.h
@@ -57,7 +57,7 @@
virtual void createClientCompositionCache(uint32_t cacheSize) = 0;
// Returns the boot display mode preferred by HWC.
- virtual int32_t getPreferredBootModeId() const = 0;
+ virtual int32_t getPreferredBootHwcConfigId() const = 0;
protected:
~Display() = default;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
index 47f07b7..3b8b06f 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
@@ -66,7 +66,7 @@
bool isSecure() const override;
bool isVirtual() const override;
void disconnect() override;
- int32_t getPreferredBootModeId() const override;
+ int32_t getPreferredBootHwcConfigId() const override;
void createDisplayColorProfile(
const compositionengine::DisplayColorProfileCreationArgs&) override;
void createRenderSurface(const compositionengine::RenderSurfaceCreationArgs&) override;
@@ -91,7 +91,7 @@
DisplayId mId;
bool mIsDisconnected = false;
Hwc2::PowerAdvisor* mPowerAdvisor = nullptr;
- int32_t mPreferredBootDisplayModeId = -1;
+ int32_t mPreferredBootHwcConfigId = -1;
};
// This template factory function standardizes the implementation details of the
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h
index 1649843..72e6f3b 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h
@@ -34,7 +34,7 @@
MOCK_CONST_METHOD0(getId, DisplayId());
MOCK_CONST_METHOD0(isSecure, bool());
MOCK_CONST_METHOD0(isVirtual, bool());
- MOCK_CONST_METHOD0(getPreferredBootModeId, int32_t());
+ MOCK_CONST_METHOD0(getPreferredBootHwcConfigId, int32_t());
MOCK_METHOD0(disconnect, void());
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index ecf5ecf..09648c3 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -66,7 +66,7 @@
std::optional<hal::HWConfigId> preferredBootModeId =
getCompositionEngine().getHwComposer().getPreferredBootDisplayMode(*physicalId);
if (preferredBootModeId.has_value()) {
- mPreferredBootDisplayModeId = static_cast<int32_t>(preferredBootModeId.value());
+ mPreferredBootHwcConfigId = static_cast<int32_t>(preferredBootModeId.value());
}
}
@@ -90,8 +90,8 @@
return mId;
}
-int32_t Display::getPreferredBootModeId() const {
- return mPreferredBootDisplayModeId;
+int32_t Display::getPreferredBootHwcConfigId() const {
+ return mPreferredBootHwcConfigId;
}
void Display::disconnect() {
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 87119ee..610d86f 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -236,6 +236,15 @@
return nullptr;
}
+DisplayModePtr DisplayDevice::getModefromHwcId(uint32_t hwcId) const {
+ const auto it = std::find_if(mSupportedModes.begin(), mSupportedModes.end(),
+ [&](DisplayModePtr mode) { return mode->getHwcId() == hwcId; });
+ if (it != mSupportedModes.end()) {
+ return *it;
+ }
+ return nullptr;
+}
+
nsecs_t DisplayDevice::getVsyncPeriodFromHWC() const {
const auto physicalId = getPhysicalId();
if (!mHwComposer.isConnected(physicalId)) {
@@ -461,7 +470,13 @@
}
ui::DisplayModeId DisplayDevice::getPreferredBootModeId() const {
- return mCompositionDisplay->getPreferredBootModeId();
+ const auto preferredBootHwcModeId = mCompositionDisplay->getPreferredBootHwcConfigId();
+ const auto mode = getModefromHwcId(preferredBootHwcModeId);
+ if (mode == nullptr) {
+ ALOGE("%s: invalid display mode (%d)", __FUNCTION__, preferredBootHwcModeId);
+ return BAD_VALUE;
+ }
+ return mode->getId().value();
}
void DisplayDevice::enableRefreshRateOverlay(bool enable, bool showSpinnner) {
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index bf6b31a..690f240 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -232,6 +232,9 @@
// set-top boxes after a hotplug reconnect.
DisplayModePtr getMode(DisplayModeId) const;
+ // Returns nullptr if the given mode ID is not supported.
+ DisplayModePtr getModefromHwcId(uint32_t) const;
+
// Returns the refresh rate configs for this display.
scheduler::RefreshRateConfigs& refreshRateConfigs() const { return *mRefreshRateConfigs; }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 688541f..416725b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1443,8 +1443,15 @@
status_t SurfaceFlinger::setBootDisplayMode(const sp<IBinder>& displayToken, ui::DisplayModeId id) {
auto future = mScheduler->schedule([=]() MAIN_THREAD -> status_t {
- if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
- return getHwComposer().setBootDisplayMode(*displayId, id);
+ if (const auto displayDevice = getDisplayDeviceLocked(displayToken)) {
+ const auto mode = displayDevice->getMode(DisplayModeId{id});
+ if (mode == nullptr) {
+ ALOGE("%s: invalid display mode (%d)", __FUNCTION__, id);
+ return BAD_VALUE;
+ }
+
+ return getHwComposer().setBootDisplayMode(displayDevice->getPhysicalId(),
+ mode->getHwcId());
} else {
ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
return BAD_VALUE;
@@ -3950,24 +3957,6 @@
void SurfaceFlinger::queueTransaction(TransactionState& state) {
Mutex::Autolock _l(mQueueLock);
- // If its TransactionQueue already has a pending TransactionState or if it is pending
- auto itr = mPendingTransactionQueues.find(state.applyToken);
- // if this is an animation frame, wait until prior animation frame has
- // been applied by SF
- if (state.flags & eAnimation) {
- while (itr != mPendingTransactionQueues.end()) {
- status_t err =
- mTransactionQueueCV.waitRelative(mQueueLock, mAnimationTransactionTimeout);
- if (CC_UNLIKELY(err != NO_ERROR)) {
- ALOGW_IF(err == TIMED_OUT,
- "setTransactionState timed out "
- "waiting for animation frame to apply");
- break;
- }
- itr = mPendingTransactionQueues.find(state.applyToken);
- }
- }
-
// Generate a CountDownLatch pending state if this is a synchronous transaction.
if ((state.flags & eSynchronous) || state.inputWindowCommands.syncInputWindows) {
state.transactionCommittedSignal = std::make_shared<CountDownLatch>(
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index 46c8404..ded7531 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -226,7 +226,7 @@
// if this is an animation, this thread should be blocked for 5s
// in setTransactionState waiting for transactionA to flush. Otherwise,
// the transaction should be placed on the pending queue
- if (flags & (ISurfaceComposer::eAnimation | ISurfaceComposer::eSynchronous) ||
+ if (flags & (ISurfaceComposer::eSynchronous) ||
syncInputWindows) {
EXPECT_GE(systemTime(),
applicationSentTime + mFlinger.getAnimationTransactionTimeout());
@@ -288,10 +288,6 @@
NotPlacedOnTransactionQueue(ISurfaceComposer::eSynchronous, /*syncInputWindows*/ false);
}
-TEST_F(TransactionApplicationTest, NotPlacedOnTransactionQueue_Animation) {
- NotPlacedOnTransactionQueue(ISurfaceComposer::eAnimation, /*syncInputWindows*/ false);
-}
-
TEST_F(TransactionApplicationTest, NotPlacedOnTransactionQueue_SyncInputWindows) {
NotPlacedOnTransactionQueue(/*flags*/ 0, /*syncInputWindows*/ true);
}
@@ -300,10 +296,6 @@
PlaceOnTransactionQueue(ISurfaceComposer::eSynchronous, /*syncInputWindows*/ false);
}
-TEST_F(TransactionApplicationTest, PlaceOnTransactionQueue_Animation) {
- PlaceOnTransactionQueue(ISurfaceComposer::eAnimation, /*syncInputWindows*/ false);
-}
-
TEST_F(TransactionApplicationTest, PlaceOnTransactionQueue_SyncInputWindows) {
PlaceOnTransactionQueue(/*flags*/ 0, /*syncInputWindows*/ true);
}
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 9225062..60c0cb5 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -632,8 +632,10 @@
switch (ext_bit) {
case ProcHook::KHR_android_surface:
case ProcHook::KHR_surface:
+ case ProcHook::KHR_surface_protected_capabilities:
case ProcHook::EXT_swapchain_colorspace:
case ProcHook::KHR_get_surface_capabilities2:
+ case ProcHook::GOOGLE_surfaceless_query:
hook_extensions_.set(ext_bit);
// return now as these extensions do not require HAL support
return;
@@ -710,8 +712,10 @@
case ProcHook::KHR_external_fence_capabilities:
case ProcHook::KHR_get_surface_capabilities2:
case ProcHook::KHR_surface:
+ case ProcHook::KHR_surface_protected_capabilities:
case ProcHook::EXT_debug_report:
case ProcHook::EXT_swapchain_colorspace:
+ case ProcHook::GOOGLE_surfaceless_query:
case ProcHook::ANDROID_native_buffer:
case ProcHook::EXTENSION_CORE_1_0:
case ProcHook::EXTENSION_CORE_1_1:
@@ -923,6 +927,9 @@
loader_extensions.push_back({
VK_KHR_SURFACE_EXTENSION_NAME,
VK_KHR_SURFACE_SPEC_VERSION});
+ loader_extensions.push_back(
+ {VK_KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME,
+ VK_KHR_SURFACE_PROTECTED_CAPABILITIES_SPEC_VERSION});
loader_extensions.push_back({
VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
VK_KHR_ANDROID_SURFACE_SPEC_VERSION});
@@ -932,6 +939,8 @@
loader_extensions.push_back({
VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION});
+ loader_extensions.push_back({VK_GOOGLE_SURFACELESS_QUERY_EXTENSION_NAME,
+ VK_GOOGLE_SURFACELESS_QUERY_SPEC_VERSION});
static const VkExtensionProperties loader_debug_report_extension = {
VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION,
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index 5f37a50..b436db1 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -565,11 +565,13 @@
if (strcmp(name, "VK_EXT_hdr_metadata") == 0) return ProcHook::EXT_hdr_metadata;
if (strcmp(name, "VK_EXT_swapchain_colorspace") == 0) return ProcHook::EXT_swapchain_colorspace;
if (strcmp(name, "VK_GOOGLE_display_timing") == 0) return ProcHook::GOOGLE_display_timing;
+ if (strcmp(name, "VK_GOOGLE_surfaceless_query") == 0) return ProcHook::GOOGLE_surfaceless_query;
if (strcmp(name, "VK_KHR_android_surface") == 0) return ProcHook::KHR_android_surface;
if (strcmp(name, "VK_KHR_get_surface_capabilities2") == 0) return ProcHook::KHR_get_surface_capabilities2;
if (strcmp(name, "VK_KHR_incremental_present") == 0) return ProcHook::KHR_incremental_present;
if (strcmp(name, "VK_KHR_shared_presentable_image") == 0) return ProcHook::KHR_shared_presentable_image;
if (strcmp(name, "VK_KHR_surface") == 0) return ProcHook::KHR_surface;
+ if (strcmp(name, "VK_KHR_surface_protected_capabilities") == 0) return ProcHook::KHR_surface_protected_capabilities;
if (strcmp(name, "VK_KHR_swapchain") == 0) return ProcHook::KHR_swapchain;
if (strcmp(name, "VK_ANDROID_external_memory_android_hardware_buffer") == 0) return ProcHook::ANDROID_external_memory_android_hardware_buffer;
if (strcmp(name, "VK_KHR_bind_memory2") == 0) return ProcHook::KHR_bind_memory2;
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index 819f6b2..079f9cc 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -41,11 +41,13 @@
EXT_hdr_metadata,
EXT_swapchain_colorspace,
GOOGLE_display_timing,
+ GOOGLE_surfaceless_query,
KHR_android_surface,
KHR_get_surface_capabilities2,
KHR_incremental_present,
KHR_shared_presentable_image,
KHR_surface,
+ KHR_surface_protected_capabilities,
KHR_swapchain,
ANDROID_external_memory_android_hardware_buffer,
KHR_bind_memory2,
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 4a6b4f1..0be4403 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -619,42 +619,65 @@
VKAPI_ATTR
VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR(
- VkPhysicalDevice /*pdev*/,
+ VkPhysicalDevice pdev,
VkSurfaceKHR surface,
VkSurfaceCapabilitiesKHR* capabilities) {
ATRACE_CALL();
int err;
- ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
-
int width, height;
- err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width);
- if (err != android::OK) {
- ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
- strerror(-err), err);
- return VK_ERROR_SURFACE_LOST_KHR;
- }
- err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height);
- if (err != android::OK) {
- ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
- strerror(-err), err);
- return VK_ERROR_SURFACE_LOST_KHR;
- }
-
int transform_hint;
- err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT, &transform_hint);
- if (err != android::OK) {
- ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)",
- strerror(-err), err);
- return VK_ERROR_SURFACE_LOST_KHR;
- }
-
int max_buffer_count;
- err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &max_buffer_count);
- if (err != android::OK) {
- ALOGE("NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d)",
- strerror(-err), err);
- return VK_ERROR_SURFACE_LOST_KHR;
+ if (surface == VK_NULL_HANDLE) {
+ const InstanceData& instance_data = GetData(pdev);
+ ProcHook::Extension surfaceless = ProcHook::GOOGLE_surfaceless_query;
+ bool surfaceless_enabled =
+ instance_data.hook_extensions.test(surfaceless);
+ if (!surfaceless_enabled) {
+ // It is an error to pass a surface==VK_NULL_HANDLE unless the
+ // VK_GOOGLE_surfaceless_query extension is enabled
+ return VK_ERROR_SURFACE_LOST_KHR;
+ }
+ // Support for VK_GOOGLE_surfaceless_query. The primary purpose of this
+ // extension for this function is for
+ // VkSurfaceProtectedCapabilitiesKHR::supportsProtected. The following
+ // four values cannot be known without a surface. Default values will
+ // be supplied anyway, but cannot be relied upon.
+ width = 1000;
+ height = 1000;
+ transform_hint = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+ max_buffer_count = 10;
+ } else {
+ ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
+
+ err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width);
+ if (err != android::OK) {
+ ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
+ strerror(-err), err);
+ return VK_ERROR_SURFACE_LOST_KHR;
+ }
+ err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height);
+ if (err != android::OK) {
+ ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
+ strerror(-err), err);
+ return VK_ERROR_SURFACE_LOST_KHR;
+ }
+
+ err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT,
+ &transform_hint);
+ if (err != android::OK) {
+ ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)",
+ strerror(-err), err);
+ return VK_ERROR_SURFACE_LOST_KHR;
+ }
+
+ err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT,
+ &max_buffer_count);
+ if (err != android::OK) {
+ ALOGE("NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d)",
+ strerror(-err), err);
+ return VK_ERROR_SURFACE_LOST_KHR;
+ }
}
capabilities->minImageCount = std::min(max_buffer_count, 3);
capabilities->maxImageCount = static_cast<uint32_t>(max_buffer_count);
@@ -695,23 +718,43 @@
const InstanceData& instance_data = GetData(pdev);
bool wide_color_support = false;
- Surface& surface = *SurfaceFromHandle(surface_handle);
- int err = native_window_get_wide_color_support(surface.window.get(),
- &wide_color_support);
- if (err) {
- return VK_ERROR_SURFACE_LOST_KHR;
- }
+ uint64_t consumer_usage = 0;
bool swapchain_ext =
instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
- ALOGV("wide_color_support is: %d", wide_color_support);
+ if (surface_handle == VK_NULL_HANDLE) {
+ ProcHook::Extension surfaceless = ProcHook::GOOGLE_surfaceless_query;
+ bool surfaceless_enabled =
+ instance_data.hook_extensions.test(surfaceless);
+ if (!surfaceless_enabled) {
+ return VK_ERROR_SURFACE_LOST_KHR;
+ }
+ // Support for VK_GOOGLE_surfaceless_query. The EGL loader
+ // unconditionally supports wide color formats, even if they will cause
+ // a SurfaceFlinger fallback. Based on that, wide_color_support will be
+ // set to true in this case.
+ wide_color_support = true;
+
+ // TODO(b/203826952): research proper value; temporarily use the
+ // values seen on Pixel
+ consumer_usage = AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY;
+ } else {
+ Surface& surface = *SurfaceFromHandle(surface_handle);
+ int err = native_window_get_wide_color_support(surface.window.get(),
+ &wide_color_support);
+ if (err) {
+ return VK_ERROR_SURFACE_LOST_KHR;
+ }
+ ALOGV("wide_color_support is: %d", wide_color_support);
+
+ consumer_usage = surface.consumer_usage;
+ }
wide_color_support = wide_color_support && swapchain_ext;
AHardwareBuffer_Desc desc = {};
desc.width = 1;
desc.height = 1;
desc.layers = 1;
- desc.usage = surface.consumer_usage |
- AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
+ desc.usage = consumer_usage | AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
// We must support R8G8B8A8
@@ -731,6 +774,10 @@
VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
}
+ // NOTE: Any new formats that are added must be coordinated across different
+ // Android users. This includes the ANGLE team (a layered implementation of
+ // OpenGL-ES).
+
desc.format = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
if (AHardwareBuffer_isSupported(&desc)) {
all_formats.emplace_back(VkSurfaceFormatKHR{
@@ -770,6 +817,10 @@
VK_COLOR_SPACE_PASS_THROUGH_EXT});
}
+ // NOTE: Any new formats that are added must be coordinated across different
+ // Android users. This includes the ANGLE team (a layered implementation of
+ // OpenGL-ES).
+
VkResult result = VK_SUCCESS;
if (formats) {
uint32_t transfer_count = all_formats.size();
@@ -814,6 +865,12 @@
.supportedUsageFlags;
} break;
+ case VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR: {
+ VkSurfaceProtectedCapabilitiesKHR* protected_caps =
+ reinterpret_cast<VkSurfaceProtectedCapabilitiesKHR*>(caps);
+ protected_caps->supportsProtected = VK_TRUE;
+ } break;
+
default:
// Ignore all other extension structs
break;
@@ -865,31 +922,51 @@
int err;
int query_value;
- ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
-
- err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
- &query_value);
- if (err != android::OK || query_value < 0) {
- ALOGE(
- "NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d) "
- "value=%d",
- strerror(-err), err, query_value);
- return VK_ERROR_SURFACE_LOST_KHR;
- }
- uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
-
- err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &query_value);
- if (err != android::OK || query_value < 0) {
- ALOGE("NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d) value=%d",
- strerror(-err), err, query_value);
- return VK_ERROR_SURFACE_LOST_KHR;
- }
- uint32_t max_buffer_count = static_cast<uint32_t>(query_value);
-
std::vector<VkPresentModeKHR> present_modes;
- if (min_undequeued_buffers + 1 < max_buffer_count)
+ if (surface == VK_NULL_HANDLE) {
+ const InstanceData& instance_data = GetData(pdev);
+ ProcHook::Extension surfaceless = ProcHook::GOOGLE_surfaceless_query;
+ bool surfaceless_enabled =
+ instance_data.hook_extensions.test(surfaceless);
+ if (!surfaceless_enabled) {
+ return VK_ERROR_SURFACE_LOST_KHR;
+ }
+ // Support for VK_GOOGLE_surfaceless_query. The primary purpose of this
+ // extension for this function is for
+ // VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR and
+ // VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR. We technically cannot
+ // know if VK_PRESENT_MODE_SHARED_MAILBOX_KHR is supported without a
+ // surface, and that cannot be relied upon.
present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR);
- present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR);
+ present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR);
+ } else {
+ ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
+
+ err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+ &query_value);
+ if (err != android::OK || query_value < 0) {
+ ALOGE(
+ "NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d) "
+ "value=%d",
+ strerror(-err), err, query_value);
+ return VK_ERROR_SURFACE_LOST_KHR;
+ }
+ uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
+
+ err =
+ window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &query_value);
+ if (err != android::OK || query_value < 0) {
+ ALOGE(
+ "NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d) value=%d",
+ strerror(-err), err, query_value);
+ return VK_ERROR_SURFACE_LOST_KHR;
+ }
+ uint32_t max_buffer_count = static_cast<uint32_t>(query_value);
+
+ if (min_undequeued_buffers + 1 < max_buffer_count)
+ present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR);
+ present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR);
+ }
VkPhysicalDevicePresentationPropertiesANDROID present_properties;
QueryPresentationProperties(pdev, &present_properties);
diff --git a/vulkan/scripts/driver_generator.py b/vulkan/scripts/driver_generator.py
index 6a73023..af56764 100644
--- a/vulkan/scripts/driver_generator.py
+++ b/vulkan/scripts/driver_generator.py
@@ -27,11 +27,13 @@
'VK_EXT_hdr_metadata',
'VK_EXT_swapchain_colorspace',
'VK_GOOGLE_display_timing',
+ 'VK_GOOGLE_surfaceless_query',
'VK_KHR_android_surface',
'VK_KHR_get_surface_capabilities2',
'VK_KHR_incremental_present',
'VK_KHR_shared_presentable_image',
'VK_KHR_surface',
+ 'VK_KHR_surface_protected_capabilities',
'VK_KHR_swapchain',
]