diff --git a/services/core/java/com/android/server/SmartStorageMaintIdler.java b/services/core/java/com/android/server/SmartStorageMaintIdler.java index 2dff72fdc3449..8996926110868 100644 --- a/services/core/java/com/android/server/SmartStorageMaintIdler.java +++ b/services/core/java/com/android/server/SmartStorageMaintIdler.java @@ -46,7 +46,7 @@ public class SmartStorageMaintIdler extends JobService { } // ... and try again in a next period scheduleSmartIdlePass(SmartStorageMaintIdler.this, - StorageManagerService.SMART_IDLE_MAINT_PERIOD); + StorageManagerService.sSmartIdleMaintPeriod); } }; @@ -70,7 +70,7 @@ public class SmartStorageMaintIdler extends JobService { /** * Schedule the smart storage idle maintenance job */ - public static void scheduleSmartIdlePass(Context context, int nHours) { + public static void scheduleSmartIdlePass(Context context, int nMinutes) { StorageManagerService ms = StorageManagerService.sSelf; if ((ms == null) || ms.isPassedLifetimeThresh()) { return; @@ -78,7 +78,7 @@ public class SmartStorageMaintIdler extends JobService { JobScheduler tm = context.getSystemService(JobScheduler.class); - long nextScheduleTime = TimeUnit.HOURS.toMillis(nHours); + long nextScheduleTime = TimeUnit.MINUTES.toMillis(nMinutes); JobInfo.Builder builder = new JobInfo.Builder(SMART_MAINT_JOB_ID, SMART_STORAGE_MAINT_SERVICE); diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 9f32888262ee6..1f4191fcb3481 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -333,13 +333,15 @@ class StorageManagerService extends IStorageManager.Stub @Nullable public static String sMediaStoreAuthorityProcessName; - // Run period in hour for smart idle maintenance - static final int SMART_IDLE_MAINT_PERIOD = 1; + // Smart idle maintenance running period in minute + static volatile int sSmartIdleMaintPeriod = 60; private final AtomicFile mSettingsFile; - private final AtomicFile mHourlyWriteFile; + private final AtomicFile mWriteRecordFile; - private static final int MAX_HOURLY_WRITE_RECORDS = 72; + // 72 hours (3 days) + private static final int MAX_PERIOD_WRITE_RECORD = 72 * 60; + private volatile int mMaxWriteRecords; /** * Default config values for smart idle maintenance @@ -347,6 +349,10 @@ class StorageManagerService extends IStorageManager.Stub */ // Decide whether smart idle maintenance is enabled or not private static final boolean DEFAULT_SMART_IDLE_MAINT_ENABLED = false; + // Run period in minute for smart idle maintenance + private static final int DEFAULT_SMART_IDLE_MAINT_PERIOD = 60; + private static final int MIN_SMART_IDLE_MAINT_PERIOD = 10; + private static final int MAX_SMART_IDLE_MAINT_PERIOD = 24 * 60; // Storage lifetime percentage threshold to decide to turn off the feature private static final int DEFAULT_LIFETIME_PERCENT_THRESHOLD = 70; // Minimum required number of dirty + free segments to trigger GC @@ -369,8 +375,8 @@ class StorageManagerService extends IStorageManager.Stub private volatile boolean mNeedGC; private volatile boolean mPassedLifetimeThresh; - // Tracking storage hourly write amounts - private volatile int[] mStorageHourlyWrites; + // Tracking storage write amounts in one period + private volatile int[] mStorageWriteRecords; /** * Never hold the lock while performing downcalls into vold, since @@ -933,7 +939,7 @@ class StorageManagerService extends IStorageManager.Stub private void handleSystemReady() { if (prepareSmartIdleMaint()) { - SmartStorageMaintIdler.scheduleSmartIdlePass(mContext, SMART_IDLE_MAINT_PERIOD); + SmartStorageMaintIdler.scheduleSmartIdlePass(mContext, sSmartIdleMaintPeriod); } // Start scheduling nominally-daily fstrim operations @@ -1908,10 +1914,19 @@ class StorageManagerService extends IStorageManager.Stub mSettingsFile = new AtomicFile( new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings"); - mHourlyWriteFile = new AtomicFile( - new File(Environment.getDataSystemDirectory(), "storage-hourly-writes")); + mWriteRecordFile = new AtomicFile( + new File(Environment.getDataSystemDirectory(), "storage-write-records")); - mStorageHourlyWrites = new int[MAX_HOURLY_WRITE_RECORDS]; + sSmartIdleMaintPeriod = DeviceConfig.getInt(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT, + "smart_idle_maint_period", DEFAULT_SMART_IDLE_MAINT_PERIOD); + if (sSmartIdleMaintPeriod < MIN_SMART_IDLE_MAINT_PERIOD) { + sSmartIdleMaintPeriod = MIN_SMART_IDLE_MAINT_PERIOD; + } else if (sSmartIdleMaintPeriod > MAX_SMART_IDLE_MAINT_PERIOD) { + sSmartIdleMaintPeriod = MAX_SMART_IDLE_MAINT_PERIOD; + } + + mMaxWriteRecords = MAX_PERIOD_WRITE_RECORD / sSmartIdleMaintPeriod; + mStorageWriteRecords = new int[mMaxWriteRecords]; synchronized (mLock) { readSettingsLocked(); @@ -2657,7 +2672,7 @@ class StorageManagerService extends IStorageManager.Stub // maintenance to avoid the conflict mNeedGC = false; - loadStorageHourlyWrites(); + loadStorageWriteRecords(); try { mVold.refreshLatestWrite(); } catch (Exception e) { @@ -2673,13 +2688,17 @@ class StorageManagerService extends IStorageManager.Stub return mPassedLifetimeThresh; } - private void loadStorageHourlyWrites() { + private void loadStorageWriteRecords() { FileInputStream fis = null; try { - fis = mHourlyWriteFile.openRead(); + fis = mWriteRecordFile.openRead(); ObjectInputStream ois = new ObjectInputStream(fis); - mStorageHourlyWrites = (int[])ois.readObject(); + + int periodValue = ois.readInt(); + if (periodValue == sSmartIdleMaintPeriod) { + mStorageWriteRecords = (int[]) ois.readObject(); + } } catch (FileNotFoundException e) { // Missing data is okay, probably first boot } catch (Exception e) { @@ -2689,24 +2708,26 @@ class StorageManagerService extends IStorageManager.Stub } } - private int getAverageHourlyWrite() { - return Arrays.stream(mStorageHourlyWrites).sum() / MAX_HOURLY_WRITE_RECORDS; + private int getAverageWriteAmount() { + return Arrays.stream(mStorageWriteRecords).sum() / mMaxWriteRecords; } - private void updateStorageHourlyWrites(int latestWrite) { + private void updateStorageWriteRecords(int latestWrite) { FileOutputStream fos = null; - System.arraycopy(mStorageHourlyWrites,0, mStorageHourlyWrites, 1, - MAX_HOURLY_WRITE_RECORDS - 1); - mStorageHourlyWrites[0] = latestWrite; + System.arraycopy(mStorageWriteRecords, 0, mStorageWriteRecords, 1, + mMaxWriteRecords - 1); + mStorageWriteRecords[0] = latestWrite; try { - fos = mHourlyWriteFile.startWrite(); + fos = mWriteRecordFile.startWrite(); ObjectOutputStream oos = new ObjectOutputStream(fos); - oos.writeObject(mStorageHourlyWrites); - mHourlyWriteFile.finishWrite(fos); + + oos.writeInt(sSmartIdleMaintPeriod); + oos.writeObject(mStorageWriteRecords); + mWriteRecordFile.finishWrite(fos); } catch (IOException e) { if (fos != null) { - mHourlyWriteFile.failWrite(fos); + mWriteRecordFile.failWrite(fos); } } } @@ -2770,22 +2791,23 @@ class StorageManagerService extends IStorageManager.Stub return; } - int latestHourlyWrite = mVold.getWriteAmount(); - if (latestHourlyWrite == -1) { - Slog.w(TAG, "Failed to get storage hourly write"); + int latestWrite = mVold.getWriteAmount(); + if (latestWrite == -1) { + Slog.w(TAG, "Failed to get storage write record"); return; } - updateStorageHourlyWrites(latestHourlyWrite); - int avgHourlyWrite = getAverageHourlyWrite(); + updateStorageWriteRecords(latestWrite); + int avgWriteAmount = getAverageWriteAmount(); - Slog.i(TAG, "Set smart idle maintenance: " + "latest hourly write: " + - latestHourlyWrite + ", average hourly write: " + avgHourlyWrite + + Slog.i(TAG, "Set smart idle maintenance: " + "latest write amount: " + + latestWrite + ", average write amount: " + avgWriteAmount + ", min segment threshold: " + mMinSegmentsThreshold + ", dirty reclaim rate: " + mDirtyReclaimRate + - ", segment reclaim weight:" + mSegmentReclaimWeight); - mVold.setGCUrgentPace(avgHourlyWrite, mMinSegmentsThreshold, mDirtyReclaimRate, - mSegmentReclaimWeight); + ", segment reclaim weight: " + mSegmentReclaimWeight + + ", period: " + sSmartIdleMaintPeriod); + mVold.setGCUrgentPace(avgWriteAmount, mMinSegmentsThreshold, mDirtyReclaimRate, + mSegmentReclaimWeight, sSmartIdleMaintPeriod); } else { Slog.i(TAG, "Skipping smart idle maintenance - block based checkpoint in progress"); }