Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1462510e authored by Daeho Jeong's avatar Daeho Jeong Committed by Automerger Merge Worker
Browse files

Merge "Make smart idle maint's period changable" am: d1233a69 am: 3219f996...

Merge "Make smart idle maint's period changable" am: d1233a69 am: 3219f996 am: 686849c5 am: 700886d8

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2032683



Change-Id: I52b7205aacb16eaf4e334fcf4bb994faa9c78d4c
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 82f0665f 700886d8
Loading
Loading
Loading
Loading
+3 −3
Original line number Original line Diff line number Diff line
@@ -46,7 +46,7 @@ public class SmartStorageMaintIdler extends JobService {
            }
            }
            // ... and try again in a next period
            // ... and try again in a next period
            scheduleSmartIdlePass(SmartStorageMaintIdler.this,
            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
     * 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;
        StorageManagerService ms = StorageManagerService.sSelf;
        if ((ms == null) || ms.isPassedLifetimeThresh()) {
        if ((ms == null) || ms.isPassedLifetimeThresh()) {
            return;
            return;
@@ -78,7 +78,7 @@ public class SmartStorageMaintIdler extends JobService {


        JobScheduler tm = context.getSystemService(JobScheduler.class);
        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,
        JobInfo.Builder builder = new JobInfo.Builder(SMART_MAINT_JOB_ID,
            SMART_STORAGE_MAINT_SERVICE);
            SMART_STORAGE_MAINT_SERVICE);
+56 −34
Original line number Original line Diff line number Diff line
@@ -336,13 +336,15 @@ class StorageManagerService extends IStorageManager.Stub


    @Nullable public static String sMediaStoreAuthorityProcessName;
    @Nullable public static String sMediaStoreAuthorityProcessName;


    // Run period in hour for smart idle maintenance
    // Smart idle maintenance running period in minute
    static final int SMART_IDLE_MAINT_PERIOD = 1;
    static volatile int sSmartIdleMaintPeriod = 60;


    private final AtomicFile mSettingsFile;
    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
     * Default config values for smart idle maintenance
@@ -350,6 +352,10 @@ class StorageManagerService extends IStorageManager.Stub
     */
     */
    // Decide whether smart idle maintenance is enabled or not
    // Decide whether smart idle maintenance is enabled or not
    private static final boolean DEFAULT_SMART_IDLE_MAINT_ENABLED = false;
    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
    // Storage lifetime percentage threshold to decide to turn off the feature
    private static final int DEFAULT_LIFETIME_PERCENT_THRESHOLD = 70;
    private static final int DEFAULT_LIFETIME_PERCENT_THRESHOLD = 70;
    // Minimum required number of dirty + free segments to trigger GC
    // Minimum required number of dirty + free segments to trigger GC
@@ -372,8 +378,8 @@ class StorageManagerService extends IStorageManager.Stub
    private volatile boolean mNeedGC;
    private volatile boolean mNeedGC;


    private volatile boolean mPassedLifetimeThresh;
    private volatile boolean mPassedLifetimeThresh;
    // Tracking storage hourly write amounts
    // Tracking storage write amounts in one period
    private volatile int[] mStorageHourlyWrites;
    private volatile int[] mStorageWriteRecords;


    /**
    /**
     * <em>Never</em> hold the lock while performing downcalls into vold, since
     * <em>Never</em> hold the lock while performing downcalls into vold, since
@@ -929,7 +935,7 @@ class StorageManagerService extends IStorageManager.Stub


    private void handleSystemReady() {
    private void handleSystemReady() {
        if (prepareSmartIdleMaint()) {
        if (prepareSmartIdleMaint()) {
            SmartStorageMaintIdler.scheduleSmartIdlePass(mContext, SMART_IDLE_MAINT_PERIOD);
            SmartStorageMaintIdler.scheduleSmartIdlePass(mContext, sSmartIdleMaintPeriod);
        }
        }


        // Start scheduling nominally-daily fstrim operations
        // Start scheduling nominally-daily fstrim operations
@@ -1950,10 +1956,19 @@ class StorageManagerService extends IStorageManager.Stub


        mSettingsFile = new AtomicFile(
        mSettingsFile = new AtomicFile(
                new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");
                new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");
        mHourlyWriteFile = new AtomicFile(
        mWriteRecordFile = new AtomicFile(
                new File(Environment.getDataSystemDirectory(), "storage-hourly-writes"));
                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) {
        synchronized (mLock) {
            readSettingsLocked();
            readSettingsLocked();
@@ -2696,7 +2711,7 @@ class StorageManagerService extends IStorageManager.Stub
            // maintenance to avoid the conflict
            // maintenance to avoid the conflict
            mNeedGC = false;
            mNeedGC = false;


            loadStorageHourlyWrites();
            loadStorageWriteRecords();
            try {
            try {
                mVold.refreshLatestWrite();
                mVold.refreshLatestWrite();
            } catch (Exception e) {
            } catch (Exception e) {
@@ -2712,13 +2727,17 @@ class StorageManagerService extends IStorageManager.Stub
        return mPassedLifetimeThresh;
        return mPassedLifetimeThresh;
    }
    }


    private void loadStorageHourlyWrites() {
    private void loadStorageWriteRecords() {
        FileInputStream fis = null;
        FileInputStream fis = null;


        try {
        try {
            fis = mHourlyWriteFile.openRead();
            fis = mWriteRecordFile.openRead();
            ObjectInputStream ois = new ObjectInputStream(fis);
            ObjectInputStream ois = new ObjectInputStream(fis);
            mStorageHourlyWrites = (int[])ois.readObject();

            int periodValue = ois.readInt();
            if (periodValue == sSmartIdleMaintPeriod) {
                mStorageWriteRecords = (int[]) ois.readObject();
            }
        } catch (FileNotFoundException e) {
        } catch (FileNotFoundException e) {
            // Missing data is okay, probably first boot
            // Missing data is okay, probably first boot
        } catch (Exception e) {
        } catch (Exception e) {
@@ -2728,24 +2747,26 @@ class StorageManagerService extends IStorageManager.Stub
        }
        }
    }
    }


    private int getAverageHourlyWrite() {
    private int getAverageWriteAmount() {
        return Arrays.stream(mStorageHourlyWrites).sum() / MAX_HOURLY_WRITE_RECORDS;
        return Arrays.stream(mStorageWriteRecords).sum() / mMaxWriteRecords;
    }
    }


    private void updateStorageHourlyWrites(int latestWrite) {
    private void updateStorageWriteRecords(int latestWrite) {
        FileOutputStream fos = null;
        FileOutputStream fos = null;


        System.arraycopy(mStorageHourlyWrites,0, mStorageHourlyWrites, 1,
        System.arraycopy(mStorageWriteRecords, 0, mStorageWriteRecords, 1,
                     MAX_HOURLY_WRITE_RECORDS - 1);
                     mMaxWriteRecords - 1);
        mStorageHourlyWrites[0] = latestWrite;
        mStorageWriteRecords[0] = latestWrite;
        try {
        try {
            fos = mHourlyWriteFile.startWrite();
            fos = mWriteRecordFile.startWrite();
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(mStorageHourlyWrites);

            mHourlyWriteFile.finishWrite(fos);
            oos.writeInt(sSmartIdleMaintPeriod);
            oos.writeObject(mStorageWriteRecords);
            mWriteRecordFile.finishWrite(fos);
        } catch (IOException e) {
        } catch (IOException e) {
            if (fos != null) {
            if (fos != null) {
                mHourlyWriteFile.failWrite(fos);
                mWriteRecordFile.failWrite(fos);
            }
            }
        }
        }
    }
    }
@@ -2809,22 +2830,23 @@ class StorageManagerService extends IStorageManager.Stub
                    return;
                    return;
                }
                }


                int latestHourlyWrite = mVold.getWriteAmount();
                int latestWrite = mVold.getWriteAmount();
                if (latestHourlyWrite == -1) {
                if (latestWrite == -1) {
                    Slog.w(TAG, "Failed to get storage hourly write");
                    Slog.w(TAG, "Failed to get storage write record");
                    return;
                    return;
                }
                }


                updateStorageHourlyWrites(latestHourlyWrite);
                updateStorageWriteRecords(latestWrite);
                int avgHourlyWrite = getAverageHourlyWrite();
                int avgWriteAmount = getAverageWriteAmount();


                Slog.i(TAG, "Set smart idle maintenance: " + "latest hourly write: " +
                Slog.i(TAG, "Set smart idle maintenance: " + "latest write amount: " +
                            latestHourlyWrite + ", average hourly write: " + avgHourlyWrite +
                            latestWrite + ", average write amount: " + avgWriteAmount +
                            ", min segment threshold: " + mMinSegmentsThreshold +
                            ", min segment threshold: " + mMinSegmentsThreshold +
                            ", dirty reclaim rate: " + mDirtyReclaimRate +
                            ", dirty reclaim rate: " + mDirtyReclaimRate +
                            ", segment reclaim weight:" + mSegmentReclaimWeight);
                            ", segment reclaim weight: " + mSegmentReclaimWeight +
                mVold.setGCUrgentPace(avgHourlyWrite, mMinSegmentsThreshold, mDirtyReclaimRate,
                            ", period: " + sSmartIdleMaintPeriod);
                                      mSegmentReclaimWeight);
                mVold.setGCUrgentPace(avgWriteAmount, mMinSegmentsThreshold, mDirtyReclaimRate,
                                      mSegmentReclaimWeight, sSmartIdleMaintPeriod);
            } else {
            } else {
                Slog.i(TAG, "Skipping smart idle maintenance - block based checkpoint in progress");
                Slog.i(TAG, "Skipping smart idle maintenance - block based checkpoint in progress");
            }
            }