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

Commit 3219f996 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

parents 024d224d d1233a69
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");
            }