MountServiceIdler.java revision 115afdadb5863a02f0b0daefcc0511bfd35b531e
1d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate/*
2d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate * Copyright (C) 2014 The Android Open Source Project
3d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate *
4d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate * Licensed under the Apache License, Version 2.0 (the "License");
5d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate * you may not use this file except in compliance with the License.
6d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate * You may obtain a copy of the License at
7d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate *
8d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate *      http://www.apache.org/licenses/LICENSE-2.0
9d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate *
10d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate * Unless required by applicable law or agreed to in writing, software
11d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate * distributed under the License is distributed on an "AS IS" BASIS,
12d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate * See the License for the specific language governing permissions and
14d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate * limitations under the License.
15d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate */
16d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate
17d417d625d244356bc770e2692fd59e754a72f59fChristopher Tatepackage com.android.server;
18d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate
19115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tateimport java.util.Calendar;
20115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate
21115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tateimport android.app.task.Task;
22115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tateimport android.app.task.TaskManager;
23115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tateimport android.app.task.TaskParams;
24115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tateimport android.app.task.TaskService;
25115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tateimport android.content.ComponentName;
26115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tateimport android.content.Context;
27d417d625d244356bc770e2692fd59e754a72f59fChristopher Tateimport android.util.Slog;
28d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate
29115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tatepublic class MountServiceIdler extends TaskService {
30d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate    private static final String TAG = "MountServiceIdler";
31d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate
32115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate    private static ComponentName sIdleService =
33115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate            new ComponentName(MountServiceIdler.class.getPackage().getName(),
34115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate                    MountServiceIdler.class.getName());
35115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate
36115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate    private static int MOUNT_TASK_ID = 808;
37115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate
38115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate    private boolean mStarted;
39115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate    private TaskParams mTaskParams;
40d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate    private Runnable mFinishCallback = new Runnable() {
41d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate        @Override
42d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate        public void run() {
43d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate            Slog.i(TAG, "Got mount service completion callback");
44115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate            synchronized (mFinishCallback) {
45115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate                if (mStarted) {
46115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate                    taskFinished(mTaskParams, false);
47115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate                    mStarted = false;
48115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate                }
49115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate            }
50115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate            // ... and try again tomorrow
51115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate            scheduleIdlePass(MountServiceIdler.this);
52d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate        }
53d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate    };
54d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate
55d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate    @Override
56115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate    public boolean onStartTask(TaskParams params) {
57d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate        // The mount service will run an fstrim operation asynchronously
58d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate        // on a designated separate thread, so we provide it with a callback
59d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate        // that lets us cleanly end our idle timeslice.  It's safe to call
60d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate        // finishIdle() from any thread.
61115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        mTaskParams = params;
62d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate        MountService ms = MountService.sSelf;
63d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate        if (ms != null) {
64115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate            synchronized (mFinishCallback) {
65115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate                mStarted = true;
66115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate            }
67d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate            ms.runIdleMaintenance(mFinishCallback);
68d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate        }
69d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate        return ms != null;
70d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate    }
71d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate
72d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate    @Override
73115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate    public boolean onStopTask(TaskParams params) {
74115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        // Once we kick off the fstrim we aren't actually interruptible; just note
75115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        // that we don't need to call taskFinished(), and let everything happen in
76115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        // the callback from the mount service.
77115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        synchronized (mFinishCallback) {
78115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate            mStarted = false;
79115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        }
80115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        return false;
81115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate    }
82115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate
83115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate    /**
84115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate     * Schedule the idle job that will ping the mount service
85115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate     */
86115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate    public static void scheduleIdlePass(Context context) {
87115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        TaskManager tm = (TaskManager) context.getSystemService(Context.TASK_SERVICE);
88115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate
89115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        Calendar calendar = tomorrowMidnight();
90115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        final long timeToMidnight = calendar.getTimeInMillis() - System.currentTimeMillis();
91115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate
92115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        Task.Builder builder = new Task.Builder(MOUNT_TASK_ID, sIdleService);
93115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        builder.setRequiresDeviceIdle(true);
94115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        builder.setRequiresCharging(true);
95115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        builder.setMinimumLatency(timeToMidnight);
96115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        tm.schedule(builder.build());
97115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate    }
98115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate
99115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate    private static Calendar tomorrowMidnight() {
100115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        Calendar calendar = Calendar.getInstance();
101115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        calendar.setTimeInMillis(System.currentTimeMillis());
102115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        calendar.set(Calendar.HOUR, 0);
103115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        calendar.set(Calendar.MINUTE, 0);
104115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        calendar.set(Calendar.SECOND, 0);
105115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        calendar.set(Calendar.MILLISECOND, 0);
106115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        calendar.add(Calendar.DAY_OF_MONTH, 1);
107115afdadb5863a02f0b0daefcc0511bfd35b531eChristopher Tate        return calendar;
108d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate    }
109d417d625d244356bc770e2692fd59e754a72f59fChristopher Tate}
110