blob: af20679fc2509b06733f31a87cc60a065e6bd71a [file] [log] [blame]
Brian Carlstrom7395a8a2014-04-28 22:11:01 -07001/*
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.pm;
18
Christopher Tate2c9655b2015-06-12 13:06:45 -070019import android.app.AlarmManager;
Christopher Tatecf1a2f72014-06-16 15:51:39 -070020import android.app.job.JobInfo;
21import android.app.job.JobParameters;
22import android.app.job.JobScheduler;
23import android.app.job.JobService;
24import android.content.ComponentName;
Brian Carlstrom7395a8a2014-04-28 22:11:01 -070025import android.content.Context;
Brian Carlstrom7395a8a2014-04-28 22:11:01 -070026import android.os.ServiceManager;
Jeff Sharkey9f837a92014-10-24 12:07:24 -070027import android.util.ArraySet;
Brian Carlstrom7395a8a2014-04-28 22:11:01 -070028import android.util.Log;
29
Brian Carlstrom7395a8a2014-04-28 22:11:01 -070030import java.util.concurrent.atomic.AtomicBoolean;
Nicolas Geoffray27c07372015-11-05 16:54:09 +000031import java.util.concurrent.TimeUnit;
Brian Carlstrom7395a8a2014-04-28 22:11:01 -070032
33/**
34 * {@hide}
35 */
Christopher Tatecf1a2f72014-06-16 15:51:39 -070036public class BackgroundDexOptService extends JobService {
Brian Carlstrom7395a8a2014-04-28 22:11:01 -070037 static final String TAG = "BackgroundDexOptService";
38
Christopher Tate2c9655b2015-06-12 13:06:45 -070039 static final long RETRY_LATENCY = 4 * AlarmManager.INTERVAL_HOUR;
40
Christopher Tate1b8b3aa2014-06-20 13:17:01 -070041 static final int BACKGROUND_DEXOPT_JOB = 800;
Christopher Tatecf1a2f72014-06-16 15:51:39 -070042 private static ComponentName sDexoptServiceName = new ComponentName(
Christopher Tate1b8b3aa2014-06-20 13:17:01 -070043 "android",
Christopher Tatecf1a2f72014-06-16 15:51:39 -070044 BackgroundDexOptService.class.getName());
Brian Carlstrom7395a8a2014-04-28 22:11:01 -070045
Brian Carlstroma00be9b2014-12-12 13:14:36 -080046 /**
47 * Set of failed packages remembered across job runs.
48 */
49 static final ArraySet<String> sFailedPackageNames = new ArraySet<String>();
50
Brian Carlstrom7395a8a2014-04-28 22:11:01 -070051 final AtomicBoolean mIdleTime = new AtomicBoolean(false);
52
Christopher Tate2c9655b2015-06-12 13:06:45 -070053 public static void schedule(Context context, long minLatency) {
Christopher Tatecf1a2f72014-06-16 15:51:39 -070054 JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
55 JobInfo job = new JobInfo.Builder(BACKGROUND_DEXOPT_JOB, sDexoptServiceName)
56 .setRequiresDeviceIdle(true)
57 .setRequiresCharging(true)
Christopher Tate2c9655b2015-06-12 13:06:45 -070058 .setMinimumLatency(minLatency)
Nicolas Geoffray27c07372015-11-05 16:54:09 +000059 .setPeriodic(TimeUnit.DAYS.toMillis(1))
Christopher Tatecf1a2f72014-06-16 15:51:39 -070060 .build();
61 js.schedule(job);
Brian Carlstrom7395a8a2014-04-28 22:11:01 -070062 }
63
Christopher Tatecf1a2f72014-06-16 15:51:39 -070064 @Override
65 public boolean onStartJob(JobParameters params) {
Brian Carlstrom7395a8a2014-04-28 22:11:01 -070066 Log.i(TAG, "onIdleStart");
Christopher Tatecf1a2f72014-06-16 15:51:39 -070067 final PackageManagerService pm =
68 (PackageManagerService)ServiceManager.getService("package");
69
70 if (pm.isStorageLow()) {
Christopher Tate2c9655b2015-06-12 13:06:45 -070071 schedule(BackgroundDexOptService.this, RETRY_LATENCY);
Brian Carlstrom7395a8a2014-04-28 22:11:01 -070072 return false;
73 }
Jeff Sharkey9f837a92014-10-24 12:07:24 -070074 final ArraySet<String> pkgs = pm.getPackagesThatNeedDexOpt();
Brian Carlstrom7395a8a2014-04-28 22:11:01 -070075 if (pkgs == null) {
76 return false;
77 }
Christopher Tatecf1a2f72014-06-16 15:51:39 -070078
79 final JobParameters jobParams = params;
Brian Carlstrom7395a8a2014-04-28 22:11:01 -070080 mIdleTime.set(true);
81 new Thread("BackgroundDexOptService_DexOpter") {
82 @Override
83 public void run() {
84 for (String pkg : pkgs) {
85 if (!mIdleTime.get()) {
Christopher Tatecf1a2f72014-06-16 15:51:39 -070086 // stopped while still working, so we need to reschedule
Christopher Tate2c9655b2015-06-12 13:06:45 -070087 schedule(BackgroundDexOptService.this, 0);
Christopher Tatecf1a2f72014-06-16 15:51:39 -070088 return;
Brian Carlstrom7395a8a2014-04-28 22:11:01 -070089 }
Brian Carlstroma00be9b2014-12-12 13:14:36 -080090 if (sFailedPackageNames.contains(pkg)) {
91 // skip previously failing package
92 continue;
93 }
Nicolas Geoffray27c07372015-11-05 16:54:09 +000094 if (!pm.performDexOpt(pkg, null /* instruction set */)) {
Brian Carlstroma00be9b2014-12-12 13:14:36 -080095 // there was a problem running dexopt,
96 // remember this so we do not keep retrying.
97 sFailedPackageNames.add(pkg);
98 }
Brian Carlstrom7395a8a2014-04-28 22:11:01 -070099 }
Christopher Tatecf1a2f72014-06-16 15:51:39 -0700100 // ran to completion, so we abandon our timeslice and do not reschedule
101 jobFinished(jobParams, false);
Brian Carlstrom7395a8a2014-04-28 22:11:01 -0700102 }
103 }.start();
104 return true;
105 }
106
Christopher Tatecf1a2f72014-06-16 15:51:39 -0700107 @Override
108 public boolean onStopJob(JobParameters params) {
Brian Carlstrom7395a8a2014-04-28 22:11:01 -0700109 Log.i(TAG, "onIdleStop");
110 mIdleTime.set(false);
Christopher Tatecf1a2f72014-06-16 15:51:39 -0700111 return false;
Brian Carlstrom7395a8a2014-04-28 22:11:01 -0700112 }
113}