MountServiceIdler.java revision 115afdadb5863a02f0b0daefcc0511bfd35b531e
1/* 2 * Copyright (C) 2014 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.server; 18 19import java.util.Calendar; 20 21import android.app.task.Task; 22import android.app.task.TaskManager; 23import android.app.task.TaskParams; 24import android.app.task.TaskService; 25import android.content.ComponentName; 26import android.content.Context; 27import android.util.Slog; 28 29public class MountServiceIdler extends TaskService { 30 private static final String TAG = "MountServiceIdler"; 31 32 private static ComponentName sIdleService = 33 new ComponentName(MountServiceIdler.class.getPackage().getName(), 34 MountServiceIdler.class.getName()); 35 36 private static int MOUNT_TASK_ID = 808; 37 38 private boolean mStarted; 39 private TaskParams mTaskParams; 40 private Runnable mFinishCallback = new Runnable() { 41 @Override 42 public void run() { 43 Slog.i(TAG, "Got mount service completion callback"); 44 synchronized (mFinishCallback) { 45 if (mStarted) { 46 taskFinished(mTaskParams, false); 47 mStarted = false; 48 } 49 } 50 // ... and try again tomorrow 51 scheduleIdlePass(MountServiceIdler.this); 52 } 53 }; 54 55 @Override 56 public boolean onStartTask(TaskParams params) { 57 // The mount service will run an fstrim operation asynchronously 58 // on a designated separate thread, so we provide it with a callback 59 // that lets us cleanly end our idle timeslice. It's safe to call 60 // finishIdle() from any thread. 61 mTaskParams = params; 62 MountService ms = MountService.sSelf; 63 if (ms != null) { 64 synchronized (mFinishCallback) { 65 mStarted = true; 66 } 67 ms.runIdleMaintenance(mFinishCallback); 68 } 69 return ms != null; 70 } 71 72 @Override 73 public boolean onStopTask(TaskParams params) { 74 // Once we kick off the fstrim we aren't actually interruptible; just note 75 // that we don't need to call taskFinished(), and let everything happen in 76 // the callback from the mount service. 77 synchronized (mFinishCallback) { 78 mStarted = false; 79 } 80 return false; 81 } 82 83 /** 84 * Schedule the idle job that will ping the mount service 85 */ 86 public static void scheduleIdlePass(Context context) { 87 TaskManager tm = (TaskManager) context.getSystemService(Context.TASK_SERVICE); 88 89 Calendar calendar = tomorrowMidnight(); 90 final long timeToMidnight = calendar.getTimeInMillis() - System.currentTimeMillis(); 91 92 Task.Builder builder = new Task.Builder(MOUNT_TASK_ID, sIdleService); 93 builder.setRequiresDeviceIdle(true); 94 builder.setRequiresCharging(true); 95 builder.setMinimumLatency(timeToMidnight); 96 tm.schedule(builder.build()); 97 } 98 99 private static Calendar tomorrowMidnight() { 100 Calendar calendar = Calendar.getInstance(); 101 calendar.setTimeInMillis(System.currentTimeMillis()); 102 calendar.set(Calendar.HOUR, 0); 103 calendar.set(Calendar.MINUTE, 0); 104 calendar.set(Calendar.SECOND, 0); 105 calendar.set(Calendar.MILLISECOND, 0); 106 calendar.add(Calendar.DAY_OF_MONTH, 1); 107 return calendar; 108 } 109} 110