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