Loading services/core/java/com/android/server/SmartStorageMaintIdler.java +3 −3 Original line number Diff line number Diff line Loading @@ -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); } }; Loading @@ -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; Loading @@ -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); Loading services/core/java/com/android/server/StorageManagerService.java +56 −34 Original line number Diff line number Diff line Loading @@ -332,13 +332,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 Loading @@ -346,6 +348,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 Loading @@ -368,8 +374,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; /** * <em>Never</em> hold the lock while performing downcalls into vold, since Loading Loading @@ -914,7 +920,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 Loading Loading @@ -1889,10 +1895,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(); Loading Loading @@ -2638,7 +2653,7 @@ class StorageManagerService extends IStorageManager.Stub // maintenance to avoid the conflict mNeedGC = false; loadStorageHourlyWrites(); loadStorageWriteRecords(); try { mVold.refreshLatestWrite(); } catch (Exception e) { Loading @@ -2654,13 +2669,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) { Loading @@ -2670,24 +2689,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); } } } Loading Loading @@ -2751,22 +2772,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"); } Loading Loading
services/core/java/com/android/server/SmartStorageMaintIdler.java +3 −3 Original line number Diff line number Diff line Loading @@ -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); } }; Loading @@ -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; Loading @@ -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); Loading
services/core/java/com/android/server/StorageManagerService.java +56 −34 Original line number Diff line number Diff line Loading @@ -332,13 +332,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 Loading @@ -346,6 +348,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 Loading @@ -368,8 +374,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; /** * <em>Never</em> hold the lock while performing downcalls into vold, since Loading Loading @@ -914,7 +920,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 Loading Loading @@ -1889,10 +1895,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(); Loading Loading @@ -2638,7 +2653,7 @@ class StorageManagerService extends IStorageManager.Stub // maintenance to avoid the conflict mNeedGC = false; loadStorageHourlyWrites(); loadStorageWriteRecords(); try { mVold.refreshLatestWrite(); } catch (Exception e) { Loading @@ -2654,13 +2669,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) { Loading @@ -2670,24 +2689,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); } } } Loading Loading @@ -2751,22 +2772,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"); } Loading