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.Context; 22import android.os.BatteryManager; 23import android.os.storage.StorageManager; 24import android.os.storage.VolumeInfo; 25import android.provider.Settings; 26import android.util.Log; 27import com.android.storagemanager.overlay.FeatureFactory; 28import com.android.storagemanager.overlay.StorageManagementJobProvider; 29 30import java.io.File; 31 32/** 33 * {@link JobService} class to start automatic storage clearing jobs to free up space. The job only 34 * starts if the device is under a certain percent of free storage. 35 */ 36public class AutomaticStorageManagementJobService extends JobService { 37 private static final String TAG = "AsmJobService"; 38 39 private static final long DEFAULT_LOW_FREE_PERCENT = 15; 40 41 private StorageManagementJobProvider mProvider; 42 43 @Override 44 public boolean onStartJob(JobParameters args) { 45 // We need to double-check the precondition shere because they are not enforced for a 46 // periodic job. 47 if (!preconditionsFulfilled()) { 48 // By telling the system to re-schedule the job, it will attempt to execute again at a 49 // later idle window -- possibly one where we are charging. 50 jobFinished(args, true); 51 return false; 52 } 53 54 StorageManager manager = getSystemService(StorageManager.class); 55 VolumeInfo internalVolume = manager.findVolumeById(VolumeInfo.ID_PRIVATE_INTERNAL); 56 final File dataPath = internalVolume.getPath(); 57 if (!volumeNeedsManagement(dataPath)) { 58 Log.i(TAG, "Skipping automatic storage management."); 59 Settings.Secure.putLong(getContentResolver(), 60 Settings.Secure.AUTOMATIC_STORAGE_MANAGER_LAST_RUN, 61 System.currentTimeMillis()); 62 jobFinished(args, false); 63 return false; 64 } 65 66 boolean isEnabled = 67 Settings.Secure.getInt(getContentResolver(), 68 Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED, 0) != 0; 69 if (!isEnabled) { 70 NotificationController.maybeShowNotification(getApplicationContext()); 71 jobFinished(args, false); 72 return false; 73 } 74 75 mProvider = FeatureFactory.getFactory(this).getStorageManagementJobProvider(); 76 if (mProvider != null) { 77 return mProvider.onStartJob(this, args, getDaysToRetain()); 78 } 79 80 jobFinished(args, false); 81 return false; 82 } 83 84 @Override 85 public boolean onStopJob(JobParameters args) { 86 if (mProvider != null) { 87 return mProvider.onStopJob(this, args); 88 } 89 90 return false; 91 } 92 93 private int getDaysToRetain() { 94 return Settings.Secure.getInt(getContentResolver(), 95 Settings.Secure.AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN, 96 Settings.Secure.AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_DEFAULT); 97 } 98 99 private boolean volumeNeedsManagement(final File dataPath) { 100 long lowStorageThreshold = (dataPath.getTotalSpace() * DEFAULT_LOW_FREE_PERCENT) / 100; 101 return dataPath.getFreeSpace() < lowStorageThreshold; 102 } 103 104 private boolean preconditionsFulfilled() { 105 // NOTE: We don't check the idle state here because this job should be running in idle 106 // maintenance windows. During the idle maintenance window, the device is -technically- not 107 // idle. For more information, see PowerManager.isDeviceIdleMode(). 108 109 boolean isCharging = false; 110 BatteryManager batteryManager = (BatteryManager) getSystemService(Context.BATTERY_SERVICE); 111 if (batteryManager != null) { 112 isCharging = batteryManager.isCharging(); 113 } 114 115 return isCharging; 116 } 117}