Merge "Test InputDeviceIdentifier::getCanonicalName"
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 49383e5..2efcf11 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -39,6 +39,7 @@
#include <sys/xattr.h>
#include <unistd.h>
+#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/scopeguard.h>
@@ -80,6 +81,8 @@
// An uuid used in unit tests.
static constexpr const char* kTestUuid = "TEST";
+static constexpr const mode_t kRollbackFolderMode = 0700;
+
static constexpr const char* kCpPath = "/system/bin/cp";
static constexpr const char* kXattrDefault = "user.default";
@@ -822,8 +825,8 @@
binder::Status InstalldNativeService::snapshotAppData(
const std::unique_ptr<std::string>& volumeUuid,
- const std::string& packageName, int32_t user, int32_t storageFlags,
- int64_t* _aidl_return) {
+ const std::string& packageName, int32_t user, int32_t snapshotId,
+ int32_t storageFlags, int64_t* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
@@ -840,16 +843,19 @@
bool clear_ce_on_exit = false;
bool clear_de_on_exit = false;
- auto deleter = [&clear_ce_on_exit, &clear_de_on_exit, &volume_uuid, &user, &package_name] {
+ auto deleter = [&clear_ce_on_exit, &clear_de_on_exit, &volume_uuid, &user, &package_name,
+ &snapshotId] {
if (clear_de_on_exit) {
- auto to = create_data_misc_de_rollback_package_path(volume_uuid, user, package_name);
+ auto to = create_data_misc_de_rollback_package_path(volume_uuid, user, snapshotId,
+ package_name);
if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) {
LOG(WARNING) << "Failed to delete app data snapshot: " << to;
}
}
if (clear_ce_on_exit) {
- auto to = create_data_misc_ce_rollback_package_path(volume_uuid, user, package_name);
+ auto to = create_data_misc_ce_rollback_package_path(volume_uuid, user, snapshotId,
+ package_name);
if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) {
LOG(WARNING) << "Failed to delete app data snapshot: " << to;
}
@@ -885,15 +891,21 @@
if (storageFlags & FLAG_STORAGE_DE) {
auto from = create_data_user_de_package_path(volume_uuid, user, package_name);
- auto to = create_data_misc_de_rollback_path(volume_uuid, user);
+ auto to = create_data_misc_de_rollback_path(volume_uuid, user, snapshotId);
+ auto rollback_package_path = create_data_misc_de_rollback_package_path(volume_uuid, user,
+ snapshotId, package_name);
- int rd = delete_dir_contents(to, true /* ignore_if_missing */);
- if (rd != 0) {
- res = error(rd, "Failed clearing existing snapshot " + to);
- return res;
+ int rc = create_dir_if_needed(to.c_str(), kRollbackFolderMode);
+ if (rc != 0) {
+ return error(rc, "Failed to create folder " + to);
}
- int rc = copy_directory_recursive(from.c_str(), to.c_str());
+ rc = delete_dir_contents(rollback_package_path, true /* ignore_if_missing */);
+ if (rc != 0) {
+ return error(rc, "Failed clearing existing snapshot " + rollback_package_path);
+ }
+
+ rc = copy_directory_recursive(from.c_str(), to.c_str());
if (rc != 0) {
res = error(rc, "Failed copying " + from + " to " + to);
clear_de_on_exit = true;
@@ -903,15 +915,21 @@
if (storageFlags & FLAG_STORAGE_CE) {
auto from = create_data_user_ce_package_path(volume_uuid, user, package_name);
- auto to = create_data_misc_ce_rollback_path(volume_uuid, user);
+ auto to = create_data_misc_ce_rollback_path(volume_uuid, user, snapshotId);
+ auto rollback_package_path = create_data_misc_ce_rollback_package_path(volume_uuid, user,
+ snapshotId, package_name);
- int rd = delete_dir_contents(to, true /* ignore_if_missing */);
- if (rd != 0) {
- res = error(rd, "Failed clearing existing snapshot " + to);
- return res;
+ int rc = create_dir_if_needed(to.c_str(), kRollbackFolderMode);
+ if (rc != 0) {
+ return error(rc, "Failed to create folder " + to);
}
- int rc = copy_directory_recursive(from.c_str(), to.c_str());
+ rc = delete_dir_contents(rollback_package_path, true /* ignore_if_missing */);
+ if (rc != 0) {
+ return error(rc, "Failed clearing existing snapshot " + rollback_package_path);
+ }
+
+ rc = copy_directory_recursive(from.c_str(), to.c_str());
if (rc != 0) {
res = error(rc, "Failed copying " + from + " to " + to);
clear_ce_on_exit = true;
@@ -919,7 +937,7 @@
}
if (_aidl_return != nullptr) {
auto ce_snapshot_path = create_data_misc_ce_rollback_package_path(volume_uuid, user,
- package_name);
+ snapshotId, package_name);
rc = get_path_inode(ce_snapshot_path, reinterpret_cast<ino_t*>(_aidl_return));
if (rc != 0) {
res = error(rc, "Failed to get_path_inode for " + ce_snapshot_path);
@@ -934,8 +952,8 @@
binder::Status InstalldNativeService::restoreAppDataSnapshot(
const std::unique_ptr<std::string>& volumeUuid, const std::string& packageName,
- const int32_t appId, const int64_t ceDataInode, const std::string& seInfo,
- const int32_t user, int32_t storageFlags) {
+ const int32_t appId, const std::string& seInfo, const int32_t user,
+ const int32_t snapshotId, int32_t storageFlags) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
@@ -945,9 +963,9 @@
const char* package_name = packageName.c_str();
auto from_ce = create_data_misc_ce_rollback_package_path(volume_uuid,
- user, package_name);
+ user, snapshotId, package_name);
auto from_de = create_data_misc_de_rollback_package_path(volume_uuid,
- user, package_name);
+ user, snapshotId, package_name);
const bool needs_ce_rollback = (storageFlags & FLAG_STORAGE_CE) &&
(access(from_ce.c_str(), F_OK) == 0);
@@ -964,7 +982,11 @@
// app with no data in those cases is arguably better than leaving the app
// with mismatched / stale data.
LOG(INFO) << "Clearing app data for " << packageName << " to restore snapshot.";
- binder::Status res = clearAppData(volumeUuid, packageName, user, storageFlags, ceDataInode);
+ // It's fine to pass 0 as ceDataInode here, because restoreAppDataSnapshot
+ // can only be called when user unlocks the phone, meaning that CE user data
+ // is decrypted.
+ binder::Status res = clearAppData(volumeUuid, packageName, user, storageFlags,
+ 0 /* ceDataInode */);
if (!res.isOk()) {
return res;
}
@@ -1000,7 +1022,8 @@
binder::Status InstalldNativeService::destroyAppDataSnapshot(
const std::unique_ptr<std::string> &volumeUuid, const std::string& packageName,
- const int32_t user, const int64_t ceSnapshotInode, int32_t storageFlags) {
+ const int32_t user, const int64_t ceSnapshotInode, const int32_t snapshotId,
+ int32_t storageFlags) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
@@ -1011,7 +1034,7 @@
if (storageFlags & FLAG_STORAGE_DE) {
auto de_snapshot_path = create_data_misc_de_rollback_package_path(volume_uuid,
- user, package_name);
+ user, snapshotId, package_name);
int res = delete_dir_contents_and_dir(de_snapshot_path, true /* ignore_if_missing */);
if (res != 0) {
@@ -1021,7 +1044,7 @@
if (storageFlags & FLAG_STORAGE_CE) {
auto ce_snapshot_path = create_data_misc_ce_rollback_package_path(volume_uuid,
- user, package_name, ceSnapshotInode);
+ user, snapshotId, package_name, ceSnapshotInode);
int res = delete_dir_contents_and_dir(ce_snapshot_path, true /* ignore_if_missing */);
if (res != 0) {
return error(res, "Failed clearing snapshot " + ce_snapshot_path);
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 578132d..0e91cb2 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -61,14 +61,14 @@
binder::Status fixupAppData(const std::unique_ptr<std::string>& uuid, int32_t flags);
binder::Status snapshotAppData(const std::unique_ptr<std::string>& volumeUuid,
- const std::string& packageName, const int32_t user, int32_t storageFlags,
- int64_t* _aidl_return);
+ const std::string& packageName, const int32_t user, const int32_t snapshotId,
+ int32_t storageFlags, int64_t* _aidl_return);
binder::Status restoreAppDataSnapshot(const std::unique_ptr<std::string>& volumeUuid,
- const std::string& packageName, const int32_t appId, const int64_t ceDataInode,
- const std::string& seInfo, const int32_t user, int32_t storageFlags);
+ const std::string& packageName, const int32_t appId, const std::string& seInfo,
+ const int32_t user, const int32_t snapshotId, int32_t storageFlags);
binder::Status destroyAppDataSnapshot(const std::unique_ptr<std::string> &volumeUuid,
const std::string& packageName, const int32_t user, const int64_t ceSnapshotInode,
- int32_t storageFlags);
+ const int32_t snapshotId, int32_t storageFlags);
binder::Status getAppSize(const std::unique_ptr<std::string>& uuid,
const std::vector<std::string>& packageNames, int32_t userId, int32_t flags,
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index b345210..63c9765 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -106,11 +106,11 @@
@nullable @utf8InCpp String dexMetadata);
long snapshotAppData(@nullable @utf8InCpp String uuid, in @utf8InCpp String packageName,
- int userId, int storageFlags);
+ int userId, int snapshotId, int storageFlags);
void restoreAppDataSnapshot(@nullable @utf8InCpp String uuid, in @utf8InCpp String packageName,
- int appId, long ceDataInode, @utf8InCpp String seInfo, int user, int storageflags);
+ int appId, @utf8InCpp String seInfo, int user, int snapshotId, int storageflags);
void destroyAppDataSnapshot(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
- int userId, long ceSnapshotInode, int storageFlags);
+ int userId, long ceSnapshotInode, int snapshotId, int storageFlags);
const int FLAG_STORAGE_DE = 0x1;
const int FLAG_STORAGE_CE = 0x2;
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
index 48b07c4..a31d510 100644
--- a/cmds/installd/tests/installd_service_test.cpp
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -259,32 +259,59 @@
return false;
}
- return (::mkdir(path.c_str(), mode) != -1);
+ if (::mkdir(path.c_str(), mode) != 0) {
+ PLOG(DEBUG) << "Failed to create folder " << path;
+ return false;
+ }
+ return true;
}
-TEST_F(ServiceTest, CreateAppDataSnapshot) {
- auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
- auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+class AppDataSnapshotTest : public testing::Test {
+private:
+ std::string rollback_ce_base_dir;
+ std::string rollback_de_base_dir;
- ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
+protected:
+ InstalldNativeService* service;
- auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
- auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
+ std::string fake_package_ce_path;
+ std::string fake_package_de_path;
- ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
+ virtual void SetUp() {
+ setenv("ANDROID_LOG_TAGS", "*:v", 1);
+ android::base::InitLogging(nullptr);
- auto deleter = [&rollback_ce_dir, &rollback_de_dir,
- &fake_package_ce_path, &fake_package_de_path]() {
- delete_dir_contents(rollback_ce_dir, true);
- delete_dir_contents(rollback_de_dir, true);
- delete_dir_contents(fake_package_ce_path, true);
- delete_dir_contents(fake_package_de_path, true);
- rmdir(rollback_ce_dir.c_str());
- rmdir(rollback_de_dir.c_str());
- };
- auto scope_guard = android::base::make_scope_guard(deleter);
+ service = new InstalldNativeService();
+ ASSERT_TRUE(mkdirs("/data/local/tmp/user/0", 0700));
+
+ init_globals_from_data_and_root();
+
+ rollback_ce_base_dir = create_data_misc_ce_rollback_base_path("TEST", 0);
+ rollback_de_base_dir = create_data_misc_de_rollback_base_path("TEST", 0);
+
+ fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
+ fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
+
+ ASSERT_TRUE(mkdirs(rollback_ce_base_dir, 0700));
+ ASSERT_TRUE(mkdirs(rollback_de_base_dir, 0700));
+ ASSERT_TRUE(mkdirs(fake_package_ce_path, 0700));
+ ASSERT_TRUE(mkdirs(fake_package_de_path, 0700));
+ }
+
+ virtual void TearDown() {
+ ASSERT_EQ(0, delete_dir_contents_and_dir(rollback_ce_base_dir, true));
+ ASSERT_EQ(0, delete_dir_contents_and_dir(rollback_de_base_dir, true));
+ ASSERT_EQ(0, delete_dir_contents(fake_package_ce_path, true));
+ ASSERT_EQ(0, delete_dir_contents(fake_package_de_path, true));
+
+ delete service;
+ ASSERT_EQ(0, delete_dir_contents_and_dir("/data/local/tmp/user/0", true));
+ }
+};
+
+TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot) {
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 37);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 37);
ASSERT_TRUE(android::base::WriteStringToFile(
"TEST_CONTENT_CE", fake_package_ce_path + "/file1",
@@ -296,7 +323,7 @@
// Request a snapshot of the CE content but not the DE content.
int64_t ce_snapshot_inode;
ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_CE, &ce_snapshot_inode));
+ "com.foo", 0, 37, FLAG_STORAGE_CE, &ce_snapshot_inode));
struct stat buf;
memset(&buf, 0, sizeof(buf));
ASSERT_EQ(0, stat((rollback_ce_dir + "/com.foo").c_str(), &buf));
@@ -318,7 +345,7 @@
// Request a snapshot of the DE content but not the CE content.
ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_DE, &ce_snapshot_inode));
+ "com.foo", 0, 37, FLAG_STORAGE_DE, &ce_snapshot_inode));
// Only DE content snapshot was requested.
ASSERT_EQ(ce_snapshot_inode, 0);
@@ -339,7 +366,7 @@
// Request a snapshot of both the CE as well as the DE content.
ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
+ "com.foo", 0, 37, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
ASSERT_TRUE(android::base::ReadFileToString(
rollback_ce_dir + "/com.foo/file1", &ce_content, false /* follow_symlinks */));
@@ -349,27 +376,73 @@
ASSERT_EQ("TEST_CONTENT_DE_MODIFIED", de_content);
}
-TEST_F(ServiceTest, CreateAppDataSnapshot_AppDataAbsent) {
- auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
- auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot_TwoSnapshotsWithTheSameId) {
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 67);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 67);
- ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
+ auto another_fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.bar");
+ auto another_fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.bar");
- auto deleter = [&rollback_ce_dir, &rollback_de_dir]() {
- delete_dir_contents(rollback_ce_dir, true);
- delete_dir_contents(rollback_de_dir, true);
- rmdir(rollback_ce_dir.c_str());
- rmdir(rollback_de_dir.c_str());
+ // Since this test sets up data for another package, some bookkeeping is required.
+ auto deleter = [&]() {
+ ASSERT_EQ(0, delete_dir_contents_and_dir(another_fake_package_ce_path, true));
+ ASSERT_EQ(0, delete_dir_contents_and_dir(another_fake_package_de_path, true));
};
-
auto scope_guard = android::base::make_scope_guard(deleter);
+ ASSERT_TRUE(mkdirs(another_fake_package_ce_path, 0700));
+ ASSERT_TRUE(mkdirs(another_fake_package_de_path, 0700));
+
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "TEST_CONTENT_CE", fake_package_ce_path + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "TEST_CONTENT_DE", fake_package_de_path + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "ANOTHER_TEST_CONTENT_CE", another_fake_package_ce_path + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "ANOTHER_TEST_CONTENT_DE", another_fake_package_de_path + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+
+ // Request snapshot for the package com.foo.
+ ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
+ "com.foo", 0, 67, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
+ // Now request snapshot with the same id for the package com.bar
+ ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
+ "com.bar", 0, 67, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
+
+ // Check that both snapshots have correct data in them.
+ std::string com_foo_ce_content, com_foo_de_content;
+ std::string com_bar_ce_content, com_bar_de_content;
+ ASSERT_TRUE(android::base::ReadFileToString(
+ rollback_ce_dir + "/com.foo/file1", &com_foo_ce_content, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::ReadFileToString(
+ rollback_de_dir + "/com.foo/file1", &com_foo_de_content, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::ReadFileToString(
+ rollback_ce_dir + "/com.bar/file1", &com_bar_ce_content, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::ReadFileToString(
+ rollback_de_dir + "/com.bar/file1", &com_bar_de_content, false /* follow_symlinks */));
+ ASSERT_EQ("TEST_CONTENT_CE", com_foo_ce_content);
+ ASSERT_EQ("TEST_CONTENT_DE", com_foo_de_content);
+ ASSERT_EQ("ANOTHER_TEST_CONTENT_CE", com_bar_ce_content);
+ ASSERT_EQ("ANOTHER_TEST_CONTENT_DE", com_bar_de_content);
+}
+
+TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot_AppDataAbsent) {
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 73);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 73);
+
+ // Similuating app data absence.
+ ASSERT_EQ(0, delete_dir_contents_and_dir(fake_package_ce_path, true));
+ ASSERT_EQ(0, delete_dir_contents_and_dir(fake_package_de_path, true));
+
int64_t ce_snapshot_inode;
ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_CE, &ce_snapshot_inode));
+ "com.foo", 0, 73, FLAG_STORAGE_CE, &ce_snapshot_inode));
ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_DE, nullptr));
+ "com.foo", 0, 73, FLAG_STORAGE_DE, nullptr));
// No CE content snapshot was performed.
ASSERT_EQ(ce_snapshot_inode, 0);
@@ -380,29 +453,12 @@
ASSERT_EQ(-1, stat((rollback_de_dir + "/com.foo").c_str(), &sb));
}
-TEST_F(ServiceTest, CreateAppDataSnapshot_ClearsExistingSnapshot) {
- auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
- auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot_ClearsExistingSnapshot) {
+ auto rollback_ce_dir = create_data_misc_ce_rollback_package_path("TEST", 0, 13, "com.foo");
+ auto rollback_de_dir = create_data_misc_de_rollback_package_path("TEST", 0, 13, "com.foo");
- ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
-
- auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
- auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
-
- ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
-
- auto deleter = [&rollback_ce_dir, &rollback_de_dir,
- &fake_package_ce_path, &fake_package_de_path]() {
- delete_dir_contents(rollback_ce_dir, true);
- delete_dir_contents(rollback_de_dir, true);
- delete_dir_contents(fake_package_ce_path, true);
- delete_dir_contents(fake_package_de_path, true);
- rmdir(rollback_ce_dir.c_str());
- rmdir(rollback_de_dir.c_str());
- };
- auto scope_guard = android::base::make_scope_guard(deleter);
+ ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
// Simulate presence of an existing snapshot
ASSERT_TRUE(android::base::WriteStringToFile(
@@ -421,62 +477,40 @@
0700, 10000, 20000, false /* follow_symlinks */));
ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
+ "com.foo", 0, 13, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
// Previous snapshot (with data for file1) must be cleared.
struct stat sb;
- ASSERT_EQ(-1, stat((rollback_ce_dir + "/com.foo/file1").c_str(), &sb));
- ASSERT_EQ(-1, stat((rollback_de_dir + "/com.foo/file1").c_str(), &sb));
+ ASSERT_EQ(-1, stat((rollback_ce_dir + "/file1").c_str(), &sb));
+ ASSERT_EQ(-1, stat((rollback_de_dir + "/file1").c_str(), &sb));
+ // New snapshot (with data for file2) must be present.
+ ASSERT_NE(-1, stat((rollback_ce_dir + "/file2").c_str(), &sb));
+ ASSERT_NE(-1, stat((rollback_de_dir + "/file2").c_str(), &sb));
}
-TEST_F(ServiceTest, SnapshotAppData_WrongVolumeUuid) {
- // Setup app data to make sure that fails due to wrong volumeUuid being
+TEST_F(AppDataSnapshotTest, SnapshotAppData_WrongVolumeUuid) {
+ // Setup rollback folders to make sure that fails due to wrong volumeUuid being
// passed, not because of some other reason.
- auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
- auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 17);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 17);
- ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
-
- auto deleter = [&rollback_ce_dir, &rollback_de_dir]() {
- delete_dir_contents(rollback_ce_dir, true);
- delete_dir_contents(rollback_de_dir, true);
- rmdir(rollback_ce_dir.c_str());
- rmdir(rollback_de_dir.c_str());
- };
- auto scope_guard = android::base::make_scope_guard(deleter);
+ ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
EXPECT_BINDER_FAIL(service->snapshotAppData(std::make_unique<std::string>("FOO"),
- "com.foo", 0, FLAG_STORAGE_DE, nullptr));
+ "com.foo", 0, 17, FLAG_STORAGE_DE, nullptr));
}
-TEST_F(ServiceTest, CreateAppDataSnapshot_ClearsCache) {
- auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
- auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
+TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot_ClearsCache) {
auto fake_package_ce_cache_path = fake_package_ce_path + "/cache";
auto fake_package_ce_code_cache_path = fake_package_ce_path + "/code_cache";
auto fake_package_de_cache_path = fake_package_de_path + "/cache";
auto fake_package_de_code_cache_path = fake_package_de_path + "/code_cache";
- auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
- auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
- ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_ce_cache_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_ce_code_cache_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_de_cache_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_de_code_cache_path, 700));
- ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
-
- auto deleter = [&fake_package_ce_path, &fake_package_de_path,
- &rollback_ce_dir, &rollback_de_dir]() {
- delete_dir_contents(fake_package_ce_path, true);
- delete_dir_contents(fake_package_de_path, true);
- delete_dir_contents_and_dir(rollback_ce_dir, true);
- delete_dir_contents_and_dir(rollback_de_dir, true);
- };
- auto scope_guard = android::base::make_scope_guard(deleter);
+ ASSERT_TRUE(mkdirs(fake_package_ce_cache_path, 0700));
+ ASSERT_TRUE(mkdirs(fake_package_ce_code_cache_path, 0700));
+ ASSERT_TRUE(mkdirs(fake_package_de_cache_path, 0700));
+ ASSERT_TRUE(mkdirs(fake_package_de_code_cache_path, 0700));
ASSERT_TRUE(android::base::WriteStringToFile(
"TEST_CONTENT_CE", fake_package_ce_cache_path + "/file1",
@@ -491,7 +525,7 @@
"TEST_CONTENT_DE", fake_package_de_code_cache_path + "/file1",
0700, 10000, 20000, false /* follow_symlinks */));
ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_CE | FLAG_STORAGE_DE, nullptr));
+ "com.foo", 0, 23, FLAG_STORAGE_CE | FLAG_STORAGE_DE, nullptr));
// The snapshot call must clear cache.
struct stat sb;
ASSERT_EQ(-1, stat((fake_package_ce_cache_path + "/file1").c_str(), &sb));
@@ -500,34 +534,17 @@
ASSERT_EQ(-1, stat((fake_package_de_code_cache_path + "/file1").c_str(), &sb));
}
-TEST_F(ServiceTest, RestoreAppDataSnapshot) {
- auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
- auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+TEST_F(AppDataSnapshotTest, RestoreAppDataSnapshot) {
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 239);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 239);
- ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
-
- auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
- auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
-
- ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
-
- auto deleter = [&rollback_ce_dir, &rollback_de_dir,
- &fake_package_ce_path, &fake_package_de_path]() {
- delete_dir_contents(rollback_ce_dir, true);
- delete_dir_contents(rollback_de_dir, true);
- delete_dir_contents(fake_package_ce_path, true);
- delete_dir_contents(fake_package_de_path, true);
- rmdir(rollback_ce_dir.c_str());
- rmdir(rollback_de_dir.c_str());
- };
- auto scope_guard = android::base::make_scope_guard(deleter);
+ ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
// Write contents to the rollback location. We'll write the same files to the
// app data location and make sure the restore has overwritten them.
- ASSERT_TRUE(mkdirs(rollback_ce_dir + "/com.foo/", 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir + "/com.foo/", 700));
+ ASSERT_TRUE(mkdirs(rollback_ce_dir + "/com.foo/", 0700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir + "/com.foo/", 0700));
ASSERT_TRUE(android::base::WriteStringToFile(
"CE_RESTORE_CONTENT", rollback_ce_dir + "/com.foo/file1",
0700, 10000, 20000, false /* follow_symlinks */));
@@ -542,7 +559,7 @@
0700, 10000, 20000, false /* follow_symlinks */));
ASSERT_BINDER_SUCCESS(service->restoreAppDataSnapshot(std::make_unique<std::string>("TEST"),
- "com.foo", 10000, -1, "", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE));
+ "com.foo", 10000, "", 0, 239, FLAG_STORAGE_DE | FLAG_STORAGE_CE));
std::string ce_content, de_content;
ASSERT_TRUE(android::base::ReadFileToString(
@@ -553,29 +570,9 @@
ASSERT_EQ("DE_RESTORE_CONTENT", de_content);
}
-TEST_F(ServiceTest, CreateSnapshotThenDestroyIt) {
- auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
- auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
-
- ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
-
- auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
- auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
-
- ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
-
- auto deleter = [&rollback_ce_dir, &rollback_de_dir,
- &fake_package_ce_path, &fake_package_de_path]() {
- delete_dir_contents(rollback_ce_dir, true);
- delete_dir_contents(rollback_de_dir, true);
- delete_dir_contents(fake_package_ce_path, true);
- delete_dir_contents(fake_package_de_path, true);
- rmdir(rollback_ce_dir.c_str());
- rmdir(rollback_de_dir.c_str());
- };
- auto scope_guard = android::base::make_scope_guard(deleter);
+TEST_F(AppDataSnapshotTest, CreateSnapshotThenDestroyIt) {
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 57);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 57);
// Prepare data for snapshot.
ASSERT_TRUE(android::base::WriteStringToFile(
@@ -588,7 +585,7 @@
int64_t ce_snapshot_inode;
// Request a snapshot of both the CE as well as the DE content.
ASSERT_TRUE(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE, &ce_snapshot_inode).isOk());
+ "com.foo", 0, 57, FLAG_STORAGE_DE | FLAG_STORAGE_CE, &ce_snapshot_inode).isOk());
// Because CE data snapshot was requested, ce_snapshot_inode can't be null.
ASSERT_NE(0, ce_snapshot_inode);
// Check snapshot is there.
@@ -598,39 +595,19 @@
ASSERT_TRUE(service->destroyAppDataSnapshot(std::make_unique<std::string>("TEST"),
- "com.foo", 0, ce_snapshot_inode, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
+ "com.foo", 0, ce_snapshot_inode, 57, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
// Check snapshot is deleted.
ASSERT_EQ(-1, stat((rollback_ce_dir + "/com.foo").c_str(), &sb));
ASSERT_EQ(-1, stat((rollback_de_dir + "/com.foo").c_str(), &sb));
}
-TEST_F(ServiceTest, DestroyAppDataSnapshot_CeSnapshotInodeIsZero) {
- auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
- auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
-
- ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
-
- auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
- auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
-
- ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
-
- auto deleter = [&rollback_ce_dir, &rollback_de_dir,
- &fake_package_ce_path, &fake_package_de_path]() {
- delete_dir_contents(rollback_ce_dir, true);
- delete_dir_contents(rollback_de_dir, true);
- delete_dir_contents(fake_package_ce_path, true);
- delete_dir_contents(fake_package_de_path, true);
- rmdir(rollback_ce_dir.c_str());
- rmdir(rollback_de_dir.c_str());
- };
- auto scope_guard = android::base::make_scope_guard(deleter);
+TEST_F(AppDataSnapshotTest, DestroyAppDataSnapshot_CeSnapshotInodeIsZero) {
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 1543);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 1543);
// Create a snapshot
- ASSERT_TRUE(mkdirs(rollback_ce_dir + "/com.foo/", 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir + "/com.foo/", 700));
+ ASSERT_TRUE(mkdirs(rollback_ce_dir + "/com.foo/", 0700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir + "/com.foo/", 0700));
ASSERT_TRUE(android::base::WriteStringToFile(
"CE_RESTORE_CONTENT", rollback_ce_dir + "/com.foo/file1",
0700, 10000, 20000, false /* follow_symlinks */));
@@ -639,7 +616,7 @@
0700, 10000, 20000, false /* follow_symlinks */));
ASSERT_TRUE(service->destroyAppDataSnapshot(std::make_unique<std::string>("TEST"),
- "com.foo", 0, 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
+ "com.foo", 0, 0, 1543, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
// Check snapshot is deleted.
struct stat sb;
@@ -648,67 +625,33 @@
// Check that deleting already deleted snapshot is no-op.
ASSERT_TRUE(service->destroyAppDataSnapshot(std::make_unique<std::string>("TEST"),
- "com.foo", 0, 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
+ "com.foo", 0, 0, 1543, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
}
-TEST_F(ServiceTest, DestroyAppDataSnapshot_WrongVolumeUuid) {
+TEST_F(AppDataSnapshotTest, DestroyAppDataSnapshot_WrongVolumeUuid) {
// Setup rollback data to make sure that test fails due to wrong volumeUuid
// being passed, not because of some other reason.
- auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
- auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 43);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 43);
- ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
-
- auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
- auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
-
- ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
-
- auto deleter = [&rollback_ce_dir, &rollback_de_dir,
- &fake_package_ce_path, &fake_package_de_path]() {
- delete_dir_contents(rollback_ce_dir, true);
- delete_dir_contents(rollback_de_dir, true);
- delete_dir_contents(fake_package_ce_path, true);
- delete_dir_contents(fake_package_de_path, true);
- rmdir(rollback_ce_dir.c_str());
- rmdir(rollback_de_dir.c_str());
- };
- auto scope_guard = android::base::make_scope_guard(deleter);
+ ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
ASSERT_FALSE(service->destroyAppDataSnapshot(std::make_unique<std::string>("BAR"),
- "com.foo", 0, 0, FLAG_STORAGE_DE).isOk());
+ "com.foo", 0, 0, 43, FLAG_STORAGE_DE).isOk());
}
-TEST_F(ServiceTest, RestoreAppDataSnapshot_WrongVolumeUuid) {
+TEST_F(AppDataSnapshotTest, RestoreAppDataSnapshot_WrongVolumeUuid) {
// Setup rollback data to make sure that fails due to wrong volumeUuid being
// passed, not because of some other reason.
- auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
- auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 41);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 41);
- ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
-
- auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
- auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
-
- ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
-
- auto deleter = [&rollback_ce_dir, &rollback_de_dir,
- &fake_package_ce_path, &fake_package_de_path]() {
- delete_dir_contents(rollback_ce_dir, true);
- delete_dir_contents(rollback_de_dir, true);
- delete_dir_contents(fake_package_ce_path, true);
- delete_dir_contents(fake_package_de_path, true);
- rmdir(rollback_ce_dir.c_str());
- rmdir(rollback_de_dir.c_str());
- };
- auto scope_guard = android::base::make_scope_guard(deleter);
+ ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
EXPECT_BINDER_FAIL(service->restoreAppDataSnapshot(std::make_unique<std::string>("BAR"),
- "com.foo", 10000, -1, "", 0, FLAG_STORAGE_DE));
+ "com.foo", 10000, "", 0, 41, FLAG_STORAGE_DE));
}
} // namespace installd
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 1782aa2..e61eb6e 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -546,56 +546,86 @@
}
TEST_F(UtilsTest, TestRollbackPaths) {
- EXPECT_EQ("/data/misc_ce/0/rollback/com.foo",
- create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo"));
- EXPECT_EQ("/data/misc_ce/10/rollback/com.foo",
- create_data_misc_ce_rollback_package_path(nullptr, 10, "com.foo"));
+ EXPECT_EQ("/data/misc_ce/0/rollback/239/com.foo",
+ create_data_misc_ce_rollback_package_path(nullptr, 0, 239, "com.foo"));
+ EXPECT_EQ("/data/misc_ce/10/rollback/37/com.foo",
+ create_data_misc_ce_rollback_package_path(nullptr, 10, 37, "com.foo"));
- EXPECT_EQ("/data/misc_de/0/rollback/com.foo",
- create_data_misc_de_rollback_package_path(nullptr, 0, "com.foo"));
- EXPECT_EQ("/data/misc_de/10/rollback/com.foo",
- create_data_misc_de_rollback_package_path(nullptr, 10, "com.foo"));
+ EXPECT_EQ("/data/misc_de/0/rollback/73/com.foo",
+ create_data_misc_de_rollback_package_path(nullptr, 0, 73, "com.foo"));
+ EXPECT_EQ("/data/misc_de/10/rollback/13/com.foo",
+ create_data_misc_de_rollback_package_path(nullptr, 10, 13, "com.foo"));
- EXPECT_EQ("/data/misc_ce/0/rollback",
- create_data_misc_ce_rollback_path(nullptr, 0));
- EXPECT_EQ("/data/misc_ce/10/rollback",
- create_data_misc_ce_rollback_path(nullptr, 10));
+ EXPECT_EQ("/data/misc_ce/0/rollback/57",
+ create_data_misc_ce_rollback_path(nullptr, 0, 57));
+ EXPECT_EQ("/data/misc_ce/10/rollback/1543",
+ create_data_misc_ce_rollback_path(nullptr, 10, 1543));
- EXPECT_EQ("/data/misc_de/0/rollback",
- create_data_misc_de_rollback_path(nullptr, 0));
- EXPECT_EQ("/data/misc_de/10/rollback",
- create_data_misc_de_rollback_path(nullptr, 10));
+ EXPECT_EQ("/data/misc_de/0/rollback/43",
+ create_data_misc_de_rollback_path(nullptr, 0, 43));
+ EXPECT_EQ("/data/misc_de/10/rollback/41",
+ create_data_misc_de_rollback_path(nullptr, 10, 41));
- EXPECT_EQ("/data/misc_ce/0/rollback/com.foo",
- create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo", 0));
- EXPECT_EQ("/data/misc_ce/0/rollback/com.foo",
- create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo", 239));
+ EXPECT_EQ("/data/misc_ce/0/rollback/17/com.foo",
+ create_data_misc_ce_rollback_package_path(nullptr, 0, 17, "com.foo", 0));
+ EXPECT_EQ("/data/misc_ce/0/rollback/19/com.foo",
+ create_data_misc_ce_rollback_package_path(nullptr, 0, 19, "com.foo", 239));
- auto rollback_ce_package_path = create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo");
- auto deleter = [&rollback_ce_package_path]() {
- delete_dir_contents_and_dir(rollback_ce_package_path, true /* ignore_if_missing */);
+ auto rollback_ce_path = create_data_misc_ce_rollback_path(nullptr, 0, 53);
+ auto rollback_ce_package_path = create_data_misc_ce_rollback_package_path(nullptr, 0, 53,
+ "com.foo");
+ auto deleter = [&rollback_ce_path]() {
+ delete_dir_contents_and_dir(rollback_ce_path, true /* ignore_if_missing */);
};
auto scope_guard = android::base::make_scope_guard(deleter);
- ASSERT_NE(-1, mkdir(rollback_ce_package_path.c_str(), 700));
+ EXPECT_NE(-1, mkdir(rollback_ce_path.c_str(), 700));
+ EXPECT_NE(-1, mkdir(rollback_ce_package_path.c_str(), 700));
ino_t ce_data_inode;
- ASSERT_EQ(0, get_path_inode(rollback_ce_package_path, &ce_data_inode));
+ EXPECT_EQ(0, get_path_inode(rollback_ce_package_path, &ce_data_inode));
- EXPECT_EQ("/data/misc_ce/0/rollback/com.foo",
- create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo", ce_data_inode));
+ EXPECT_EQ("/data/misc_ce/0/rollback/53/com.foo",
+ create_data_misc_ce_rollback_package_path(nullptr, 0, 53, "com.foo", ce_data_inode));
// Check that path defined by inode is picked even if it's not the same as
// the fallback one.
- EXPECT_EQ("/data/misc_ce/0/rollback/com.foo",
- create_data_misc_ce_rollback_package_path(nullptr, 0, "com.bar", ce_data_inode));
+ EXPECT_EQ("/data/misc_ce/0/rollback/53/com.foo",
+ create_data_misc_ce_rollback_package_path(nullptr, 0, 53, "com.bar", ce_data_inode));
// These last couple of cases are never exercised in production because we
// only snapshot apps in the primary data partition. Exercise them here for
// the sake of completeness.
- EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/misc_ce/0/rollback/com.example",
- create_data_misc_ce_rollback_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example"));
- EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/misc_de/0/rollback/com.example",
- create_data_misc_de_rollback_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example"));
+ EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/misc_ce/0/rollback/7/com.example",
+ create_data_misc_ce_rollback_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, 7,
+ "com.example"));
+ EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/misc_de/0/rollback/11/com.example",
+ create_data_misc_de_rollback_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, 11,
+ "com.example"));
+}
+
+TEST_F(UtilsTest, TestCreateDirIfNeeded) {
+ system("mkdir -p /data/local/tmp/user/0");
+
+ auto deleter = [&]() {
+ delete_dir_contents_and_dir("/data/local/tmp/user/0", true /* ignore_if_missing */);
+ };
+ auto scope_guard = android::base::make_scope_guard(deleter);
+
+ // Create folder and check it's permissions.
+ ASSERT_EQ(0, create_dir_if_needed("/data/local/tmp/user/0/foo", 0700));
+ struct stat st;
+ ASSERT_EQ(0, stat("/data/local/tmp/user/0/foo", &st));
+ ASSERT_EQ(0700, st.st_mode & ALLPERMS);
+
+ // Check that create_dir_if_needed is no-op if folder already exists with
+ // correct permissions.
+ ASSERT_EQ(0, create_dir_if_needed("/data/local/tmp/user/0/foo", 0700));
+
+ // Check -1 is returned if folder exists but with different permissions.
+ ASSERT_EQ(-1, create_dir_if_needed("/data/local/tmp/user/0/foo", 0750));
+
+ // Check that call fails if parent doesn't exist.
+ ASSERT_NE(0, create_dir_if_needed("/data/local/tmp/user/0/bar/baz", 0700));
}
} // namespace installd
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 5b487bb..52ca0df 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -197,32 +197,44 @@
return StringPrintf("%s/user_de/%u", data.c_str(), userid);
}
-
-std::string create_data_misc_ce_rollback_path(const char* volume_uuid, userid_t user) {
+std::string create_data_misc_ce_rollback_base_path(const char* volume_uuid, userid_t user) {
return StringPrintf("%s/misc_ce/%u/rollback", create_data_path(volume_uuid).c_str(), user);
}
-std::string create_data_misc_de_rollback_path(const char* volume_uuid, userid_t user) {
+std::string create_data_misc_de_rollback_base_path(const char* volume_uuid, userid_t user) {
return StringPrintf("%s/misc_de/%u/rollback", create_data_path(volume_uuid).c_str(), user);
}
-std::string create_data_misc_ce_rollback_package_path(const char* volume_uuid,
- userid_t user, const char* package_name) {
- return StringPrintf("%s/%s",
- create_data_misc_ce_rollback_path(volume_uuid, user).c_str(), package_name);
+std::string create_data_misc_ce_rollback_path(const char* volume_uuid, userid_t user,
+ int32_t snapshot_id) {
+ return StringPrintf("%s/%d", create_data_misc_ce_rollback_base_path(volume_uuid, user).c_str(),
+ snapshot_id);
+}
+
+std::string create_data_misc_de_rollback_path(const char* volume_uuid, userid_t user,
+ int32_t snapshot_id) {
+ return StringPrintf("%s/%d", create_data_misc_de_rollback_base_path(volume_uuid, user).c_str(),
+ snapshot_id);
}
std::string create_data_misc_ce_rollback_package_path(const char* volume_uuid,
- userid_t user, const char* package_name, ino_t ce_rollback_inode) {
- auto fallback = create_data_misc_ce_rollback_package_path(volume_uuid, user, package_name);
- auto user_path = create_data_misc_ce_rollback_path(volume_uuid, user);
+ userid_t user, int32_t snapshot_id, const char* package_name) {
+ return StringPrintf("%s/%s",
+ create_data_misc_ce_rollback_path(volume_uuid, user, snapshot_id).c_str(), package_name);
+}
+
+std::string create_data_misc_ce_rollback_package_path(const char* volume_uuid,
+ userid_t user, int32_t snapshot_id, const char* package_name, ino_t ce_rollback_inode) {
+ auto fallback = create_data_misc_ce_rollback_package_path(volume_uuid, user, snapshot_id,
+ package_name);
+ auto user_path = create_data_misc_ce_rollback_path(volume_uuid, user, snapshot_id);
return resolve_ce_path_by_inode_or_fallback(user_path, ce_rollback_inode, fallback);
}
std::string create_data_misc_de_rollback_package_path(const char* volume_uuid,
- userid_t user, const char* package_name) {
+ userid_t user, int32_t snapshot_id, const char* package_name) {
return StringPrintf("%s/%s",
- create_data_misc_de_rollback_path(volume_uuid, user).c_str(), package_name);
+ create_data_misc_de_rollback_path(volume_uuid, user, snapshot_id).c_str(), package_name);
}
/**
@@ -528,6 +540,30 @@
return result;
}
+int create_dir_if_needed(const std::string& pathname, mode_t perms) {
+ struct stat st;
+
+ int rc;
+ if ((rc = stat(pathname.c_str(), &st)) != 0) {
+ if (errno == ENOENT) {
+ return mkdir(pathname.c_str(), perms);
+ } else {
+ return rc;
+ }
+ } else if (!S_ISDIR(st.st_mode)) {
+ LOG(DEBUG) << pathname << " is not a folder";
+ return -1;
+ }
+
+ mode_t actual_perms = st.st_mode & ALLPERMS;
+ if (actual_perms != perms) {
+ LOG(WARNING) << pathname << " permissions " << actual_perms << " expected " << perms;
+ return -1;
+ }
+
+ return 0;
+}
+
int delete_dir_contents(const std::string& pathname, bool ignore_if_missing) {
return delete_dir_contents(pathname.c_str(), 0, nullptr, ignore_if_missing);
}
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 0711b34..955d524 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -61,14 +61,18 @@
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_ce_rollback_path(const char* volume_uuid, userid_t user);
-std::string create_data_misc_de_rollback_path(const char* volume_uuid, userid_t user);
+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);
+std::string create_data_misc_ce_rollback_path(const char* volume_uuid, userid_t user,
+ int32_t snapshot_id);
+std::string create_data_misc_de_rollback_path(const char* volume_uuid, userid_t user,
+ int32_t snapshot_id);
std::string create_data_misc_ce_rollback_package_path(const char* volume_uuid,
- userid_t user, const char* package_name);
+ userid_t user, int32_t snapshot_id, const char* package_name);
std::string create_data_misc_ce_rollback_package_path(const char* volume_uuid,
- userid_t user, const char* package_name, ino_t ce_rollback_inode);
+ userid_t user, int32_t snapshot_id, const char* package_name, ino_t ce_rollback_inode);
std::string create_data_misc_de_rollback_package_path(const char* volume_uuid,
- userid_t user, const char* package_name);
+ userid_t user, int32_t snapshot_id, const char* package_name);
std::string create_data_media_path(const char* volume_uuid, userid_t userid);
std::string create_data_media_obb_path(const char* volume_uuid, const char* package_name);
@@ -109,6 +113,8 @@
bool is_valid_filename(const std::string& name);
bool is_valid_package_name(const std::string& packageName);
+int create_dir_if_needed(const std::string& pathname, mode_t mode);
+
int delete_dir_contents(const std::string& pathname, bool ignore_if_missing = false);
int delete_dir_contents_and_dir(const std::string& pathname, bool ignore_if_missing = false);
diff --git a/include/input/IInputFlinger.h b/include/input/IInputFlinger.h
index ff443c6..cd12fcd 100644
--- a/include/input/IInputFlinger.h
+++ b/include/input/IInputFlinger.h
@@ -24,6 +24,7 @@
#include <utils/Vector.h>
#include <input/InputWindow.h>
+#include <input/ISetInputWindowsListener.h>
namespace android {
@@ -35,7 +36,8 @@
public:
DECLARE_META_INTERFACE(InputFlinger)
- virtual void setInputWindows(const Vector<InputWindowInfo>& inputHandles) = 0;
+ virtual void setInputWindows(const Vector<InputWindowInfo>& inputHandles,
+ const sp<ISetInputWindowsListener>& setInputWindowsListener) = 0;
virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) = 0;
virtual void registerInputChannel(const sp<InputChannel>& channel) = 0;
virtual void unregisterInputChannel(const sp<InputChannel>& channel) = 0;
diff --git a/include/input/ISetInputWindowsListener.h b/include/input/ISetInputWindowsListener.h
new file mode 100644
index 0000000..15d31b2
--- /dev/null
+++ b/include/input/ISetInputWindowsListener.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+class ISetInputWindowsListener : public IInterface {
+public:
+ DECLARE_META_INTERFACE(SetInputWindowsListener)
+ virtual void onSetInputWindowsFinished() = 0;
+};
+
+class BnSetInputWindowsListener: public BnInterface<ISetInputWindowsListener> {
+public:
+ enum SetInputWindowsTag : uint32_t {
+ ON_SET_INPUT_WINDOWS_FINISHED
+ };
+
+ virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags = 0) override;
+};
+
+}; // namespace android
diff --git a/include/input/Keyboard.h b/include/input/Keyboard.h
index 8b66f69..92da10c 100644
--- a/include/input/Keyboard.h
+++ b/include/input/Keyboard.h
@@ -25,15 +25,6 @@
namespace android {
-enum {
- /* Device id of the built in keyboard. */
- DEVICE_ID_BUILT_IN_KEYBOARD = 0,
-
- /* Device id of a generic virtual keyboard with a full layout that can be used
- * to synthesize key events. */
- DEVICE_ID_VIRTUAL_KEYBOARD = -1,
-};
-
class KeyLayoutMap;
class KeyCharacterMap;
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 386f9f0..13c0d87 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -146,36 +146,39 @@
return 0;
}
-void GraphicsEnv::setDriverPath(const std::string path) {
- if (!mDriverPath.empty()) {
- ALOGV("ignoring attempt to change driver path from '%s' to '%s'", mDriverPath.c_str(),
- path.c_str());
+void GraphicsEnv::setDriverPathAndSphalLibraries(const std::string path,
+ const std::string sphalLibraries) {
+ if (!mDriverPath.empty() || !mSphalLibraries.empty()) {
+ ALOGV("ignoring attempt to change driver path from '%s' to '%s' or change sphal libraries "
+ "from '%s' to '%s'",
+ mDriverPath.c_str(), path.c_str(), mSphalLibraries.c_str(), sphalLibraries.c_str());
return;
}
- ALOGV("setting driver path to '%s'", path.c_str());
+ ALOGV("setting driver path to '%s' and sphal libraries to '%s'", path.c_str(),
+ sphalLibraries.c_str());
mDriverPath = path;
+ mSphalLibraries = sphalLibraries;
}
void GraphicsEnv::setGpuStats(const std::string& driverPackageName,
const std::string& driverVersionName, uint64_t driverVersionCode,
- const std::string& driverBuildDate,
- const std::string& appPackageName) {
+ int64_t driverBuildTime, const std::string& appPackageName) {
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mStatsLock);
ALOGV("setGpuStats:\n"
"\tdriverPackageName[%s]\n"
"\tdriverVersionName[%s]\n"
- "\tdriverVersionCode[%llu]\n"
- "\tdriverBuildDate[%s]\n"
+ "\tdriverVersionCode[%" PRIu64 "]\n"
+ "\tdriverBuildTime[%" PRId64 "]\n"
"\tappPackageName[%s]\n",
- driverPackageName.c_str(), driverVersionName.c_str(),
- (unsigned long long)driverVersionCode, driverBuildDate.c_str(), appPackageName.c_str());
+ driverPackageName.c_str(), driverVersionName.c_str(), driverVersionCode, driverBuildTime,
+ appPackageName.c_str());
mGpuStats.driverPackageName = driverPackageName;
mGpuStats.driverVersionName = driverVersionName;
mGpuStats.driverVersionCode = driverVersionCode;
- mGpuStats.driverBuildDate = driverBuildDate;
+ mGpuStats.driverBuildTime = driverBuildTime;
mGpuStats.appPackageName = appPackageName;
}
@@ -264,21 +267,20 @@
ALOGV("sendGpuStats:\n"
"\tdriverPackageName[%s]\n"
"\tdriverVersionName[%s]\n"
- "\tdriverVersionCode[%llu]\n"
- "\tdriverBuildDate[%s]\n"
+ "\tdriverVersionCode[%" PRIu64 "]\n"
+ "\tdriverBuildTime[%" PRId64 "]\n"
"\tappPackageName[%s]\n"
"\tdriver[%d]\n"
"\tisDriverLoaded[%d]\n"
- "\tdriverLoadingTime[%lld]",
+ "\tdriverLoadingTime[%" PRId64 "]",
mGpuStats.driverPackageName.c_str(), mGpuStats.driverVersionName.c_str(),
- (unsigned long long)mGpuStats.driverVersionCode, mGpuStats.driverBuildDate.c_str(),
- mGpuStats.appPackageName.c_str(), static_cast<int32_t>(driver), isDriverLoaded,
- (long long)driverLoadingTime);
+ mGpuStats.driverVersionCode, mGpuStats.driverBuildTime, mGpuStats.appPackageName.c_str(),
+ static_cast<int32_t>(driver), isDriverLoaded, driverLoadingTime);
const sp<IGpuService> gpuService = getGpuService();
if (gpuService) {
gpuService->setGpuStats(mGpuStats.driverPackageName, mGpuStats.driverVersionName,
- mGpuStats.driverVersionCode, mGpuStats.driverBuildDate,
+ mGpuStats.driverVersionCode, mGpuStats.driverBuildTime,
mGpuStats.appPackageName, driver, isDriverLoaded,
driverLoadingTime);
}
@@ -538,6 +540,23 @@
mDriverNamespace = nullptr;
return;
}
+
+ if (mSphalLibraries.empty()) return;
+
+ // Make additional libraries in sphal to be accessible
+ auto sphalNamespace = android_get_exported_namespace("sphal");
+ if (!sphalNamespace) {
+ ALOGE("Depend on these libraries[%s] in sphal, but failed to get sphal namespace",
+ mSphalLibraries.c_str());
+ mDriverNamespace = nullptr;
+ return;
+ }
+
+ if (!android_link_namespaces(mDriverNamespace, sphalNamespace, mSphalLibraries.c_str())) {
+ ALOGE("Failed to link sphal namespace[%s]", dlerror());
+ mDriverNamespace = nullptr;
+ return;
+ }
});
return mDriverNamespace;
diff --git a/libs/graphicsenv/IGpuService.cpp b/libs/graphicsenv/IGpuService.cpp
index a8a07c2..f755e00 100644
--- a/libs/graphicsenv/IGpuService.cpp
+++ b/libs/graphicsenv/IGpuService.cpp
@@ -29,7 +29,7 @@
virtual void setGpuStats(const std::string& driverPackageName,
const std::string& driverVersionName, uint64_t driverVersionCode,
- const std::string& driverBuildDate, const std::string& appPackageName,
+ int64_t driverBuildTime, const std::string& appPackageName,
GraphicsEnv::Driver driver, bool isDriverLoaded,
int64_t driverLoadingTime) {
Parcel data, reply;
@@ -38,7 +38,7 @@
data.writeUtf8AsUtf16(driverPackageName);
data.writeUtf8AsUtf16(driverVersionName);
data.writeUint64(driverVersionCode);
- data.writeUtf8AsUtf16(driverBuildDate);
+ data.writeInt64(driverBuildTime);
data.writeUtf8AsUtf16(appPackageName);
data.writeInt32(static_cast<int32_t>(driver));
data.writeBool(isDriverLoaded);
@@ -68,8 +68,8 @@
uint64_t driverVersionCode;
if ((status = data.readUint64(&driverVersionCode)) != OK) return status;
- std::string driverBuildDate;
- if ((status = data.readUtf8FromUtf16(&driverBuildDate)) != OK) return status;
+ int64_t driverBuildTime;
+ if ((status = data.readInt64(&driverBuildTime)) != OK) return status;
std::string appPackageName;
if ((status = data.readUtf8FromUtf16(&appPackageName)) != OK) return status;
@@ -83,7 +83,7 @@
int64_t driverLoadingTime;
if ((status = data.readInt64(&driverLoadingTime)) != OK) return status;
- setGpuStats(driverPackageName, driverVersionName, driverVersionCode, driverBuildDate,
+ setGpuStats(driverPackageName, driverVersionName, driverVersionCode, driverBuildTime,
appPackageName, static_cast<GraphicsEnv::Driver>(driver), isDriverLoaded,
driverLoadingTime);
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index 20b0205..cb4239f 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -48,7 +48,7 @@
std::string driverPackageName;
std::string driverVersionName;
uint64_t driverVersionCode;
- std::string driverBuildDate;
+ int64_t driverBuildTime;
std::string appPackageName;
Driver glDriverToLoad;
Driver glDriverFallback;
@@ -59,7 +59,7 @@
: driverPackageName(""),
driverVersionName(""),
driverVersionCode(0),
- driverBuildDate(""),
+ driverBuildTime(0),
appPackageName(""),
glDriverToLoad(Driver::NONE),
glDriverFallback(Driver::NONE),
@@ -77,10 +77,13 @@
// (drivers must be stored uncompressed and page aligned); such elements
// in the search path must have a '!' after the zip filename, e.g.
// /data/app/com.example.driver/base.apk!/lib/arm64-v8a
- void setDriverPath(const std::string path);
+ // Also set additional required sphal libraries to the linker for loading
+ // graphics drivers. The string is a list of libraries separated by ':',
+ // which is required by android_link_namespaces.
+ void setDriverPathAndSphalLibraries(const std::string path, const std::string sphalLibraries);
android_namespace_t* getDriverNamespace();
void setGpuStats(const std::string& driverPackageName, const std::string& driverVersionName,
- uint64_t versionCode, const std::string& driverBuildDate,
+ uint64_t versionCode, int64_t driverBuildTime,
const std::string& appPackageName);
void setDriverToLoad(Driver driver);
void setDriverLoaded(Api api, bool isDriverLoaded, int64_t driverLoadingTime);
@@ -118,6 +121,7 @@
GraphicsEnv() = default;
std::string mDriverPath;
+ std::string mSphalLibraries;
std::mutex mStatsLock;
GpuStats mGpuStats;
std::string mAnglePath;
diff --git a/libs/graphicsenv/include/graphicsenv/IGpuService.h b/libs/graphicsenv/include/graphicsenv/IGpuService.h
index 105a903..5f9340d 100644
--- a/libs/graphicsenv/include/graphicsenv/IGpuService.h
+++ b/libs/graphicsenv/include/graphicsenv/IGpuService.h
@@ -35,7 +35,7 @@
// set GPU stats from GraphicsEnvironment.
virtual void setGpuStats(const std::string& driverPackageName,
const std::string& driverVersionName, uint64_t driverVersionCode,
- const std::string& driverBuildDate, const std::string& appPackageName,
+ int64_t driverBuildTime, const std::string& appPackageName,
GraphicsEnv::Driver driver, bool isDriverLoaded,
int64_t driverLoadingTime) = 0;
};
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 9197262..f77eeb2 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -806,12 +806,6 @@
}
return error;
}
-
- virtual void setInputWindowsFinished() {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- remote()->transact(BnSurfaceComposer::SET_INPUT_WINDOWS_FINISHED, data, &reply);
- }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -1323,11 +1317,6 @@
}
return removeRegionSamplingListener(listener);
}
- case SET_INPUT_WINDOWS_FINISHED: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- setInputWindowsFinished();
- return NO_ERROR;
- }
default: {
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/LayerMetadata.cpp b/libs/gui/LayerMetadata.cpp
index 745433a..04d2871 100644
--- a/libs/gui/LayerMetadata.cpp
+++ b/libs/gui/LayerMetadata.cpp
@@ -31,10 +31,23 @@
LayerMetadata::LayerMetadata(LayerMetadata&& other) = default;
-void LayerMetadata::merge(const LayerMetadata& other) {
+bool LayerMetadata::merge(const LayerMetadata& other, bool eraseEmpty) {
+ bool changed = false;
for (const auto& entry : other.mMap) {
- mMap[entry.first] = entry.second;
+ auto it = mMap.find(entry.first);
+ if (it != mMap.cend() && it->second != entry.second) {
+ if (eraseEmpty && entry.second.empty()) {
+ mMap.erase(it);
+ } else {
+ it->second = entry.second;
+ }
+ changed = true;
+ } else if (it == mMap.cend() && !entry.second.empty()) {
+ mMap[entry.first] = entry.second;
+ changed = true;
+ }
}
+ return changed;
}
status_t LayerMetadata::writeToParcel(Parcel* parcel) const {
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index c2d7d28..e6700e7 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -359,8 +359,6 @@
* Removes a listener that was streaming median luma updates from SurfaceFlinger.
*/
virtual status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) = 0;
-
- virtual void setInputWindowsFinished() = 0;
};
// ----------------------------------------------------------------------------
@@ -408,7 +406,6 @@
GET_PHYSICAL_DISPLAY_IDS,
ADD_REGION_SAMPLING_LISTENER,
REMOVE_REGION_SAMPLING_LISTENER,
- SET_INPUT_WINDOWS_FINISHED,
// Always append new enum to the end.
};
diff --git a/libs/gui/include/gui/LayerMetadata.h b/libs/gui/include/gui/LayerMetadata.h
index 3ae10e4..47f0ced 100644
--- a/libs/gui/include/gui/LayerMetadata.h
+++ b/libs/gui/include/gui/LayerMetadata.h
@@ -34,7 +34,9 @@
LayerMetadata& operator=(const LayerMetadata& other);
LayerMetadata& operator=(LayerMetadata&& other);
- void merge(const LayerMetadata& other);
+ // Merges other into this LayerMetadata. If eraseEmpty is true, any entries in
+ // in this whose keys are paired with empty values in other will be erased.
+ bool merge(const LayerMetadata& other, bool eraseEmpty = false);
status_t writeToParcel(Parcel* parcel) const override;
status_t readFromParcel(const Parcel* parcel) override;
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 8430874..32d7391 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -254,7 +254,7 @@
};
std::vector<TransferTouchFocusCommand> transferTouchFocusCommands;
- bool syncInputWindows;
+ bool syncInputWindows{false};
void merge(const InputWindowCommands& other);
void clear();
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index f020a40..a5b87ec 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -87,3 +87,26 @@
"libdvr_headers",
],
}
+
+cc_test {
+ name: "SamplingDemo",
+
+ clang: true,
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+
+ srcs: [
+ "SamplingDemo.cpp",
+ ],
+
+ shared_libs: [
+ "libbinder",
+ "libcutils",
+ "libgui",
+ "liblog",
+ "libui",
+ "libutils",
+ ]
+}
diff --git a/libs/gui/tests/SamplingDemo.cpp b/libs/gui/tests/SamplingDemo.cpp
new file mode 100644
index 0000000..9891587
--- /dev/null
+++ b/libs/gui/tests/SamplingDemo.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#define LOG_TAG "SamplingTest"
+
+#include <chrono>
+#include <thread>
+
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <gui/IRegionSamplingListener.h>
+#include <gui/ISurfaceComposer.h>
+#include <gui/SurfaceComposerClient.h>
+#include <gui/SurfaceControl.h>
+#include <private/gui/ComposerService.h>
+#include <utils/Trace.h>
+
+using namespace std::chrono_literals;
+
+namespace android {
+
+class Button : public BnRegionSamplingListener {
+public:
+ Button(const char* name, const Rect& samplingArea) {
+ sp<SurfaceComposerClient> client = new SurfaceComposerClient;
+
+ mButton = client->createSurface(String8(name), 0, 0, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceColor);
+
+ const int32_t width = samplingArea.getWidth();
+ const int32_t height = samplingArea.getHeight();
+
+ SurfaceComposerClient::Transaction{}
+ .setLayer(mButton, 0x7fffffff)
+ .setCrop_legacy(mButton,
+ {0, 0, width - 2 * BUTTON_PADDING, height - 2 * BUTTON_PADDING})
+ .setPosition(mButton, samplingArea.left + BUTTON_PADDING,
+ samplingArea.top + BUTTON_PADDING)
+ .setColor(mButton, half3{1, 1, 1})
+ .show(mButton)
+ .apply();
+
+ mButtonBlend = client->createSurface(String8(name) + "Blend", 0, 0, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceColor);
+
+ SurfaceComposerClient::Transaction{}
+ .setLayer(mButtonBlend, 0x7ffffffe)
+ .setCrop_legacy(mButtonBlend,
+ {0, 0, width - 2 * SAMPLE_AREA_PADDING,
+ height - 2 * SAMPLE_AREA_PADDING})
+ .setPosition(mButtonBlend, samplingArea.left + SAMPLE_AREA_PADDING,
+ samplingArea.top + SAMPLE_AREA_PADDING)
+ .setColor(mButtonBlend, half3{1, 1, 1})
+ .setAlpha(mButtonBlend, 0.2)
+ .show(mButtonBlend)
+ .apply(true);
+
+ const bool HIGHLIGHT_SAMPLING_AREA = false;
+ if (HIGHLIGHT_SAMPLING_AREA) {
+ mSamplingArea =
+ client->createSurface(String8("SamplingArea"), 0, 0, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceColor);
+
+ SurfaceComposerClient::Transaction{}
+ .setLayer(mSamplingArea, 0x7ffffffd)
+ .setCrop_legacy(mSamplingArea, {0, 0, 100, 32})
+ .setPosition(mSamplingArea, 490, 1606)
+ .setColor(mSamplingArea, half3{0, 1, 0})
+ .setAlpha(mSamplingArea, 0.1)
+ .show(mSamplingArea)
+ .apply();
+ }
+ }
+
+ sp<IBinder> getStopLayerHandle() { return mButtonBlend->getHandle(); }
+
+private:
+ static const int32_t BLEND_WIDTH = 2;
+ static const int32_t SAMPLE_AREA_PADDING = 8;
+ static const int32_t BUTTON_PADDING = BLEND_WIDTH + SAMPLE_AREA_PADDING;
+
+ void setColor(float color) {
+ const float complement = std::fmod(color + 0.5f, 1.0f);
+ SurfaceComposerClient::Transaction{}
+ .setColor(mButton, half3{complement, complement, complement})
+ .setColor(mButtonBlend, half3{color, color, color})
+ .apply();
+ }
+
+ void onSampleCollected(float medianLuma) override {
+ ATRACE_CALL();
+ setColor(medianLuma);
+ }
+
+ sp<SurfaceComposerClient> mClient;
+ sp<SurfaceControl> mButton;
+ sp<SurfaceControl> mButtonBlend;
+ sp<SurfaceControl> mSamplingArea;
+};
+
+} // namespace android
+
+using namespace android;
+
+int main(int, const char**) {
+ const Rect homeButtonArea{490, 1606, 590, 1654};
+ sp<android::Button> homeButton = new android::Button("HomeButton", homeButtonArea);
+ const Rect backButtonArea{200, 1606, 248, 1654};
+ sp<android::Button> backButton = new android::Button("BackButton", backButtonArea);
+
+ sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+ composer->addRegionSamplingListener(homeButtonArea, homeButton->getStopLayerHandle(),
+ homeButton);
+ composer->addRegionSamplingListener(backButtonArea, backButton->getStopLayerHandle(),
+ backButton);
+
+ ProcessState::self()->startThreadPool();
+ IPCThreadState::self()->joinThreadPool();
+
+ return 0;
+}
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 8225647..f127853 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -679,8 +679,6 @@
return NO_ERROR;
}
- void setInputWindowsFinished() override {}
-
protected:
IBinder* onAsBinder() override { return nullptr; }
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 6aedb00..2d78811 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -47,6 +47,7 @@
"InputApplication.cpp",
"InputTransport.cpp",
"InputWindow.cpp",
+ "ISetInputWindowsListener.cpp",
"VelocityControl.cpp",
"VelocityTracker.cpp",
],
diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp
index acf40bc..4ce5a10 100644
--- a/libs/input/IInputFlinger.cpp
+++ b/libs/input/IInputFlinger.cpp
@@ -30,7 +30,8 @@
explicit BpInputFlinger(const sp<IBinder>& impl) :
BpInterface<IInputFlinger>(impl) { }
- virtual void setInputWindows(const Vector<InputWindowInfo>& inputInfo) {
+ virtual void setInputWindows(const Vector<InputWindowInfo>& inputInfo,
+ const sp<ISetInputWindowsListener>& setInputWindowsListener) {
Parcel data, reply;
data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor());
@@ -38,6 +39,8 @@
for (const auto& info : inputInfo) {
info.write(data);
}
+ data.writeStrongBinder(IInterface::asBinder(setInputWindowsListener));
+
remote()->transact(BnInputFlinger::SET_INPUT_WINDOWS_TRANSACTION, data, &reply,
IBinder::FLAG_ONEWAY);
}
@@ -83,7 +86,9 @@
for (size_t i = 0; i < count; i++) {
handles.add(InputWindowInfo(data));
}
- setInputWindows(handles);
+ const sp<ISetInputWindowsListener> setInputWindowsListener =
+ ISetInputWindowsListener::asInterface(data.readStrongBinder());
+ setInputWindows(handles, setInputWindowsListener);
break;
}
case REGISTER_INPUT_CHANNEL_TRANSACTION: {
diff --git a/libs/input/ISetInputWindowsListener.cpp b/libs/input/ISetInputWindowsListener.cpp
new file mode 100644
index 0000000..a0330da
--- /dev/null
+++ b/libs/input/ISetInputWindowsListener.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <input/ISetInputWindowsListener.h>
+
+namespace android {
+
+class BpSetInputWindowsListener : public BpInterface<ISetInputWindowsListener> {
+public:
+ explicit BpSetInputWindowsListener(const sp<IBinder>& impl)
+ : BpInterface<ISetInputWindowsListener>(impl) {
+ }
+
+ virtual ~BpSetInputWindowsListener() = default;
+
+ virtual void onSetInputWindowsFinished() {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISetInputWindowsListener::getInterfaceDescriptor());
+ remote()->transact(BnSetInputWindowsListener::ON_SET_INPUT_WINDOWS_FINISHED, data, &reply,
+ IBinder::FLAG_ONEWAY);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(SetInputWindowsListener, "android.input.ISetInputWindowsListener");
+
+status_t BnSetInputWindowsListener::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags) {
+ switch(code) {
+ case ON_SET_INPUT_WINDOWS_FINISHED: {
+ CHECK_INTERFACE(ISetInputWindowsListener, data, reply);
+ onSetInputWindowsFinished();
+ return NO_ERROR;
+ }
+ default: {
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+ }
+}
+
+} // namespace android
diff --git a/libs/renderengine/OWNERS b/libs/renderengine/OWNERS
new file mode 100644
index 0000000..c00fbba
--- /dev/null
+++ b/libs/renderengine/OWNERS
@@ -0,0 +1,2 @@
+lpy@google.com
+stoza@google.com
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 8f9071e..e7ff9ab 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -789,13 +789,18 @@
status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
const std::vector<LayerSettings>& layers,
ANativeWindowBuffer* const buffer,
- base::unique_fd* drawFence) {
+ base::unique_fd&& bufferFence, base::unique_fd* drawFence) {
ATRACE_CALL();
if (layers.empty()) {
ALOGV("Drawing empty layer stack");
return NO_ERROR;
}
+ if (bufferFence.get() >= 0 && !waitFence(std::move(bufferFence))) {
+ ATRACE_NAME("Waiting before draw");
+ sync_wait(bufferFence.get(), -1);
+ }
+
BindNativeBufferAsFramebuffer fbo(*this, buffer);
if (fbo.getStatus() != NO_ERROR) {
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index 7b72666..a86b4f5 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -81,7 +81,8 @@
bool supportsProtectedContent() const override;
bool useProtectedContext(bool useProtectedContext) override;
status_t drawLayers(const DisplaySettings& display, const std::vector<LayerSettings>& layers,
- ANativeWindowBuffer* buffer, base::unique_fd* drawFence) override;
+ ANativeWindowBuffer* buffer, base::unique_fd&& bufferFence,
+ base::unique_fd* drawFence) override;
// internal to RenderEngine
EGLDisplay getEGLDisplay() const { return mEGLDisplay; }
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index b51ed22..812d761 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -167,7 +167,9 @@
// drawing any layers.
// @param layers The layers to draw onto the display, in Z-order.
// @param buffer The buffer which will be drawn to. This buffer will be
- // ready once displayFence fires.
+ // ready once drawFence fires.
+ // @param bufferFence Fence signalling that the buffer is ready to be drawn
+ // to.
// @param drawFence A pointer to a fence, which will fire when the buffer
// has been drawn to and is ready to be examined. The fence will be
// initialized by this method. The caller will be responsible for owning the
@@ -176,7 +178,8 @@
// now, this always returns NO_ERROR.
virtual status_t drawLayers(const DisplaySettings& display,
const std::vector<LayerSettings>& layers,
- ANativeWindowBuffer* buffer, base::unique_fd* drawFence) = 0;
+ ANativeWindowBuffer* buffer, base::unique_fd&& bufferFence,
+ base::unique_fd* drawFence) = 0;
protected:
// Gets a framebuffer to render to. This framebuffer may or may not be
diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h
index 800eac3..5956c46 100644
--- a/libs/renderengine/include/renderengine/mock/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h
@@ -78,9 +78,9 @@
MOCK_CONST_METHOD0(isProtected, bool());
MOCK_CONST_METHOD0(supportsProtectedContent, bool());
MOCK_METHOD1(useProtectedContext, bool(bool));
- MOCK_METHOD4(drawLayers,
+ MOCK_METHOD5(drawLayers,
status_t(const DisplaySettings&, const std::vector<LayerSettings>&,
- ANativeWindowBuffer*, base::unique_fd*));
+ ANativeWindowBuffer*, base::unique_fd&&, base::unique_fd*));
};
} // namespace mock
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index f82beeb..f28f672 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -105,7 +105,8 @@
std::vector<renderengine::LayerSettings> layers,
sp<GraphicBuffer> buffer) {
base::unique_fd fence;
- status_t status = sRE->drawLayers(settings, layers, buffer->getNativeBuffer(), &fence);
+ status_t status = sRE->drawLayers(settings, layers, buffer->getNativeBuffer(),
+ base::unique_fd(), &fence);
int fd = fence.release();
if (fd >= 0) {
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index f487dfa..79958ec 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -15,6 +15,7 @@
*/
#define LOG_TAG "GraphicBuffer"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <ui/GraphicBuffer.h>
@@ -29,6 +30,7 @@
#include <ui/Gralloc2.h>
#include <ui/GraphicBufferAllocator.h>
#include <ui/GraphicBufferMapper.h>
+#include <utils/Trace.h>
namespace android {
@@ -111,6 +113,7 @@
GraphicBuffer::~GraphicBuffer()
{
+ ATRACE_CALL();
if (handle) {
free_handle();
}
diff --git a/services/gpuservice/Android.bp b/services/gpuservice/Android.bp
index e21d8e7..2e8571a 100644
--- a/services/gpuservice/Android.bp
+++ b/services/gpuservice/Android.bp
@@ -29,6 +29,7 @@
"frameworks/native/vulkan/include",
],
shared_libs: [
+ "libbase",
"libbinder",
"libcutils",
"libgraphicsenv",
@@ -37,6 +38,7 @@
"libvulkan",
],
static_libs: [
+ "libserviceutils",
"libvkjson",
],
}
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index 81b70c0..70dd904 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -18,8 +18,12 @@
#include "GpuService.h"
+#include <android-base/stringprintf.h>
+#include <binder/IPCThreadState.h>
#include <binder/IResultReceiver.h>
#include <binder/Parcel.h>
+#include <binder/PermissionCache.h>
+#include <private/android_filesystem_config.h>
#include <utils/String8.h>
#include <utils/Trace.h>
@@ -27,11 +31,14 @@
namespace android {
+using base::StringAppendF;
namespace {
- status_t cmd_help(int out);
- status_t cmd_vkjson(int out, int err);
-}
+status_t cmdHelp(int out);
+status_t cmdVkjson(int out, int err);
+} // namespace
+
+const String16 sDump("android.permission.DUMP");
const char* const GpuService::SERVICE_NAME = "gpu";
@@ -39,7 +46,7 @@
void GpuService::setGpuStats(const std::string& driverPackageName,
const std::string& driverVersionName, uint64_t driverVersionCode,
- const std::string& driverBuildDate, const std::string& appPackageName,
+ int64_t driverBuildTime, const std::string& appPackageName,
GraphicsEnv::Driver driver, bool isDriverLoaded,
int64_t driverLoadingTime) {
ATRACE_CALL();
@@ -48,15 +55,14 @@
ALOGV("Received:\n"
"\tdriverPackageName[%s]\n"
"\tdriverVersionName[%s]\n"
- "\tdriverVersionCode[%llu]\n"
- "\tdriverBuildDate[%s]\n"
+ "\tdriverVersionCode[%" PRIu64 "]\n"
+ "\tdriverBuildTime[%" PRId64 "]\n"
"\tappPackageName[%s]\n"
"\tdriver[%d]\n"
"\tisDriverLoaded[%d]\n"
- "\tdriverLoadingTime[%lld]",
- driverPackageName.c_str(), driverVersionName.c_str(),
- (unsigned long long)driverVersionCode, driverBuildDate.c_str(), appPackageName.c_str(),
- static_cast<int32_t>(driver), isDriverLoaded, (long long)driverLoadingTime);
+ "\tdriverLoadingTime[%" PRId64 "]",
+ driverPackageName.c_str(), driverVersionName.c_str(), driverVersionCode, driverBuildTime,
+ appPackageName.c_str(), static_cast<int32_t>(driver), isDriverLoaded, driverLoadingTime);
}
status_t GpuService::shellCommand(int /*in*/, int out, int err, std::vector<String16>& args) {
@@ -67,28 +73,42 @@
ALOGV(" arg[%zu]: '%s'", i, String8(args[i]).string());
if (args.size() >= 1) {
- if (args[0] == String16("vkjson"))
- return cmd_vkjson(out, err);
- if (args[0] == String16("help"))
- return cmd_help(out);
+ if (args[0] == String16("vkjson")) return cmdVkjson(out, err);
+ if (args[0] == String16("help")) return cmdHelp(out);
}
// no command, or unrecognized command
- cmd_help(err);
+ cmdHelp(err);
return BAD_VALUE;
}
+status_t GpuService::doDump(int fd, const Vector<String16>& /*args*/, bool /*asProto*/) {
+ std::string result;
+
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+
+ if ((uid != AID_SHELL) && !PermissionCache::checkPermission(sDump, pid, uid)) {
+ StringAppendF(&result, "Permission Denial: can't dump gpu from pid=%d, uid=%d\n", pid, uid);
+ } else {
+ result.append("Hello world from dumpsys gpu.\n");
+ }
+
+ write(fd, result.c_str(), result.size());
+ return NO_ERROR;
+}
+
namespace {
-status_t cmd_help(int out) {
+status_t cmdHelp(int out) {
FILE* outs = fdopen(out, "w");
if (!outs) {
- ALOGE("vkjson: failed to create out stream: %s (%d)", strerror(errno),
- errno);
+ ALOGE("vkjson: failed to create out stream: %s (%d)", strerror(errno), errno);
return BAD_VALUE;
}
fprintf(outs,
- "GPU Service commands:\n"
- " vkjson dump Vulkan properties as JSON\n");
+ "GPU Service commands:\n"
+ " vkjson dump Vulkan properties as JSON\n");
fclose(outs);
return NO_ERROR;
}
@@ -99,7 +119,7 @@
fputc('\n', out);
}
-status_t cmd_vkjson(int out, int /*err*/) {
+status_t cmdVkjson(int out, int /*err*/) {
FILE* outs = fdopen(out, "w");
if (!outs) {
int errnum = errno;
diff --git a/services/gpuservice/GpuService.h b/services/gpuservice/GpuService.h
index 76234a3..7216035 100644
--- a/services/gpuservice/GpuService.h
+++ b/services/gpuservice/GpuService.h
@@ -20,13 +20,14 @@
#include <binder/IInterface.h>
#include <cutils/compiler.h>
#include <graphicsenv/IGpuService.h>
+#include <serviceutils/PriorityDumper.h>
#include <mutex>
#include <vector>
namespace android {
-class GpuService : public BnGpuService {
+class GpuService : public BnGpuService, public PriorityDumper {
public:
static const char* const SERVICE_NAME ANDROID_API;
@@ -36,12 +37,36 @@
status_t shellCommand(int in, int out, int err, std::vector<String16>& args) override;
private:
- // IGpuService interface
+ /*
+ * IGpuService interface
+ */
void setGpuStats(const std::string& driverPackageName, const std::string& driverVersionName,
- uint64_t driverVersionCode, const std::string& driverBuildDate,
+ uint64_t driverVersionCode, int64_t driverBuildTime,
const std::string& appPackageName, GraphicsEnv::Driver driver,
bool isDriverLoaded, int64_t driverLoadingTime);
+ /*
+ * IBinder interface
+ */
+ status_t dump(int fd, const Vector<String16>& args) override { return priorityDump(fd, args); }
+
+ /*
+ * Debugging & dumpsys
+ */
+ status_t dumpCritical(int fd, const Vector<String16>& /*args*/, bool asProto) override {
+ return doDump(fd, Vector<String16>(), asProto);
+ }
+
+ status_t dumpAll(int fd, const Vector<String16>& args, bool asProto) override {
+ return doDump(fd, args, asProto);
+ }
+
+ status_t doDump(int fd, const Vector<String16>& args, bool asProto);
+
+ /*
+ * Attributes
+ */
+
// GpuStats access must be protected by mStateLock
std::mutex mStateLock;
};
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 2ffd0a8..d288736 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -3072,7 +3072,7 @@
* For removed handle, check if need to send a cancel event if already in touch.
*/
void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle>>& inputWindowHandles,
- int32_t displayId) {
+ int32_t displayId, const sp<ISetInputWindowsListener>& setInputWindowsListener) {
#if DEBUG_FOCUS
ALOGD("setInputWindows displayId=%" PRId32, displayId);
#endif
@@ -3222,6 +3222,10 @@
// Wake up poll loop since it may need to make new input dispatching choices.
mLooper->wake();
+
+ if (setInputWindowsListener) {
+ setInputWindowsListener->onSetInputWindowsFinished();
+ }
}
void InputDispatcher::setFocusedApplication(
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index ecfeb6c..9d8919b 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -21,6 +21,7 @@
#include <input/InputApplication.h>
#include <input/InputTransport.h>
#include <input/InputWindow.h>
+#include <input/ISetInputWindowsListener.h>
#include <utils/KeyedVector.h>
#include <utils/Vector.h>
#include <utils/threads.h>
@@ -39,7 +40,6 @@
#include "InputListener.h"
#include "InputReporterInterface.h"
-
namespace android {
/*
@@ -315,7 +315,8 @@
* This method may be called on any thread (usually by the input manager).
*/
virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles,
- int32_t displayId) = 0;
+ int32_t displayId,
+ const sp<ISetInputWindowsListener>& setInputWindowsListener = nullptr) = 0;
/* Sets the focused application on the given display.
*
@@ -406,7 +407,8 @@
uint32_t policyFlags);
virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles,
- int32_t displayId);
+ int32_t displayId,
+ const sp<ISetInputWindowsListener>& setInputWindowsListener = nullptr);
virtual void setFocusedApplication(int32_t displayId,
const sp<InputApplicationHandle>& inputApplicationHandle);
virtual void setFocusedDisplay(int32_t displayId);
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index a7fd9ba..b0157a1 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -103,7 +103,8 @@
}
};
-void InputManager::setInputWindows(const Vector<InputWindowInfo>& infos) {
+void InputManager::setInputWindows(const Vector<InputWindowInfo>& infos,
+ const sp<ISetInputWindowsListener>& setInputWindowsListener) {
std::unordered_map<int32_t, Vector<sp<InputWindowHandle>>> handlesPerDisplay;
Vector<sp<InputWindowHandle>> handles;
@@ -112,7 +113,7 @@
handlesPerDisplay[info.displayId].add(new BinderWindowHandle(info));
}
for (auto const& i : handlesPerDisplay) {
- mDispatcher->setInputWindows(i.second, i.first);
+ mDispatcher->setInputWindows(i.second, i.first, setInputWindowsListener);
}
}
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index e632da3..ff9a080 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -29,6 +29,7 @@
#include <input/Input.h>
#include <input/InputTransport.h>
+#include <input/ISetInputWindowsListener.h>
#include <input/IInputFlinger.h>
#include <utils/Errors.h>
@@ -93,7 +94,8 @@
virtual sp<InputClassifierInterface> getClassifier();
virtual sp<InputDispatcherInterface> getDispatcher();
- virtual void setInputWindows(const Vector<InputWindowInfo>& handles);
+ virtual void setInputWindows(const Vector<InputWindowInfo>& handles,
+ const sp<ISetInputWindowsListener>& setInputWindowsListener);
virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken);
virtual void registerInputChannel(const sp<InputChannel>& channel);
diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h
index 9d0be95..a00b5fb 100644
--- a/services/inputflinger/host/InputFlinger.h
+++ b/services/inputflinger/host/InputFlinger.h
@@ -24,6 +24,7 @@
#include <cutils/compiler.h>
#include <input/IInputFlinger.h>
+#include <input/ISetInputWindowsListener.h>
#include <utils/String8.h>
#include <utils/String16.h>
#include <utils/StrongPointer.h>
@@ -39,7 +40,7 @@
InputFlinger() ANDROID_API;
virtual status_t dump(int fd, const Vector<String16>& args);
- void setInputWindows(const Vector<InputWindowInfo>&) {}
+ void setInputWindows(const Vector<InputWindowInfo>&, const sp<ISetInputWindowsListener>&) {}
void transferTouchFocus(const sp<IBinder>&, const sp<IBinder>&) {}
void registerInputChannel(const sp<InputChannel>&) {}
void unregisterInputChannel(const sp<InputChannel>&) {}
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 734ed6c..3304fd1 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -142,6 +142,7 @@
"MonitoredProducer.cpp",
"NativeWindowSurface.cpp",
"RenderArea.cpp",
+ "RegionSamplingThread.cpp",
"Scheduler/DispSync.cpp",
"Scheduler/DispSyncSource.cpp",
"Scheduler/EventControlThread.cpp",
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index b3e2a4b..96c4992 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -397,9 +397,11 @@
void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
// Add this buffer from our internal queue tracker
{ // Autolock scope
- // Report the requested present time to the Scheduler.
- mFlinger->mScheduler->addFramePresentTimeForLayer(item.mTimestamp, item.mIsAutoTimestamp,
- mName.c_str());
+ if (mFlinger->mUse90Hz && mFlinger->mUseSmart90ForVideo) {
+ // Report the requested present time to the Scheduler, if the feature is turned on.
+ mFlinger->mScheduler->addFramePresentTimeForLayer(item.mTimestamp,
+ item.mIsAutoTimestamp, mName.c_str());
+ }
Mutex::Autolock lock(mQueueItemLock);
// Reset the frame number tracker when we receive the first buffer after
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index e48c41e..f6b69eb 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -198,7 +198,6 @@
mReleasePreviousBuffer = true;
}
- mCurrentState.sequence++;
mCurrentState.buffer = buffer;
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
@@ -217,7 +216,6 @@
bool BufferStateLayer::setDataspace(ui::Dataspace dataspace) {
if (mCurrentState.dataspace == dataspace) return false;
- mCurrentState.sequence++;
mCurrentState.dataspace = dataspace;
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
index 2009380..e69b99f 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
@@ -71,7 +71,7 @@
virtual status_t prepareFrame() = 0;
// Allocates a buffer as scratch space for GPU composition
- virtual sp<GraphicBuffer> dequeueBuffer() = 0;
+ virtual sp<GraphicBuffer> dequeueBuffer(base::unique_fd* bufferFence) = 0;
// Queues the drawn buffer for consumption by HWC. readyFence is the fence
// which will fire when the buffer is ready for consumption.
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
index 58b13ed..3c79084 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
@@ -52,7 +52,7 @@
void setProtected(bool useProtected) override;
status_t beginFrame(bool mustRecompose) override;
status_t prepareFrame() override;
- sp<GraphicBuffer> dequeueBuffer() override;
+ sp<GraphicBuffer> dequeueBuffer(base::unique_fd* bufferFence) override;
void queueBuffer(base::unique_fd&& readyFence) override;
void onPresentDisplayCompleted() override;
void setViewportAndProjection() override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
index 8442bef..1562f58 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
@@ -37,7 +37,7 @@
MOCK_METHOD1(setBufferDataspace, void(ui::Dataspace));
MOCK_METHOD1(beginFrame, status_t(bool mustRecompose));
MOCK_METHOD0(prepareFrame, status_t());
- MOCK_METHOD0(dequeueBuffer, sp<GraphicBuffer>());
+ MOCK_METHOD1(dequeueBuffer, sp<GraphicBuffer>(base::unique_fd*));
MOCK_METHOD1(queueBuffer, void(base::unique_fd&&));
MOCK_METHOD0(onPresentDisplayCompleted, void());
MOCK_METHOD0(setViewportAndProjection, void());
diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
index ebb1bc2..b4dfba1 100644
--- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
#include <android-base/stringprintf.h>
#include <android/native_window.h>
#include <compositionengine/CompositionEngine.h>
@@ -28,6 +30,7 @@
#include <system/window.h>
#include <ui/GraphicBuffer.h>
#include <ui/Rect.h>
+#include <utils/Trace.h>
#include "DisplayHardware/HWComposer.h"
@@ -127,7 +130,8 @@
return mDisplaySurface->prepareFrame(compositionType);
}
-sp<GraphicBuffer> RenderSurface::dequeueBuffer() {
+sp<GraphicBuffer> RenderSurface::dequeueBuffer(base::unique_fd* bufferFence) {
+ ATRACE_CALL();
int fd = -1;
ANativeWindowBuffer* buffer = nullptr;
@@ -145,13 +149,7 @@
mGraphicBuffer->getNativeBuffer()->handle);
mGraphicBuffer = GraphicBuffer::from(buffer);
- // Block until the buffer is ready
- // TODO(alecmouri): it's perhaps more appropriate to block renderengine so
- // that the gl driver can block instead.
- if (fd >= 0) {
- sync_wait(fd, -1);
- close(fd);
- }
+ *bufferFence = base::unique_fd(fd);
return mGraphicBuffer;
}
@@ -172,7 +170,8 @@
// We shouldn't deadlock here, since mGraphicBuffer == nullptr only
// after a successful call to queueBuffer, or if dequeueBuffer has
// never been called.
- dequeueBuffer();
+ base::unique_fd unused;
+ dequeueBuffer(&unused);
}
if (mGraphicBuffer == nullptr) {
diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
index 0a7c462..84af9b9 100644
--- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
@@ -358,7 +358,8 @@
.WillOnce(
DoAll(SetArgPointee<0>(buffer.get()), SetArgPointee<1>(-1), Return(NO_ERROR)));
- EXPECT_EQ(buffer.get(), mSurface.dequeueBuffer().get());
+ base::unique_fd fence;
+ EXPECT_EQ(buffer.get(), mSurface.dequeueBuffer(&fence).get());
EXPECT_EQ(buffer.get(), mSurface.mutableGraphicBufferForTest().get());
}
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index daef7c6..b7aa5a5 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1338,10 +1338,8 @@
return true;
}
-bool Layer::setMetadata(LayerMetadata data) {
- bool changed = data.mMap != mCurrentState.metadata.mMap;
- if (!changed) return false;
- mCurrentState.metadata = std::move(data);
+bool Layer::setMetadata(const LayerMetadata& data) {
+ if (!mCurrentState.metadata.merge(data, true /* eraseEmpty */)) return false;
mCurrentState.sequence++;
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 1375a39..fcec262 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -292,7 +292,7 @@
uint64_t frameNumber);
virtual void deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber);
virtual bool setOverrideScalingMode(int32_t overrideScalingMode);
- virtual bool setMetadata(LayerMetadata data);
+ virtual bool setMetadata(const LayerMetadata& data);
virtual bool reparentChildren(const sp<IBinder>& layer);
virtual void setChildrenDrawingParent(const sp<Layer>& layer);
virtual bool reparent(const sp<IBinder>& newParentHandle);
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
new file mode 100644
index 0000000..cbc7ada
--- /dev/null
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#undef LOG_TAG
+#define LOG_TAG "RegionSamplingThread"
+
+#include "RegionSamplingThread.h"
+
+#include <gui/IRegionSamplingListener.h>
+#include <utils/Trace.h>
+
+#include "DisplayDevice.h"
+#include "Layer.h"
+#include "SurfaceFlinger.h"
+
+namespace android {
+
+template <typename T>
+struct SpHash {
+ size_t operator()(const sp<T>& p) const { return std::hash<T*>()(p.get()); }
+};
+
+RegionSamplingThread::RegionSamplingThread(SurfaceFlinger& flinger) : mFlinger(flinger) {
+ std::lock_guard threadLock(mThreadMutex);
+ mThread = std::thread([this]() { threadMain(); });
+ pthread_setname_np(mThread.native_handle(), "RegionSamplingThread");
+}
+
+RegionSamplingThread::~RegionSamplingThread() {
+ {
+ std::lock_guard lock(mMutex);
+ mRunning = false;
+ mCondition.notify_one();
+ }
+
+ std::lock_guard threadLock(mThreadMutex);
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+}
+
+void RegionSamplingThread::addListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle,
+ const sp<IRegionSamplingListener>& listener) {
+ wp<Layer> stopLayer = stopLayerHandle != nullptr
+ ? static_cast<Layer::Handle*>(stopLayerHandle.get())->owner
+ : nullptr;
+
+ sp<IBinder> asBinder = IInterface::asBinder(listener);
+ asBinder->linkToDeath(this);
+ std::lock_guard lock(mMutex);
+ mDescriptors.emplace(wp<IBinder>(asBinder), Descriptor{samplingArea, stopLayer, listener});
+}
+
+void RegionSamplingThread::removeListener(const sp<IRegionSamplingListener>& listener) {
+ std::lock_guard lock(mMutex);
+ mDescriptors.erase(wp<IBinder>(IInterface::asBinder(listener)));
+}
+
+void RegionSamplingThread::sampleNow() {
+ std::lock_guard lock(mMutex);
+ mSampleRequested = true;
+ mCondition.notify_one();
+}
+
+void RegionSamplingThread::binderDied(const wp<IBinder>& who) {
+ std::lock_guard lock(mMutex);
+ mDescriptors.erase(who);
+}
+
+namespace {
+// Using Rec. 709 primaries
+float getLuma(float r, float g, float b) {
+ constexpr auto rec709_red_primary = 0.2126f;
+ constexpr auto rec709_green_primary = 0.7152f;
+ constexpr auto rec709_blue_primary = 0.0722f;
+ return rec709_red_primary * r + rec709_green_primary * g + rec709_blue_primary * b;
+}
+
+float sampleArea(const uint32_t* data, int32_t stride, const Rect& area) {
+ std::array<int32_t, 256> brightnessBuckets = {};
+ const int32_t majoritySampleNum = area.getWidth() * area.getHeight() / 2;
+
+ for (int32_t row = area.top; row < area.bottom; ++row) {
+ const uint32_t* rowBase = data + row * stride;
+ for (int32_t column = area.left; column < area.right; ++column) {
+ uint32_t pixel = rowBase[column];
+ const float r = (pixel & 0xFF) / 255.0f;
+ const float g = ((pixel >> 8) & 0xFF) / 255.0f;
+ const float b = ((pixel >> 16) & 0xFF) / 255.0f;
+ const uint8_t luma = std::round(getLuma(r, g, b) * 255.0f);
+ ++brightnessBuckets[luma];
+ if (brightnessBuckets[luma] > majoritySampleNum) return luma / 255.0f;
+ }
+ }
+
+ int32_t accumulated = 0;
+ size_t bucket = 0;
+ while (bucket++ < brightnessBuckets.size()) {
+ accumulated += brightnessBuckets[bucket];
+ if (accumulated > majoritySampleNum) break;
+ }
+
+ return bucket / 255.0f;
+}
+} // anonymous namespace
+
+std::vector<float> sampleBuffer(const sp<GraphicBuffer>& buffer, const Point& leftTop,
+ const std::vector<RegionSamplingThread::Descriptor>& descriptors) {
+ void* data_raw = nullptr;
+ buffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, &data_raw);
+ std::shared_ptr<uint32_t> data(reinterpret_cast<uint32_t*>(data_raw),
+ [&buffer](auto) { buffer->unlock(); });
+ if (!data) return {};
+
+ const int32_t stride = buffer->getStride();
+ std::vector<float> lumas(descriptors.size());
+ std::transform(descriptors.begin(), descriptors.end(), lumas.begin(),
+ [&](auto const& descriptor) {
+ return sampleArea(data.get(), stride, descriptor.area - leftTop);
+ });
+ return lumas;
+}
+
+void RegionSamplingThread::captureSample() {
+ ATRACE_CALL();
+
+ if (mDescriptors.empty()) {
+ return;
+ }
+
+ std::vector<RegionSamplingThread::Descriptor> descriptors;
+ Region sampleRegion;
+ for (const auto& [listener, descriptor] : mDescriptors) {
+ sampleRegion.orSelf(descriptor.area);
+ descriptors.emplace_back(descriptor);
+ }
+
+ Rect sampledArea = sampleRegion.bounds();
+
+ sp<const DisplayDevice> device = mFlinger.getDefaultDisplayDevice();
+ DisplayRenderArea renderArea(device, sampledArea, sampledArea.getWidth(),
+ sampledArea.getHeight(), ui::Dataspace::V0_SRGB,
+ ui::Transform::ROT_0);
+
+ std::unordered_set<sp<IRegionSamplingListener>, SpHash<IRegionSamplingListener>> listeners;
+
+ auto traverseLayers = [&](const LayerVector::Visitor& visitor) {
+ bool stopLayerFound = false;
+ auto filterVisitor = [&](Layer* layer) {
+ // We don't want to capture any layers beyond the stop layer
+ if (stopLayerFound) return;
+
+ // Likewise if we just found a stop layer, set the flag and abort
+ for (const auto& [area, stopLayer, listener] : descriptors) {
+ if (layer == stopLayer.promote().get()) {
+ stopLayerFound = true;
+ return;
+ }
+ }
+
+ // Compute the layer's position on the screen
+ Rect bounds = Rect(layer->getBounds());
+ ui::Transform transform = layer->getTransform();
+ constexpr bool roundOutwards = true;
+ Rect transformed = transform.transform(bounds, roundOutwards);
+
+ // If this layer doesn't intersect with the larger sampledArea, skip capturing it
+ Rect ignore;
+ if (!transformed.intersect(sampledArea, &ignore)) return;
+
+ // If the layer doesn't intersect a sampling area, skip capturing it
+ bool intersectsAnyArea = false;
+ for (const auto& [area, stopLayer, listener] : descriptors) {
+ if (transformed.intersect(area, &ignore)) {
+ intersectsAnyArea = true;
+ listeners.insert(listener);
+ }
+ }
+ if (!intersectsAnyArea) return;
+
+ ALOGV("Traversing [%s] [%d, %d, %d, %d]", layer->getName().string(), bounds.left,
+ bounds.top, bounds.right, bounds.bottom);
+ visitor(layer);
+ };
+ mFlinger.traverseLayersInDisplay(device, filterVisitor);
+ };
+
+ const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER;
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(sampledArea.getWidth(), sampledArea.getHeight(),
+ PIXEL_FORMAT_RGBA_8888, 1, usage, "RegionSamplingThread");
+
+ // When calling into SF, we post a message into the SF message queue (so the
+ // screen capture runs on the main thread). This message blocks until the
+ // screenshot is actually captured, but before the capture occurs, the main
+ // thread may perform a normal refresh cycle. At the end of this cycle, it
+ // can request another sample (because layers changed), which triggers a
+ // call into sampleNow. When sampleNow attempts to grab the mutex, we can
+ // deadlock.
+ //
+ // To avoid this, we drop the mutex while we call into SF.
+ mMutex.unlock();
+ mFlinger.captureScreenCore(renderArea, traverseLayers, buffer, false);
+ mMutex.lock();
+
+ std::vector<Descriptor> activeDescriptors;
+ for (const auto& descriptor : descriptors) {
+ if (listeners.count(descriptor.listener) != 0) {
+ activeDescriptors.emplace_back(descriptor);
+ }
+ }
+
+ ALOGV("Sampling %zu descriptors", activeDescriptors.size());
+ std::vector<float> lumas = sampleBuffer(buffer, sampledArea.leftTop(), activeDescriptors);
+
+ if (lumas.size() != activeDescriptors.size()) {
+ return;
+ }
+
+ for (size_t d = 0; d < activeDescriptors.size(); ++d) {
+ activeDescriptors[d].listener->onSampleCollected(lumas[d]);
+ }
+}
+
+void RegionSamplingThread::threadMain() {
+ std::lock_guard lock(mMutex);
+ while (mRunning) {
+ if (mSampleRequested) {
+ mSampleRequested = false;
+ captureSample();
+ }
+ mCondition.wait(mMutex,
+ [this]() REQUIRES(mMutex) { return mSampleRequested || !mRunning; });
+ }
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/RegionSamplingThread.h b/services/surfaceflinger/RegionSamplingThread.h
new file mode 100644
index 0000000..bf59007
--- /dev/null
+++ b/services/surfaceflinger/RegionSamplingThread.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <condition_variable>
+#include <mutex>
+#include <thread>
+#include <unordered_map>
+
+#include <android-base/thread_annotations.h>
+#include <binder/IBinder.h>
+#include <ui/Rect.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+class GraphicBuffer;
+class IRegionSamplingListener;
+class Layer;
+class SurfaceFlinger;
+
+class RegionSamplingThread : public IBinder::DeathRecipient {
+public:
+ explicit RegionSamplingThread(SurfaceFlinger& flinger);
+ ~RegionSamplingThread();
+
+ void addListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle,
+ const sp<IRegionSamplingListener>& listener);
+ void removeListener(const sp<IRegionSamplingListener>& listener);
+ void sampleNow();
+
+ struct Descriptor {
+ Rect area = Rect::EMPTY_RECT;
+ wp<Layer> stopLayer;
+ sp<IRegionSamplingListener> listener;
+ };
+
+ struct WpHash {
+ size_t operator()(const wp<IBinder>& p) const {
+ return std::hash<IBinder*>()(p.unsafe_get());
+ }
+ };
+
+private:
+ void binderDied(const wp<IBinder>& who) override;
+
+ void captureSample() REQUIRES(mMutex);
+ void threadMain();
+
+ SurfaceFlinger& mFlinger;
+
+ std::mutex mThreadMutex;
+ std::thread mThread GUARDED_BY(mThreadMutex);
+
+ std::mutex mMutex;
+ std::condition_variable_any mCondition;
+ bool mRunning GUARDED_BY(mMutex) = true;
+ bool mSampleRequested GUARDED_BY(mMutex) = false;
+
+ std::unordered_map<wp<IBinder>, Descriptor, WpHash> mDescriptors GUARDED_BY(mMutex);
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 8ed3958..4f846db 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -299,6 +299,7 @@
}
void Scheduler::incrementFrameCounter() {
+ std::lock_guard<std::mutex> lock(mLayerHistoryLock);
mLayerHistory.incrementCounter();
}
@@ -323,25 +324,28 @@
void Scheduler::determineLayerTimestampStats(const std::string layerName,
const nsecs_t framePresentTime) {
- mLayerHistory.insert(layerName, framePresentTime);
std::vector<int64_t> differencesMs;
-
- // Traverse through the layer history, and determine the differences in present times.
- nsecs_t newestPresentTime = framePresentTime;
std::string differencesText = "";
- for (int i = 1; i < mLayerHistory.getSize(); i++) {
- std::unordered_map<std::string, nsecs_t> layers = mLayerHistory.get(i);
- for (auto layer : layers) {
- if (layer.first != layerName) {
- continue;
+ {
+ std::lock_guard<std::mutex> lock(mLayerHistoryLock);
+ mLayerHistory.insert(layerName, framePresentTime);
+
+ // Traverse through the layer history, and determine the differences in present times.
+ nsecs_t newestPresentTime = framePresentTime;
+ for (int i = 1; i < mLayerHistory.getSize(); i++) {
+ std::unordered_map<std::string, nsecs_t> layers = mLayerHistory.get(i);
+ for (auto layer : layers) {
+ if (layer.first != layerName) {
+ continue;
+ }
+ int64_t differenceMs = (newestPresentTime - layer.second) / 1000000;
+ // Dismiss noise.
+ if (differenceMs > 10 && differenceMs < 60) {
+ differencesMs.push_back(differenceMs);
+ }
+ IF_ALOGV() { differencesText += (std::to_string(differenceMs) + " "); }
+ newestPresentTime = layer.second;
}
- int64_t differenceMs = (newestPresentTime - layer.second) / 1000000;
- // Dismiss noise.
- if (differenceMs > 10 && differenceMs < 60) {
- differencesMs.push_back(differenceMs);
- }
- IF_ALOGV() { differencesText += (std::to_string(differenceMs) + " "); }
- newestPresentTime = layer.second;
}
}
ALOGV("Layer %s timestamp intervals: %s", layerName.c_str(), differencesText.c_str());
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index ce5c87e..c566922 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -201,7 +201,10 @@
std::array<int64_t, scheduler::ARRAY_SIZE> mTimeDifferences{};
size_t mCounter = 0;
- LayerHistory mLayerHistory;
+ // DetermineLayerTimestampStats is called from BufferQueueLayer::onFrameAvailable which
+ // can run on any thread, and cause failure.
+ std::mutex mLayerHistoryLock;
+ LayerHistory mLayerHistory GUARDED_BY(mLayerHistoryLock);
// Timer that records time between requests for next vsync. If the time is higher than a given
// interval, a callback is fired. Set this variable to >0 to use this feature.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e1e3dfb..df558e5 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -297,7 +297,9 @@
mNumLayers(0),
mVrFlingerRequestsDisplay(false),
mMainThreadId(std::this_thread::get_id()),
- mCompositionEngine{getFactory().createCompositionEngine()} {}
+ mCompositionEngine{getFactory().createCompositionEngine()} {
+ mSetInputWindowsListener = new SetInputWindowsListener(this);
+}
SurfaceFlinger::SurfaceFlinger(surfaceflinger::Factory& factory)
: SurfaceFlinger(factory, SkipInitialization) {
@@ -396,6 +398,12 @@
property_get("debug.sf.use_90Hz", value, "0");
mUse90Hz = atoi(value);
+ property_get("debug.sf.use_smart_90_for_video", value, "0");
+ mUseSmart90ForVideo = atoi(value);
+
+ property_get("debug.sf.luma_sampling", value, "1");
+ mLumaSampling = atoi(value);
+
const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
mVsyncModulator.setPhaseOffsets(early, gl, late);
@@ -576,9 +584,24 @@
LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
- postMessageAsync(new LambdaMessage([this] {
+ postMessageAsync(new LambdaMessage([this]() NO_THREAD_SAFETY_ANALYSIS {
readPersistentProperties();
mBootStage = BootStage::FINISHED;
+
+ // TODO(b/122905403): Once the display policy is completely integrated, this flag should go
+ // away and it should be controlled by flipping the switch in setting. The switch in
+ // settings should only be available to P19 devices, if they are opted into 90Hz fishfood.
+ // The boot must be complete before we can set the active config.
+
+ if (mUse90Hz) {
+ mPhaseOffsets->setRefreshRateType(
+ scheduler::RefreshRateConfigs::RefreshRateType::PERFORMANCE);
+ setRefreshRateTo(RefreshRateType::PERFORMANCE);
+ } else {
+ mPhaseOffsets->setRefreshRateType(
+ scheduler::RefreshRateConfigs::RefreshRateType::DEFAULT);
+ setRefreshRateTo(RefreshRateType::DEFAULT);
+ }
}));
}
@@ -635,11 +658,6 @@
mVsyncModulator.setSchedulerAndHandles(mScheduler.get(), mAppConnectionHandle.get(),
mSfConnectionHandle.get());
- if (mUse90Hz) {
- mPhaseOffsets->setRefreshRateType(
- scheduler::RefreshRateConfigs::RefreshRateType::PERFORMANCE);
- }
-
// Get a RenderEngine for the given display / config (can't fail)
int32_t renderEngineFeature = 0;
renderEngineFeature |= (useColorManagement ?
@@ -705,15 +723,16 @@
ALOGE("Run StartPropertySetThread failed!");
}
- mScheduler->setExpiredIdleTimerCallback([this] {
- Mutex::Autolock lock(mStateLock);
- setRefreshRateTo(RefreshRateType::DEFAULT);
- });
- mScheduler->setResetIdleTimerCallback([this] {
- Mutex::Autolock lock(mStateLock);
- setRefreshRateTo(RefreshRateType::PERFORMANCE);
- });
-
+ if (mUse90Hz) {
+ mScheduler->setExpiredIdleTimerCallback([this] {
+ Mutex::Autolock lock(mStateLock);
+ setRefreshRateTo(RefreshRateType::DEFAULT);
+ });
+ mScheduler->setResetIdleTimerCallback([this] {
+ Mutex::Autolock lock(mStateLock);
+ setRefreshRateTo(RefreshRateType::PERFORMANCE);
+ });
+ }
mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(getHwComposer().getConfigs(
*display->getId()),
mTimeStats);
@@ -984,6 +1003,7 @@
}
bool SurfaceFlinger::performSetActiveConfig() NO_THREAD_SAFETY_ANALYSIS {
+ ATRACE_CALL();
// we may be in the process of changing the active state
if (mWaitForNextInvalidate) {
mWaitForNextInvalidate = false;
@@ -1291,17 +1311,20 @@
return NO_ERROR;
}
-status_t SurfaceFlinger::addRegionSamplingListener(
- const Rect& /*samplingArea*/, const sp<IBinder>& /*stopLayerHandle*/,
- const sp<IRegionSamplingListener>& /*listener*/) {
+status_t SurfaceFlinger::addRegionSamplingListener(const Rect& samplingArea,
+ const sp<IBinder>& stopLayerHandle,
+ const sp<IRegionSamplingListener>& listener) {
+ if (!listener) {
+ return BAD_VALUE;
+ }
+ mRegionSamplingThread->addListener(samplingArea, stopLayerHandle, listener);
return NO_ERROR;
}
-status_t SurfaceFlinger::removeRegionSamplingListener(
- const sp<IRegionSamplingListener>& /*listener*/) {
+status_t SurfaceFlinger::removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) {
+ mRegionSamplingThread->removeListener(listener);
return NO_ERROR;
}
-
// ----------------------------------------------------------------------------
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
@@ -1496,6 +1519,7 @@
}
void SurfaceFlinger::updateVrFlinger() {
+ ATRACE_CALL();
if (!mVrFlinger)
return;
bool vrFlingerRequestsDisplay = mVrFlingerRequestsDisplay;
@@ -1585,15 +1609,21 @@
break;
}
- // This call is made each time SF wakes up and creates a new frame.
- mScheduler->incrementFrameCounter();
-
- bool frameMissed = !mHadClientComposition && mPreviousPresentFence != Fence::NO_FENCE &&
+ if (mUse90Hz && mUseSmart90ForVideo) {
+ // This call is made each time SF wakes up and creates a new frame. It is part
+ // of video detection feature.
+ mScheduler->incrementFrameCounter();
+ }
+ bool frameMissed = mPreviousPresentFence != Fence::NO_FENCE &&
(mPreviousPresentFence->getStatus() == Fence::Status::Unsignaled);
- mFrameMissedCount += frameMissed;
- ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
+ bool hwcFrameMissed = !mHadClientComposition && frameMissed;
if (frameMissed) {
+ ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
+ mFrameMissedCount++;
mTimeStats->incrementMissedFrames();
+ }
+ // For now, only propagate backpressure when missing a hwc frame.
+ if (hwcFrameMissed) {
if (mPropagateBackpressure) {
signalLayerUpdate();
break;
@@ -1628,6 +1658,7 @@
}
bool SurfaceFlinger::handleMessageTransaction() {
+ ATRACE_CALL();
uint32_t transactionFlags = peekTransactionFlags();
// Apply any ready transactions in the queues if there are still transactions that have not been
@@ -2147,6 +2178,10 @@
mTransactionCompletedThread.addPresentFence(mPreviousPresentFence);
mTransactionCompletedThread.sendCallbacks();
+ if (mLumaSampling) {
+ mRegionSamplingThread->sampleNow();
+ }
+
ASSERT_ON_STACK_GUARD();
}
#pragma clang optimize on // b/119477596
@@ -2933,6 +2968,10 @@
if (mVisibleRegionsDirty || mInputInfoChanged) {
mInputInfoChanged = false;
updateInputWindowInfo();
+ } else if (mInputWindowCommands.syncInputWindows) {
+ // If the caller requested to sync input windows, but there are no
+ // changes to input windows, notify immediately.
+ setInputWindowsFinished();
}
executeInputWindowCommands();
@@ -2948,7 +2987,10 @@
inputHandles.add(layer->fillInputInfo());
}
});
- mInputFlinger->setInputWindows(inputHandles);
+
+ mInputFlinger->setInputWindows(inputHandles,
+ mInputWindowCommands.syncInputWindows ? mSetInputWindowsListener
+ : nullptr);
}
void SurfaceFlinger::commitInputWindowCommands() {
@@ -3301,12 +3343,12 @@
renderengine::DisplaySettings clientCompositionDisplay;
std::vector<renderengine::LayerSettings> clientCompositionLayers;
sp<GraphicBuffer> buf;
+ base::unique_fd fd;
if (hasClientComposition) {
ALOGV("hasClientComposition");
- buf = display->getRenderSurface()->dequeueBuffer();
-
+ buf = display->getRenderSurface()->dequeueBuffer(&fd);
if (buf == nullptr) {
ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
"client composition for this frame",
@@ -3327,7 +3369,6 @@
m[3][0] = displayTransform[2][0];
m[3][1] = displayTransform[2][1];
m[3][3] = displayTransform[2][2];
-
clientCompositionDisplay.globalTransform = m;
const auto* profile = display->getDisplayColorProfile();
@@ -3427,7 +3468,7 @@
}
}
getRenderEngine().drawLayers(clientCompositionDisplay, clientCompositionLayers,
- buf->getNativeBuffer(), readyFence);
+ buf->getNativeBuffer(), std::move(fd), readyFence);
}
return true;
}
@@ -3659,13 +3700,16 @@
if (flags & eAnimation) {
mAnimTransactionPending = true;
}
- while (mTransactionPending) {
+
+ mPendingSyncInputWindows = mPendingInputWindowCommands.syncInputWindows;
+ while (mTransactionPending || mPendingSyncInputWindows) {
status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
if (CC_UNLIKELY(err != NO_ERROR)) {
// just in case something goes wrong in SF, return to the
// called after a few seconds.
ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
mTransactionPending = false;
+ mPendingSyncInputWindows = false;
break;
}
}
@@ -4058,7 +4102,7 @@
}
}
- layer->setMetadata(std::move(metadata));
+ layer->setMetadata(metadata);
bool addToCurrentState = callingThreadHasUnscopedSurfaceFlingerAccess();
result = addClientLayer(client, *handle, *gbp, layer, *parent,
@@ -4455,7 +4499,9 @@
" present offset: %9" PRId64 " ns\t VSYNC period: %9" PRId64 " ns\n\n",
dispSyncPresentTimeOffset, getVsyncPeriod());
- StringAppendF(&result, "Scheduler enabled. 90Hz feature: %s\n\n", mUse90Hz ? "on" : "off");
+ StringAppendF(&result, "Scheduler enabled. 90Hz feature: %s\n", mUse90Hz ? "on" : "off");
+ StringAppendF(&result, "+ Smart 90 for video detection: %s\n\n",
+ mUseSmart90ForVideo ? "on" : "off");
mScheduler->dump(mAppConnectionHandle, result);
}
@@ -4907,8 +4953,7 @@
case GET_COLOR_MANAGEMENT:
case GET_COMPOSITION_PREFERENCE:
case GET_PROTECTED_CONTENT_SUPPORT:
- case IS_WIDE_COLOR_DISPLAY:
- case SET_INPUT_WINDOWS_FINISHED: {
+ case IS_WIDE_COLOR_DISPLAY: {
return OK;
}
case CAPTURE_LAYERS:
@@ -5440,6 +5485,13 @@
static_cast<android_pixel_format>(reqPixelFormat), 1,
usage, "screenshot");
+ return captureScreenCore(renderArea, traverseLayers, *outBuffer, useIdentityTransform);
+}
+
+status_t SurfaceFlinger::captureScreenCore(RenderArea& renderArea,
+ TraverseLayersFunction traverseLayers,
+ const sp<GraphicBuffer>& buffer,
+ bool useIdentityTransform) {
// This mutex protects syncFd and captureResult for communication of the return values from the
// main thread back to this Binder thread
std::mutex captureMutex;
@@ -5467,7 +5519,7 @@
{
Mutex::Autolock _l(mStateLock);
renderArea.render([&] {
- result = captureScreenImplLocked(renderArea, traverseLayers, (*outBuffer).get(),
+ result = captureScreenImplLocked(renderArea, traverseLayers, buffer.get(),
useIdentityTransform, forSystem, &fd);
});
}
@@ -5602,9 +5654,12 @@
});
clientCompositionDisplay.clearRegion = clearRegion;
+ // Use an empty fence for the buffer fence, since we just created the buffer so
+ // there is no need for synchronization with the GPU.
+ base::unique_fd bufferFence;
base::unique_fd drawFence;
getRenderEngine().drawLayers(clientCompositionDisplay, clientCompositionLayers, buffer,
- &drawFence);
+ std::move(bufferFence), &drawFence);
*outSyncFd = drawFence.release();
}
@@ -5634,7 +5689,12 @@
return NO_ERROR;
}
-void SurfaceFlinger::setInputWindowsFinished() {}
+void SurfaceFlinger::setInputWindowsFinished() {
+ Mutex::Autolock _l(mStateLock);
+
+ mPendingSyncInputWindows = false;
+ mTransactionCV.broadcast();
+}
// ---------------------------------------------------------------------------
@@ -5667,6 +5727,12 @@
}
}
+// ----------------------------------------------------------------------------
+
+void SetInputWindowsListener::onSetInputWindowsFinished() {
+ mFlinger->setInputWindowsFinished();
+}
+
}; // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 220e664..31b4fb6 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -33,6 +33,7 @@
#include <gui/LayerState.h>
#include <gui/OccupancyTracker.h>
#include <hardware/hwcomposer_defs.h>
+#include <input/ISetInputWindowsListener.h>
#include <layerproto/LayerProtoHeader.h>
#include <math/mat4.h>
#include <serviceutils/PriorityDumper.h>
@@ -56,6 +57,7 @@
#include "LayerBE.h"
#include "LayerStats.h"
#include "LayerVector.h"
+#include "RegionSamplingThread.h"
#include "Scheduler/DispSync.h"
#include "Scheduler/EventThread.h"
#include "Scheduler/MessageQueue.h"
@@ -201,6 +203,14 @@
std::map<wp<IBinder>, std::vector<CompositionInfo>> mEndOfFrameCompositionInfo;
};
+class SetInputWindowsListener : public BnSetInputWindowsListener {
+public:
+ SetInputWindowsListener(const sp<SurfaceFlinger>& flinger) : mFlinger(flinger) {}
+ void onSetInputWindowsFinished() override;
+
+private:
+ const sp<SurfaceFlinger> mFlinger;
+};
class SurfaceFlinger : public BnSurfaceComposer,
public PriorityDumper,
@@ -348,6 +358,8 @@
return mTransactionCompletedThread;
}
+ void setInputWindowsFinished();
+
private:
friend class Client;
friend class DisplayEventConnection;
@@ -357,6 +369,7 @@
friend class BufferQueueLayer;
friend class BufferStateLayer;
friend class MonitoredProducer;
+ friend class RegionSamplingThread;
// For unit tests
friend class TestableSurfaceFlinger;
@@ -477,7 +490,6 @@
status_t addRegionSamplingListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle,
const sp<IRegionSamplingListener>& listener) override;
status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) override;
- void setInputWindowsFinished() override;
/* ------------------------------------------------------------------------
* DeathRecipient interface
*/
@@ -623,6 +635,8 @@
status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers,
sp<GraphicBuffer>* outBuffer, const ui::PixelFormat reqPixelFormat,
bool useIdentityTransform);
+ status_t captureScreenCore(RenderArea& renderArea, TraverseLayersFunction traverseLayers,
+ const sp<GraphicBuffer>& buffer, bool useIdentityTransform);
status_t captureScreenImplLocked(const RenderArea& renderArea,
TraverseLayersFunction traverseLayers,
ANativeWindowBuffer* buffer, bool useIdentityTransform,
@@ -988,6 +1002,9 @@
TransactionCompletedThread mTransactionCompletedThread;
+ bool mLumaSampling = true;
+ sp<RegionSamplingThread> mRegionSamplingThread = new RegionSamplingThread(*this);
+
// Restrict layers to use two buffers in their bufferqueues.
bool mLayerTripleBufferingDisabled = false;
@@ -1075,6 +1092,7 @@
* Scheduler
*/
bool mUse90Hz = false;
+ bool mUseSmart90ForVideo = false;
std::unique_ptr<Scheduler> mScheduler;
sp<Scheduler::ConnectionHandle> mAppConnectionHandle;
sp<Scheduler::ConnectionHandle> mSfConnectionHandle;
@@ -1112,6 +1130,9 @@
InputWindowCommands mInputWindowCommands;
ui::DisplayPrimaries mInternalDisplayPrimaries;
+
+ sp<SetInputWindowsListener> mSetInputWindowsListener;
+ bool mPendingSyncInputWindows GUARDED_BY(mStateLock);
};
}; // namespace android
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index d0f7b90..6deec29 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -312,7 +312,7 @@
.WillRepeatedly(
[](const renderengine::DisplaySettings& displaySettings,
const std::vector<renderengine::LayerSettings>& /*layerSettings*/,
- ANativeWindowBuffer*, base::unique_fd*) -> status_t {
+ ANativeWindowBuffer*, base::unique_fd&&, base::unique_fd*) -> status_t {
EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
displaySettings.physicalDisplay);
@@ -351,7 +351,7 @@
.WillRepeatedly(
[](const renderengine::DisplaySettings& displaySettings,
const std::vector<renderengine::LayerSettings>& /*layerSettings*/,
- ANativeWindowBuffer*, base::unique_fd*) -> status_t {
+ ANativeWindowBuffer*, base::unique_fd&&, base::unique_fd*) -> status_t {
EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
displaySettings.physicalDisplay);
@@ -580,7 +580,8 @@
EXPECT_CALL(*test->mRenderEngine, drawLayers)
.WillOnce([](const renderengine::DisplaySettings& displaySettings,
const std::vector<renderengine::LayerSettings>& layerSettings,
- ANativeWindowBuffer*, base::unique_fd*) -> status_t {
+ ANativeWindowBuffer*, base::unique_fd&&,
+ base::unique_fd*) -> status_t {
EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
displaySettings.physicalDisplay);
@@ -624,7 +625,8 @@
EXPECT_CALL(*test->mRenderEngine, drawLayers)
.WillOnce([](const renderengine::DisplaySettings& displaySettings,
const std::vector<renderengine::LayerSettings>& layerSettings,
- ANativeWindowBuffer*, base::unique_fd*) -> status_t {
+ ANativeWindowBuffer*, base::unique_fd&&,
+ base::unique_fd*) -> status_t {
EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
displaySettings.physicalDisplay);
@@ -693,7 +695,8 @@
EXPECT_CALL(*test->mRenderEngine, drawLayers)
.WillOnce([](const renderengine::DisplaySettings& displaySettings,
const std::vector<renderengine::LayerSettings>& layerSettings,
- ANativeWindowBuffer*, base::unique_fd*) -> status_t {
+ ANativeWindowBuffer*, base::unique_fd&&,
+ base::unique_fd*) -> status_t {
EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
displaySettings.physicalDisplay);
diff --git a/services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp b/services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp
index 92c9f92..75a061b 100644
--- a/services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp
@@ -62,17 +62,6 @@
metadata.mMap[2] = std::vector<uint8_t>{'a', 'b'};
ASSERT_EQ(0, metadata.getInt32(2, 0));
- LayerMetadata second;
- std::vector<uint8_t> someData{'c', 'd', '\0'};
- second.mMap[2] = someData;
- second.setInt32(6, 5);
- metadata.merge(second);
-
- ASSERT_EQ(3, metadata.mMap.size());
- ASSERT_EQ(someData, second.mMap[2]);
- ASSERT_EQ(5, metadata.getInt32(6, 0));
- ASSERT_EQ(2, metadata.getInt32(4, 0));
-
Parcel p;
metadata.writeToParcel(&p);
LayerMetadata reconstructed;
@@ -82,5 +71,39 @@
ASSERT_EQ(metadata.mMap, reconstructed.mMap);
}
+TEST_F(LayerMetadataTest, merge) {
+ LayerMetadata metadata;
+ metadata.setInt32(4, 2);
+ metadata.mMap[2] = std::vector<uint8_t>{'a', 'b'};
+
+ LayerMetadata second;
+ std::vector<uint8_t> someData{'c', 'd', '\0'};
+ second.mMap[2] = someData;
+ second.setInt32(6, 5);
+ second.mMap[4].clear(); // will not delete if eraseEmpty is false
+ bool changed = metadata.merge(second);
+
+ ASSERT_TRUE(changed);
+ ASSERT_EQ(3, metadata.mMap.size());
+ ASSERT_EQ(someData, second.mMap[2]);
+ ASSERT_EQ(5, metadata.getInt32(6, 0));
+ ASSERT_TRUE(metadata.mMap.at(4).empty());
+
+ LayerMetadata withErase;
+ withErase.mMap[6].clear();
+ changed = metadata.merge(withErase, true /* eraseEmpty */);
+ ASSERT_TRUE(changed);
+ ASSERT_EQ(2, metadata.mMap.size());
+ ASSERT_EQ(someData, second.mMap[2]);
+ ASSERT_EQ(true, metadata.has(4));
+
+ // test for change detection
+ LayerMetadata third;
+ third.mMap[2] = someData;
+ third.mMap[5].clear();
+ changed = metadata.merge(third);
+ ASSERT_FALSE(changed);
+}
+
} // namespace
} // namespace android
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index b49d894..a7fd912 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -392,8 +392,8 @@
Status<void> ProducerChannel::OnProducerPost(Message&,
LocalFence acquire_fence) {
ATRACE_NAME("ProducerChannel::OnProducerPost");
- ALOGD("ProducerChannel::OnProducerPost: buffer_id=%d, state=0x%x",
- buffer_id(), buffer_state_->load(std::memory_order_acquire));
+ ALOGD_IF(TRACE, "%s: buffer_id=%d, state=0x%x", __FUNCTION__, buffer_id(),
+ buffer_state_->load(std::memory_order_acquire));
epoll_event event;
event.events = 0;
@@ -437,7 +437,7 @@
Status<LocalFence> ProducerChannel::OnProducerGain(Message& /*message*/) {
ATRACE_NAME("ProducerChannel::OnGain");
- ALOGW("ProducerChannel::OnGain: buffer_id=%d", buffer_id());
+ ALOGD_IF(TRACE, "%s: buffer_id=%d", __FUNCTION__, buffer_id());
ClearAvailable();
post_fence_.close();
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 32e19f7..73fc7b2 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -688,6 +688,8 @@
{VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
{VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
{VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
+ {VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
+ {VK_FORMAT_R16G16B16A16_SFLOAT, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
};
const uint32_t kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);
uint32_t total_num_formats = kNumFormats;