Merge "Revert "Reduce AppFuse max read size."" into main
diff --git a/Android.bp b/Android.bp
index 6d70d4d..00d1382 100644
--- a/Android.bp
+++ b/Android.bp
@@ -62,7 +62,6 @@
         "libincfs",
         "libhidlbase",
         "libkeymint_support",
-        "libkeyutils",
         "liblog",
         "liblogwrap",
         "libselinux",
diff --git a/FsCrypt.cpp b/FsCrypt.cpp
index 9f6403c..51b35c5 100644
--- a/FsCrypt.cpp
+++ b/FsCrypt.cpp
@@ -44,13 +44,10 @@
 
 #include "android/os/IVold.h"
 
-#define MANAGE_MISC_DIRS 0
-
 #include <cutils/fs.h>
 #include <cutils/properties.h>
 
 #include <fscrypt/fscrypt.h>
-#include <keyutils.h>
 #include <libdm/dm.h>
 
 #include <android-base/file.h>
@@ -76,7 +73,6 @@
 using android::vold::SetDefaultAcl;
 using android::vold::SetQuotaInherit;
 using android::vold::SetQuotaProjectId;
-using android::vold::writeStringToFile;
 using namespace android::fscrypt;
 using namespace android::dm;
 
@@ -605,7 +601,7 @@
     // only prepare DE storage here, since user 0's CE key won't be installed
     // yet unless it was just created.  The framework will prepare the user's CE
     // storage later, once their CE key is installed.
-    if (!fscrypt_prepare_user_storage("", 0, 0, android::os::IVold::STORAGE_FLAG_DE)) {
+    if (!fscrypt_prepare_user_storage("", 0, android::os::IVold::STORAGE_FLAG_DE)) {
         LOG(ERROR) << "Failed to prepare user 0 storage";
         return false;
     }
@@ -615,14 +611,14 @@
 }
 
 // Creates the CE and DE keys for a new user.
-bool fscrypt_create_user_keys(userid_t user_id, int serial, bool ephemeral) {
-    LOG(DEBUG) << "fscrypt_create_user_keys for " << user_id << " serial " << serial;
+bool fscrypt_create_user_keys(userid_t user_id, bool ephemeral) {
+    LOG(DEBUG) << "fscrypt_create_user_keys for " << user_id;
     if (!IsFbeEnabled()) {
         return true;
     }
     // FIXME test for existence of key that is not loaded yet
     if (s_ce_policies.count(user_id) != 0) {
-        LOG(ERROR) << "Already exists, can't create keys for " << user_id << " serial " << serial;
+        LOG(ERROR) << "Already exists, can't create keys for " << user_id;
         // FIXME should we fail the command?
         return true;
     }
@@ -632,27 +628,6 @@
     return true;
 }
 
-// "Lock" all encrypted directories whose key has been removed.  This is needed
-// in the case where the keys are being put in the session keyring (rather in
-// the newer filesystem-level keyrings), because removing a key from the session
-// keyring doesn't affect inodes in the kernel's inode cache whose per-file key
-// was already set up.  So to remove the per-file keys and make the files
-// "appear encrypted", these inodes must be evicted.
-//
-// To do this, sync() to clean all dirty inodes, then drop all reclaimable slab
-// objects systemwide.  This is overkill, but it's the best available method
-// currently.  Don't use drop_caches mode "3" because that also evicts pagecache
-// for in-use files; all files relevant here are already closed and sync'ed.
-static void drop_caches_if_needed() {
-    if (android::vold::isFsKeyringSupported()) {
-        return;
-    }
-    sync();
-    if (!writeStringToFile("2", "/proc/sys/vm/drop_caches")) {
-        PLOG(ERROR) << "Failed to drop caches during key eviction";
-    }
-}
-
 // Evicts all the user's keys of one type from all volumes (internal and adoptable).
 // This evicts either CE keys or DE keys, depending on which map is passed.
 static bool evict_user_keys(std::map<userid_t, UserPolicies>& policy_map, userid_t user_id) {
@@ -665,7 +640,6 @@
             success &= android::vold::evictKey(BuildDataPath(volume_uuid), policy);
         }
         policy_map.erase(it);
-        drop_caches_if_needed();
     }
     return success;
 }
@@ -871,8 +845,8 @@
 // Unlocks internal CE storage for the given user.  This only unlocks internal storage, since
 // fscrypt_prepare_user_storage() has to be called for each adoptable storage volume anyway (since
 // the volume might have been absent when the user was created), and that handles the unlocking.
-bool fscrypt_unlock_ce_storage(userid_t user_id, int serial, const std::string& secret_hex) {
-    LOG(DEBUG) << "fscrypt_unlock_ce_storage " << user_id << " serial=" << serial;
+bool fscrypt_unlock_ce_storage(userid_t user_id, const std::string& secret_hex) {
+    LOG(DEBUG) << "fscrypt_unlock_ce_storage " << user_id;
     if (!IsFbeEnabled()) return true;
     if (s_ce_policies.count(user_id) != 0) {
         LOG(WARNING) << "CE storage for user " << user_id << " is already unlocked";
@@ -907,10 +881,9 @@
     return true;
 }
 
-bool fscrypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_id, int serial,
-                                  int flags) {
+bool fscrypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_id, int flags) {
     LOG(DEBUG) << "fscrypt_prepare_user_storage for volume " << escape_empty(volume_uuid)
-               << ", user " << user_id << ", serial " << serial << ", flags " << flags;
+               << ", user " << user_id << ", flags " << flags;
 
     // Internal storage must be prepared before adoptable storage, since the
     // user's volume keys are stored in their internal storage.
@@ -932,7 +905,6 @@
     if (flags & android::os::IVold::STORAGE_FLAG_DE) {
         // DE_sys key
         auto system_legacy_path = android::vold::BuildDataSystemLegacyPath(user_id);
-        auto misc_legacy_path = android::vold::BuildDataMiscLegacyPath(user_id);
         auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id);
 
         // DE_n key
@@ -962,11 +934,6 @@
 
         if (volume_uuid.empty()) {
             if (!prepare_dir(system_legacy_path, 0700, AID_SYSTEM, AID_SYSTEM)) return false;
-#if MANAGE_MISC_DIRS
-            if (!prepare_dir(misc_legacy_path, 0750, multiuser_get_uid(user_id, AID_SYSTEM),
-                             multiuser_get_uid(user_id, AID_EVERYBODY)))
-                return false;
-#endif
             if (!prepare_dir(profiles_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
 
             if (!prepare_dir_with_policy(system_de_path, 0770, AID_SYSTEM, AID_SYSTEM, de_policy))
@@ -1075,7 +1042,6 @@
     if (flags & android::os::IVold::STORAGE_FLAG_DE) {
         // DE_sys key
         auto system_legacy_path = android::vold::BuildDataSystemLegacyPath(user_id);
-        auto misc_legacy_path = android::vold::BuildDataMiscLegacyPath(user_id);
         auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id);
 
         // DE_n key
@@ -1088,9 +1054,6 @@
         res &= destroy_dir(misc_de_path);
         if (volume_uuid.empty()) {
             res &= destroy_dir(system_legacy_path);
-#if MANAGE_MISC_DIRS
-            res &= destroy_dir(misc_legacy_path);
-#endif
             res &= destroy_dir(profiles_de_path);
             res &= destroy_dir(system_de_path);
             res &= destroy_dir(vendor_de_path);
diff --git a/FsCrypt.h b/FsCrypt.h
index f5c367c..afcedfb 100644
--- a/FsCrypt.h
+++ b/FsCrypt.h
@@ -23,17 +23,16 @@
 
 bool fscrypt_init_user0();
 extern bool fscrypt_init_user0_done;
-bool fscrypt_create_user_keys(userid_t user_id, int serial, bool ephemeral);
+bool fscrypt_create_user_keys(userid_t user_id, bool ephemeral);
 bool fscrypt_destroy_user_keys(userid_t user_id);
 bool fscrypt_set_ce_key_protection(userid_t user_id, const std::string& secret);
 void fscrypt_deferred_fixate_ce_keys();
 
 std::vector<int> fscrypt_get_unlocked_users();
-bool fscrypt_unlock_ce_storage(userid_t user_id, int serial, const std::string& secret);
+bool fscrypt_unlock_ce_storage(userid_t user_id, const std::string& secret);
 bool fscrypt_lock_ce_storage(userid_t user_id);
 
-bool fscrypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_id, int serial,
-                                  int flags);
+bool fscrypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_id, int flags);
 bool fscrypt_destroy_user_storage(const std::string& volume_uuid, userid_t user_id, int flags);
 
 bool fscrypt_destroy_volume_keys(const std::string& volume_uuid);
diff --git a/IdleMaint.cpp b/IdleMaint.cpp
index 7d3eaf4..fafa280 100644
--- a/IdleMaint.cpp
+++ b/IdleMaint.cpp
@@ -507,6 +507,30 @@
     return -1;
 }
 
+int32_t GetStorageRemainingLifetime() {
+    std::string path = getDevSysfsPath();
+    if (path.empty()) {
+        return -1;
+    }
+
+    std::string lifeTimeBasePath = path + "/health_descriptor/life_time_estimation_";
+
+    int32_t lifeTime = getLifeTime(lifeTimeBasePath + "c");
+    if (lifeTime == -1) {
+        int32_t lifeTimeA = getLifeTime(lifeTimeBasePath + "a");
+        int32_t lifeTimeB = getLifeTime(lifeTimeBasePath + "b");
+        lifeTime = std::max(lifeTimeA, lifeTimeB);
+        if (lifeTime <= 0) {
+            return -1;
+        }
+
+        // 1 = 0-10% used, 10 = 90-100% used. Subtract 1 so that a brand new
+        // device looks 0% used.
+        lifeTime = (lifeTime - 1) * 10;
+    }
+    return 100 - std::clamp(lifeTime, 0, 100);
+}
+
 void SetGCUrgentPace(int32_t neededSegments, int32_t minSegmentThreshold, float dirtyReclaimRate,
                      float reclaimWeight, int32_t gcPeriod, int32_t minGCSleepTime,
                      int32_t targetDirtyRatio) {
diff --git a/IdleMaint.h b/IdleMaint.h
index a28cde2..a1387b3 100644
--- a/IdleMaint.h
+++ b/IdleMaint.h
@@ -26,6 +26,7 @@
 int RunIdleMaint(bool needGC, const android::sp<android::os::IVoldTaskListener>& listener);
 int AbortIdleMaint(const android::sp<android::os::IVoldTaskListener>& listener);
 int32_t GetStorageLifeTime();
+int32_t GetStorageRemainingLifetime();
 void SetGCUrgentPace(int32_t neededSegments, int32_t minSegmentThreshold, float dirtyReclaimRate,
                      float reclaimWeight, int32_t gcPeriod, int32_t minGCSleepTime,
                      int32_t targetDirtyRatio);
diff --git a/KeyBuffer.h b/KeyBuffer.h
index 3275255..619cb27 100644
--- a/KeyBuffer.h
+++ b/KeyBuffer.h
@@ -28,7 +28,7 @@
 // Allocator that delegates useful work to standard one but zeroes data before deallocating.
 class ZeroingAllocator : public std::allocator<char> {
   public:
-    void deallocate(pointer p, size_type n) {
+    void deallocate(value_type* p, size_type n) {
         memset_explicit(p, 0, n);
         std::allocator<char>::deallocate(p, n);
     }
diff --git a/KeyUtil.cpp b/KeyUtil.cpp
index 9e8920d..bd2ccdd 100644
--- a/KeyUtil.cpp
+++ b/KeyUtil.cpp
@@ -28,7 +28,6 @@
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
-#include <keyutils.h>
 
 #include "KeyStorage.h"
 #include "Utils.h"
@@ -75,39 +74,6 @@
     }
 }
 
-static bool isFsKeyringSupportedImpl() {
-    android::base::unique_fd fd(open("/data", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
-
-    // FS_IOC_ADD_ENCRYPTION_KEY with a NULL argument will fail with ENOTTY if
-    // the ioctl isn't supported.  Otherwise it will fail with another error
-    // code such as EFAULT.
-    //
-    // Note that there's no need to check for FS_IOC_REMOVE_ENCRYPTION_KEY,
-    // since it's guaranteed to be available if FS_IOC_ADD_ENCRYPTION_KEY is.
-    // There's also no need to check for support on external volumes separately
-    // from /data, since either the kernel supports the ioctls on all
-    // fscrypt-capable filesystems or it doesn't.
-    errno = 0;
-    (void)ioctl(fd, FS_IOC_ADD_ENCRYPTION_KEY, NULL);
-    if (errno == ENOTTY) {
-        LOG(INFO) << "Kernel doesn't support FS_IOC_ADD_ENCRYPTION_KEY.  Falling back to "
-                     "session keyring";
-        return false;
-    }
-    if (errno != EFAULT) {
-        PLOG(WARNING) << "Unexpected error from FS_IOC_ADD_ENCRYPTION_KEY";
-    }
-    LOG(DEBUG) << "Detected support for FS_IOC_ADD_ENCRYPTION_KEY";
-    return true;
-}
-
-// Return true if the kernel supports the ioctls to add/remove fscrypt keys
-// directly to/from the filesystem.
-bool isFsKeyringSupported(void) {
-    static bool supported = isFsKeyringSupportedImpl();
-    return supported;
-}
-
 // Get raw keyref - used to make keyname and to pass to ioctl
 static std::string generateKeyRef(const uint8_t* key, int length) {
     SHA512_CTX c;
@@ -127,20 +93,6 @@
     return std::string((char*)key_ref2, FSCRYPT_KEY_DESCRIPTOR_SIZE);
 }
 
-static bool fillKey(const KeyBuffer& key, fscrypt_key* fs_key) {
-    if (key.size() != FSCRYPT_MAX_KEY_SIZE) {
-        LOG(ERROR) << "Wrong size key " << key.size();
-        return false;
-    }
-    static_assert(FSCRYPT_MAX_KEY_SIZE == sizeof(fs_key->raw), "Mismatch of max key sizes");
-    fs_key->mode = 0;  // unused by kernel
-    memcpy(fs_key->raw, key.data(), key.size());
-    fs_key->size = key.size();
-    return true;
-}
-
-static char const* const NAME_PREFIXES[] = {"ext4", "f2fs", "fscrypt", nullptr};
-
 static std::string keyrefstring(const std::string& raw_ref) {
     std::ostringstream o;
     for (unsigned char i : raw_ref) {
@@ -149,44 +101,6 @@
     return o.str();
 }
 
-static std::string buildLegacyKeyName(const std::string& prefix, const std::string& raw_ref) {
-    return prefix + ":" + keyrefstring(raw_ref);
-}
-
-// Get the ID of the keyring we store all fscrypt keys in when the kernel is too
-// old to support FS_IOC_ADD_ENCRYPTION_KEY and FS_IOC_REMOVE_ENCRYPTION_KEY.
-static bool fscryptKeyring(key_serial_t* device_keyring) {
-    *device_keyring = keyctl_search(KEY_SPEC_SESSION_KEYRING, "keyring", "fscrypt", 0);
-    if (*device_keyring == -1) {
-        PLOG(ERROR) << "Unable to find device keyring";
-        return false;
-    }
-    return true;
-}
-
-// Add an encryption key to the legacy global session keyring.
-static bool installKeyLegacy(const KeyBuffer& key, const std::string& raw_ref) {
-    // Place fscrypt_key into automatically zeroing buffer.
-    KeyBuffer fsKeyBuffer(sizeof(fscrypt_key));
-    fscrypt_key& fs_key = *reinterpret_cast<fscrypt_key*>(fsKeyBuffer.data());
-
-    if (!fillKey(key, &fs_key)) return false;
-    key_serial_t device_keyring;
-    if (!fscryptKeyring(&device_keyring)) return false;
-    for (char const* const* name_prefix = NAME_PREFIXES; *name_prefix != nullptr; name_prefix++) {
-        auto ref = buildLegacyKeyName(*name_prefix, raw_ref);
-        key_serial_t key_id =
-            add_key("logon", ref.c_str(), (void*)&fs_key, sizeof(fs_key), device_keyring);
-        if (key_id == -1) {
-            PLOG(ERROR) << "Failed to insert key into keyring " << device_keyring;
-            return false;
-        }
-        LOG(DEBUG) << "Added key " << key_id << " (" << ref << ") to keyring " << device_keyring
-                   << " in process " << getpid();
-    }
-    return true;
-}
-
 // Build a struct fscrypt_key_specifier for use in the key management ioctls.
 static bool buildKeySpecifier(fscrypt_key_specifier* spec, const EncryptionPolicy& policy) {
     switch (policy.options.version) {
@@ -230,9 +144,6 @@
             // "descriptor", which must be provided by userspace.  We use the
             // first 8 bytes from the double SHA-512 of the key itself.
             policy->key_raw_ref = generateKeyRef((const uint8_t*)key.data(), key.size());
-            if (!isFsKeyringSupported()) {
-                return installKeyLegacy(key, policy->key_raw_ref);
-            }
             if (!buildKeySpecifier(&arg->key_spec, *policy)) {
                 return false;
             }
@@ -276,29 +187,6 @@
     return true;
 }
 
-// Remove an encryption key from the legacy global session keyring.
-static bool evictKeyLegacy(const std::string& raw_ref) {
-    key_serial_t device_keyring;
-    if (!fscryptKeyring(&device_keyring)) return false;
-    bool success = true;
-    for (char const* const* name_prefix = NAME_PREFIXES; *name_prefix != nullptr; name_prefix++) {
-        auto ref = buildLegacyKeyName(*name_prefix, raw_ref);
-        auto key_serial = keyctl_search(device_keyring, "logon", ref.c_str(), 0);
-
-        // Unlink the key from the keyring.  Prefer unlinking to revoking or
-        // invalidating, since unlinking is actually no less secure currently, and
-        // it avoids bugs in certain kernel versions where the keyring key is
-        // referenced from places it shouldn't be.
-        if (keyctl_unlink(key_serial, device_keyring) != 0) {
-            PLOG(ERROR) << "Failed to unlink key with serial " << key_serial << " ref " << ref;
-            success = false;
-        } else {
-            LOG(DEBUG) << "Unlinked key with serial " << key_serial << " ref " << ref;
-        }
-    }
-    return success;
-}
-
 static void waitForBusyFiles(const struct fscrypt_key_specifier key_spec, const std::string ref,
                              const std::string mountpoint) {
     android::base::unique_fd fd(open(mountpoint.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
@@ -359,9 +247,6 @@
 
 bool evictKey(const std::string& mountpoint, const EncryptionPolicy& policy) {
     const std::lock_guard<std::mutex> lock(fscrypt_keyring_mutex);
-    if (policy.options.version == 1 && !isFsKeyringSupported()) {
-        return evictKeyLegacy(policy.key_raw_ref);
-    }
 
     android::base::unique_fd fd(open(mountpoint.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
     if (fd == -1) {
diff --git a/KeyUtil.h b/KeyUtil.h
index 17a234e..cc1a1f9 100644
--- a/KeyUtil.h
+++ b/KeyUtil.h
@@ -43,28 +43,15 @@
 // be generated.
 const KeyGeneration neverGen();
 
-bool isFsKeyringSupported(void);
-
 // Install a file-based encryption key to the kernel, for use by encrypted files
 // on the specified filesystem using the specified encryption policy version.
 //
-// For v1 policies, we use FS_IOC_ADD_ENCRYPTION_KEY if the kernel supports it.
-// Otherwise we add the key to the legacy global session keyring.
-//
-// For v2 policies, we always use FS_IOC_ADD_ENCRYPTION_KEY; it's the only way
-// the kernel supports.
-//
 // Returns %true on success, %false on failure.  On success also sets *policy
 // to the EncryptionPolicy used to refer to this key.
 bool installKey(const std::string& mountpoint, const android::fscrypt::EncryptionOptions& options,
                 const KeyBuffer& key, android::fscrypt::EncryptionPolicy* policy);
 
 // Evict a file-based encryption key from the kernel.
-//
-// We use FS_IOC_REMOVE_ENCRYPTION_KEY if the kernel supports it.  Otherwise we
-// remove the key from the legacy global session keyring.
-//
-// In the latter case, the caller is responsible for dropping caches.
 bool evictKey(const std::string& mountpoint, const android::fscrypt::EncryptionPolicy& policy);
 
 // Retrieves the key from the named directory, or generates it if it doesn't
diff --git a/TEST_MAPPING b/TEST_MAPPING
index a535181..93938b6 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -10,6 +10,15 @@
       "name": "CtsScopedStorageDeviceOnlyTest"
     },
     {
+      "name": "CtsScopedStorageBypassDatabaseOperationsTest"
+    },
+    {
+      "name": "CtsScopedStorageGeneralTest"
+    },
+    {
+      "name": "CtsScopedStorageRedactUriTest"
+    },
+    {
       "name": "AdoptableHostTest"
     }
   ],
@@ -24,6 +33,15 @@
       "name": "CtsScopedStorageDeviceOnlyTest"
     },
     {
+      "name": "CtsScopedStorageBypassDatabaseOperationsTest"
+    },
+    {
+      "name": "CtsScopedStorageGeneralTest"
+    },
+    {
+      "name": "CtsScopedStorageRedactUriTest"
+    },
+    {
       "name": "AdoptableHostTest"
     }
   ]
diff --git a/Utils.cpp b/Utils.cpp
index 40a182b..696b0b4 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -1116,10 +1116,6 @@
     return StringPrintf("%s/system_de/%u", BuildDataPath("").c_str(), userId);
 }
 
-std::string BuildDataMiscLegacyPath(userid_t userId) {
-    return StringPrintf("%s/misc/user/%u", BuildDataPath("").c_str(), userId);
-}
-
 // Keep in sync with installd (frameworks/native/cmds/installd/utils.h)
 std::string BuildDataProfilesDePath(userid_t userId) {
     return StringPrintf("%s/misc/profiles/cur/%u", BuildDataPath("").c_str(), userId);
diff --git a/Utils.h b/Utils.h
index fbd0f30..690f79e 100644
--- a/Utils.h
+++ b/Utils.h
@@ -148,7 +148,6 @@
 std::string BuildDataSystemLegacyPath(userid_t userid);
 std::string BuildDataSystemCePath(userid_t userid);
 std::string BuildDataSystemDePath(userid_t userid);
-std::string BuildDataMiscLegacyPath(userid_t userid);
 std::string BuildDataProfilesDePath(userid_t userid);
 std::string BuildDataVendorCePath(userid_t userid);
 std::string BuildDataVendorDePath(userid_t userid);
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index c39604b..96f4eaf 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -504,6 +504,14 @@
     return Ok();
 }
 
+binder::Status VoldNativeService::getStorageRemainingLifetime(int32_t* _aidl_return) {
+    ENFORCE_SYSTEM_OR_ROOT;
+    ACQUIRE_LOCK;
+
+    *_aidl_return = GetStorageRemainingLifetime();
+    return Ok();
+}
+
 binder::Status VoldNativeService::setGCUrgentPace(int32_t neededSegments,
                                                   int32_t minSegmentThreshold,
                                                   float dirtyReclaimRate, float reclaimWeight,
@@ -607,12 +615,11 @@
     return translateBool(setKeyStorageBindingSeed(seed));
 }
 
-binder::Status VoldNativeService::createUserStorageKeys(int32_t userId, int32_t userSerial,
-                                                        bool ephemeral) {
+binder::Status VoldNativeService::createUserStorageKeys(int32_t userId, bool ephemeral) {
     ENFORCE_SYSTEM_OR_ROOT;
     ACQUIRE_CRYPT_LOCK;
 
-    return translateBool(fscrypt_create_user_keys(userId, userSerial, ephemeral));
+    return translateBool(fscrypt_create_user_keys(userId, ephemeral));
 }
 
 binder::Status VoldNativeService::destroyUserStorageKeys(int32_t userId) {
@@ -638,12 +645,11 @@
     return Ok();
 }
 
-binder::Status VoldNativeService::unlockCeStorage(int32_t userId, int32_t userSerial,
-                                                  const std::string& secret) {
+binder::Status VoldNativeService::unlockCeStorage(int32_t userId, const std::string& secret) {
     ENFORCE_SYSTEM_OR_ROOT;
     ACQUIRE_CRYPT_LOCK;
 
-    return translateBool(fscrypt_unlock_ce_storage(userId, userSerial, secret));
+    return translateBool(fscrypt_unlock_ce_storage(userId, secret));
 }
 
 binder::Status VoldNativeService::lockCeStorage(int32_t userId) {
@@ -654,15 +660,14 @@
 }
 
 binder::Status VoldNativeService::prepareUserStorage(const std::optional<std::string>& uuid,
-                                                     int32_t userId, int32_t userSerial,
-                                                     int32_t flags) {
+                                                     int32_t userId, int32_t flags) {
     ENFORCE_SYSTEM_OR_ROOT;
     std::string empty_string = "";
     auto uuid_ = uuid ? *uuid : empty_string;
     CHECK_ARGUMENT_HEX(uuid_);
 
     ACQUIRE_CRYPT_LOCK;
-    return translateBool(fscrypt_prepare_user_storage(uuid_, userId, userSerial, flags));
+    return translateBool(fscrypt_prepare_user_storage(uuid_, userId, flags));
 }
 
 binder::Status VoldNativeService::destroyUserStorage(const std::optional<std::string>& uuid,
diff --git a/VoldNativeService.h b/VoldNativeService.h
index e98aea8..bb00d35 100644
--- a/VoldNativeService.h
+++ b/VoldNativeService.h
@@ -89,6 +89,7 @@
                                 const android::sp<android::os::IVoldTaskListener>& listener);
     binder::Status abortIdleMaint(const android::sp<android::os::IVoldTaskListener>& listener);
     binder::Status getStorageLifeTime(int32_t* _aidl_return);
+    binder::Status getStorageRemainingLifetime(int32_t* _aidl_return);
     binder::Status setGCUrgentPace(int32_t neededSegments, int32_t minSegmentThreshold,
                                    float dirtyReclaimRate, float reclaimWeight, int32_t gcPeriod,
                                    int32_t minGCSleepTime, int32_t targetDirtyRatio);
@@ -112,17 +113,17 @@
 
     binder::Status setStorageBindingSeed(const std::vector<uint8_t>& seed);
 
-    binder::Status createUserStorageKeys(int32_t userId, int32_t userSerial, bool ephemeral);
+    binder::Status createUserStorageKeys(int32_t userId, bool ephemeral);
     binder::Status destroyUserStorageKeys(int32_t userId);
 
     binder::Status setCeStorageProtection(int32_t userId, const std::string& secret);
 
     binder::Status getUnlockedUsers(std::vector<int>* _aidl_return);
-    binder::Status unlockCeStorage(int32_t userId, int32_t userSerial, const std::string& secret);
+    binder::Status unlockCeStorage(int32_t userId, const std::string& secret);
     binder::Status lockCeStorage(int32_t userId);
 
     binder::Status prepareUserStorage(const std::optional<std::string>& uuid, int32_t userId,
-                                      int32_t userSerial, int32_t flags);
+                                      int32_t flags);
     binder::Status destroyUserStorage(const std::optional<std::string>& uuid, int32_t userId,
                                       int32_t flags);
 
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index c981f2d..a1ac20d 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -921,25 +921,34 @@
 int VolumeManager::reset() {
     // Tear down all existing disks/volumes and start from a blank slate so
     // newly connected framework hears all events.
+
+    // Destroy StubVolume disks. This needs to be done before destroying
+    // EmulatedVolumes because in ARC (Android on ChromeOS), ChromeOS Downloads
+    // directory (which is in a StubVolume) is bind-mounted to
+    // /data/media/0/Download.
+    // We do not recreate StubVolumes here because they are managed from outside
+    // Android (e.g. from ChromeOS) and their disk recreation on reset events
+    // should be handled from outside by calling createStubVolume() again.
+    for (const auto& disk : mDisks) {
+        if (disk->isStub()) {
+            disk->destroy();
+        }
+    }
+    // Remove StubVolume from both mDisks and mPendingDisks.
+    const auto isStub = [](const auto& disk) { return disk->isStub(); };
+    mDisks.remove_if(isStub);
+    mPendingDisks.remove_if(isStub);
+
     for (const auto& vol : mInternalEmulatedVolumes) {
         vol->destroy();
     }
     mInternalEmulatedVolumes.clear();
 
-    // Destroy and recreate all disks except that StubVolume disks are just
-    // destroyed and removed from both mDisks and mPendingDisks.
-    // StubVolumes are managed from outside Android (e.g. from Chrome OS) and
-    // their disk recreation on reset events should be handled from outside by
-    // calling createStubVolume() again.
+    // Destroy and recreate non-StubVolume disks.
     for (const auto& disk : mDisks) {
         disk->destroy();
-        if (!disk->isStub()) {
-            disk->create();
-        }
+        disk->create();
     }
-    const auto isStub = [](const auto& disk) { return disk->isStub(); };
-    mDisks.remove_if(isStub);
-    mPendingDisks.remove_if(isStub);
 
     updateVirtualDisk();
     mAddedUsers.clear();
@@ -958,11 +967,20 @@
         return 0;  // already shutdown
     }
     android::vold::sSleepOnUnmount = false;
+    // Destroy StubVolume disks before destroying EmulatedVolumes (see the
+    // comment in VolumeManager::reset()).
+    for (const auto& disk : mDisks) {
+        if (disk->isStub()) {
+            disk->destroy();
+        }
+    }
     for (const auto& vol : mInternalEmulatedVolumes) {
         vol->destroy();
     }
     for (const auto& disk : mDisks) {
-        disk->destroy();
+        if (!disk->isStub()) {
+            disk->destroy();
+        }
     }
 
     mInternalEmulatedVolumes.clear();
@@ -978,11 +996,20 @@
     ATRACE_NAME("VolumeManager::unmountAll()");
 
     // First, try gracefully unmounting all known devices
+    // Unmount StubVolume disks before unmounting EmulatedVolumes (see the
+    // comment in VolumeManager::reset()).
+    for (const auto& disk : mDisks) {
+        if (disk->isStub()) {
+            disk->unmountAll();
+        }
+    }
     for (const auto& vol : mInternalEmulatedVolumes) {
         vol->unmount();
     }
     for (const auto& disk : mDisks) {
-        disk->unmountAll();
+        if (!disk->isStub()) {
+            disk->unmountAll();
+        }
     }
 
     // Worst case we might have some stale mounts lurking around, so
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index 852e8af..d121dee 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -66,6 +66,8 @@
     void fstrim(int fstrimFlags, IVoldTaskListener listener);
     void runIdleMaint(boolean needGC, IVoldTaskListener listener);
     void abortIdleMaint(IVoldTaskListener listener);
+    // Returns the amount of storage lifetime used, as a percentage.
+    // (eg, 10 indicates 10% of lifetime used), or -1 on failure.
     int getStorageLifeTime();
     void setGCUrgentPace(int neededSegments, int minSegmentThreshold,
                          float dirtyReclaimRate, float reclaimWeight,
@@ -85,17 +87,16 @@
 
     void setStorageBindingSeed(in byte[] seed);
 
-    void createUserStorageKeys(int userId, int userSerial, boolean ephemeral);
+    void createUserStorageKeys(int userId, boolean ephemeral);
     void destroyUserStorageKeys(int userId);
 
     void setCeStorageProtection(int userId, @utf8InCpp String secret);
 
     int[] getUnlockedUsers();
-    void unlockCeStorage(int userId, int userSerial, @utf8InCpp String secret);
+    void unlockCeStorage(int userId, @utf8InCpp String secret);
     void lockCeStorage(int userId);
 
-    void prepareUserStorage(@nullable @utf8InCpp String uuid, int userId, int userSerial,
-                            int storageFlags);
+    void prepareUserStorage(@nullable @utf8InCpp String uuid, int userId, int storageFlags);
     void destroyUserStorage(@nullable @utf8InCpp String uuid, int userId, int storageFlags);
 
     void prepareSandboxForApp(in @utf8InCpp String packageName, int appId,
@@ -136,6 +137,11 @@
 
     long getStorageSize();
 
+    // Returns the remaining storage lifetime as a percentage, rounded up as
+    // needed when the underlying hardware reports low precision. Returns -1
+    // on failure.
+    int getStorageRemainingLifetime();
+
     const int FSTRIM_FLAG_DEEP_TRIM = 1;
 
     const int MOUNT_FLAG_PRIMARY = 1;
diff --git a/fs/Vfat.cpp b/fs/Vfat.cpp
index f3f04d8..c0cd918 100644
--- a/fs/Vfat.cpp
+++ b/fs/Vfat.cpp
@@ -20,6 +20,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 #include <unistd.h>
 
 #include <linux/fs.h>
@@ -118,6 +119,16 @@
     return 0;
 }
 
+int16_t currentUtcOffsetMinutes() {
+    time_t now = time(NULL);
+
+    struct tm nowTm;
+    localtime_r(&now, &nowTm);
+
+    int32_t utcOffsetSeconds = nowTm.tm_gmtoff;
+    return (int16_t)(utcOffsetSeconds / 60);
+}
+
 status_t Mount(const std::string& source, const std::string& target, bool ro, bool remount,
                bool executable, int ownerUid, int ownerGid, int permMask, bool createLost) {
     int rc;
@@ -136,6 +147,33 @@
         android::base::StringPrintf("utf8,uid=%d,gid=%d,fmask=%o,dmask=%o,shortname=mixed",
                                     ownerUid, ownerGid, permMask, permMask);
 
+    // b/315058275: Set this to false if you don't want to use a fixed offset
+    // determined at mount time. When this is false, the vfat driver will fall
+    // back to using sys_tz, which Android does not set by default, then assume
+    // local time == UTC.
+    if (true) {
+        // Calculate the offset to use to adjust FAT timestamps to convert them
+        // from "local time" into unix epoch time. This assumes the current UTC
+        // offset of this device is the same as the device that wrote them. User
+        // space code, e.g. ls -l, will then apply the UTC offset for the UTC
+        // time to convert times from unix epoch time to local time for display.
+        // Before Android U (b/246256335), Android platform code informed the
+        // Linux kernel about the UTC offset under some circumstances, but not
+        // for all, e.g. DST changes. The kernel vfat driver is one of the few
+        // things in the kernel that tries to use kernel UTC offset information.
+        // Setting time zone offset in the Linux kernel is discouraged and so
+        // Android no longer informs the kernel. Instead, the offset for vfat
+        // to use is now set at volume mount time. This means that if the time
+        // zone offset changes while the device is mounted, or if files were
+        // written in opposing daylight saving time, then incorrect file times
+        // will be displayed until the volume is remounted. Even then, the vfat
+        // driver has to assume a fixed offset to apply to all files, so files
+        // written at different times of the year can have incorrect times
+        // calculated, e.g. offset incorrectly by one hour.
+        int16_t timeOffsetArg = currentUtcOffsetMinutes();
+        mountData += android::base::StringPrintf(",time_offset=%d", timeOffsetArg);
+    }
+
     rc = mount(c_source, c_target, "vfat", flags, mountData.c_str());
 
     if (rc && errno == EROFS) {