From 0620564ecb47a6fd33317a31bf8ae2f0afea8dd9 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 31 Jan 2024 18:54:33 +0000 Subject: [PATCH] Add API to get remaining lifetime as a percentage. This differs slightly from the previous API, which exists for idle maintenance, whereas this value is intended to be displayed to users. First, it returns remaining lifetime, rather than used lifetime. Second, it rounds up the returned value for usabilty purposes. This isn't an issue on Pixel (which reports at 1% granularity), but devices which report at 10% granularity should show 100% out-of-box, which is not possible to distinguish in the old API. Bug: 309886423 Test: StorageManager.getRemainingStorageLifetime Change-Id: Ic5f6ec9969667302ba8bad95b2765e2cc740bed4 --- IdleMaint.cpp | 24 ++++++++++++++++++++++++ IdleMaint.h | 1 + VoldNativeService.cpp | 8 ++++++++ VoldNativeService.h | 1 + binder/android/os/IVold.aidl | 7 +++++++ 5 files changed, 41 insertions(+) diff --git a/IdleMaint.cpp b/IdleMaint.cpp index 7d3eaf4..fafa280 100644 --- a/IdleMaint.cpp +++ b/IdleMaint.cpp @@ -507,6 +507,30 @@ int32_t GetStorageLifeTime() { 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 @@ void Trim(const android::sp& listener); int RunIdleMaint(bool needGC, const android::sp& listener); int AbortIdleMaint(const android::sp& 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/VoldNativeService.cpp b/VoldNativeService.cpp index 65731af..96f4eaf 100644 --- a/VoldNativeService.cpp +++ b/VoldNativeService.cpp @@ -504,6 +504,14 @@ binder::Status VoldNativeService::getStorageLifeTime(int32_t* _aidl_return) { 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, diff --git a/VoldNativeService.h b/VoldNativeService.h index d9aee57..bb00d35 100644 --- a/VoldNativeService.h +++ b/VoldNativeService.h @@ -89,6 +89,7 @@ class VoldNativeService : public BinderService, public os::Bn const android::sp& listener); binder::Status abortIdleMaint(const android::sp& 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); diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl index 229f173..d121dee 100644 --- a/binder/android/os/IVold.aidl +++ b/binder/android/os/IVold.aidl @@ -66,6 +66,8 @@ interface IVold { 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, @@ -135,6 +137,11 @@ interface IVold { 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;