Merge "Add synchronous transaction to wait for setInputWindow to complete (3/n)"
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/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..6e5324e 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -158,24 +158,23 @@
 
 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 +263,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);
     }
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..2054426 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),
@@ -80,7 +80,7 @@
     void setDriverPath(const std::string path);
     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);
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/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/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index 81b70c0..ed56c49 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -39,7 +39,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 +48,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) {
diff --git a/services/gpuservice/GpuService.h b/services/gpuservice/GpuService.h
index 76234a3..389e695 100644
--- a/services/gpuservice/GpuService.h
+++ b/services/gpuservice/GpuService.h
@@ -38,7 +38,7 @@
 private:
     // 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);
 
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/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 bf17d50..3f2f79b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -398,6 +398,9 @@
     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);
+
     const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
     mVsyncModulator.setPhaseOffsets(early, gl, late);
 
@@ -578,9 +581,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);
+        }
     }));
 }
 
@@ -637,11 +655,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 ?
@@ -707,15 +720,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);
@@ -1587,8 +1601,11 @@
                 break;
             }
 
-            // This call is made each time SF wakes up and creates a new frame.
-            mScheduler->incrementFrameCounter();
+            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 = !mHadClientComposition && mPreviousPresentFence != Fence::NO_FENCE &&
                     (mPreviousPresentFence->getStatus() == Fence::Status::Unsignaled);
@@ -4460,7 +4477,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);
 }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index ee3933e..b240ebf 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1085,6 +1085,7 @@
      * Scheduler
      */
     bool mUse90Hz = false;
+    bool mUseSmart90ForVideo = false;
     std::unique_ptr<Scheduler> mScheduler;
     sp<Scheduler::ConnectionHandle> mAppConnectionHandle;
     sp<Scheduler::ConnectionHandle> mSfConnectionHandle;