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

Commit d1233a69 authored by Daeho Jeong's avatar Daeho Jeong Committed by Gerrit Code Review
Browse files

Merge "Make smart idle maint's period changable"

parents ca46dc18 ce8bb222
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -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);
+56 −34
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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();
@@ -2638,7 +2653,7 @@ class StorageManagerService extends IStorageManager.Stub
            // maintenance to avoid the conflict
            mNeedGC = false;

            loadStorageHourlyWrites();
            loadStorageWriteRecords();
            try {
                mVold.refreshLatestWrite();
            } catch (Exception e) {
@@ -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) {
@@ -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);
            }
        }
    }
@@ -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");
            }