AutomaticStorageManagementJobService.java revision 01a81f3502750035b8eabb6a053a61bfae4d768e
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.storagemanager.automatic; 18 19import android.app.job.JobParameters; 20import android.app.job.JobService; 21import android.content.ContentResolver; 22import android.content.Context; 23import android.content.Intent; 24import android.os.storage.StorageManager; 25import android.provider.Settings; 26import android.util.Log; 27 28import com.android.internal.annotations.VisibleForTesting; 29import com.android.settingslib.Utils; 30import com.android.settingslib.deviceinfo.PrivateStorageInfo; 31import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider; 32import com.android.settingslib.deviceinfo.StorageVolumeProvider; 33import com.android.storagemanager.overlay.FeatureFactory; 34import com.android.storagemanager.overlay.StorageManagementJobProvider; 35 36/** 37 * {@link JobService} class to start automatic storage clearing jobs to free up space. The job only 38 * starts if the device is under a certain percent of free storage. 39 */ 40public class AutomaticStorageManagementJobService extends JobService { 41 private static final String TAG = "AsmJobService"; 42 43 private static final long DEFAULT_LOW_FREE_PERCENT = 15; 44 45 private StorageManagementJobProvider mProvider; 46 private StorageVolumeProvider mVolumeProvider; 47 private Clock mClock; 48 49 @Override 50 public boolean onStartJob(JobParameters args) { 51 // We need to double-check the preconditions here because they are not enforced for a 52 // periodic job. 53 if (!preconditionsFulfilled()) { 54 // By telling the system to re-schedule the job, it will attempt to execute again at a 55 // later idle window -- possibly one where we are charging. 56 jobFinished(args, true); 57 return false; 58 } 59 60 mProvider = FeatureFactory.getFactory(this).getStorageManagementJobProvider(); 61 if (maybeDisableDueToPolicy(mProvider, getContentResolver(), getClock())) { 62 jobFinished(args, false); 63 return false; 64 } 65 66 if (!volumeNeedsManagement()) { 67 Log.i(TAG, "Skipping automatic storage management."); 68 Settings.Secure.putLong(getContentResolver(), 69 Settings.Secure.AUTOMATIC_STORAGE_MANAGER_LAST_RUN, 70 System.currentTimeMillis()); 71 jobFinished(args, false); 72 return false; 73 } 74 75 boolean isEnabled = 76 Settings.Secure.getInt(getContentResolver(), 77 Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED, 0) != 0; 78 if (!isEnabled) { 79 Intent maybeShowNotificationIntent = 80 new Intent(NotificationController.INTENT_ACTION_SHOW_NOTIFICATION); 81 maybeShowNotificationIntent.setClass(getApplicationContext(), 82 NotificationController.class); 83 getApplicationContext().sendBroadcast(maybeShowNotificationIntent); 84 jobFinished(args, false); 85 return false; 86 } 87 88 if (mProvider != null) { 89 return mProvider.onStartJob(this, args, getDaysToRetain()); 90 } 91 92 jobFinished(args, false); 93 return false; 94 } 95 96 @Override 97 public boolean onStopJob(JobParameters args) { 98 if (mProvider != null) { 99 return mProvider.onStopJob(this, args); 100 } 101 102 return false; 103 } 104 105 void setStorageVolumeProvider(StorageVolumeProvider storageProvider) { 106 mVolumeProvider = storageProvider; 107 } 108 109 private int getDaysToRetain() { 110 return Settings.Secure.getInt( 111 getContentResolver(), 112 Settings.Secure.AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN, 113 Utils.getDefaultStorageManagerDaysToRetain(getResources())); 114 } 115 116 private boolean volumeNeedsManagement() { 117 if (mVolumeProvider == null) { 118 mVolumeProvider = new StorageManagerVolumeProvider( 119 getSystemService(StorageManager.class)); 120 } 121 122 PrivateStorageInfo info = PrivateStorageInfo.getPrivateStorageInfo(mVolumeProvider); 123 124 long lowStorageThreshold = (info.totalBytes * DEFAULT_LOW_FREE_PERCENT) / 100; 125 return info.freeBytes < lowStorageThreshold; 126 } 127 128 private boolean preconditionsFulfilled() { 129 // NOTE: We don't check the idle state here because this job should be running in idle 130 // maintenance windows. During the idle maintenance window, the device is -technically- not 131 // idle. For more information, see PowerManager.isDeviceIdleMode(). 132 Context context = getApplicationContext(); 133 return JobPreconditions.isCharging(context); 134 } 135 136 /** Returns if ASM was disabled due to policy. * */ 137 @VisibleForTesting 138 static boolean maybeDisableDueToPolicy( 139 StorageManagementJobProvider provider, ContentResolver cr, Clock clock) { 140 if (provider == null || cr == null) { 141 return false; 142 } 143 144 final long disabledThresholdMillis = provider.getDisableThresholdMillis(cr); 145 final long currentTime = clock.currentTimeMillis(); 146 final boolean disabledByPolicyInThePast = 147 Settings.Secure.getInt( 148 cr, 149 Settings.Secure.AUTOMATIC_STORAGE_MANAGER_TURNED_OFF_BY_POLICY, 150 0) 151 != 0; 152 if (currentTime > disabledThresholdMillis && !disabledByPolicyInThePast) { 153 Settings.Secure.putInt( 154 cr, Settings.Secure.AUTOMATIC_STORAGE_MANAGER_TURNED_OFF_BY_POLICY, 1); 155 Settings.Secure.putInt(cr, Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED, 0); 156 return true; 157 } 158 159 return false; 160 } 161 162 private Clock getClock() { 163 if (mClock == null) { 164 mClock = new Clock(); 165 } 166 return mClock; 167 } 168 169 @VisibleForTesting 170 void setClock(Clock clock) { 171 mClock = clock; 172 } 173 174 /** Clock provides the current time. */ 175 protected static class Clock { 176 /** Returns the current time in milliseconds. */ 177 public long currentTimeMillis() { 178 return System.currentTimeMillis(); 179 } 180 } 181} 182