BackgroundDexOptService.java revision 8735f07a698218d311826a140d08d611d3c23db1
17395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom/* 27395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom * Copyright (C) 2014 The Android Open Source Project 37395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom * 47395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License"); 57395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom * you may not use this file except in compliance with the License. 67395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom * You may obtain a copy of the License at 77395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom * 87395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom * http://www.apache.org/licenses/LICENSE-2.0 97395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom * 107395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom * Unless required by applicable law or agreed to in writing, software 117395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS, 127395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom * See the License for the specific language governing permissions and 147395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom * limitations under the License. 157395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom */ 167395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom 177395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrompackage com.android.server.pm; 187395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom 1937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdilimport static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT; 2037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 212c9655b3d4c1fb0687baa14730c6d97ab5a56789Christopher Tateimport android.app.AlarmManager; 22cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tateimport android.app.job.JobInfo; 23cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tateimport android.app.job.JobParameters; 24cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tateimport android.app.job.JobScheduler; 25cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tateimport android.app.job.JobService; 26cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tateimport android.content.ComponentName; 277395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstromimport android.content.Context; 2837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdilimport android.content.Intent; 2937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdilimport android.content.IntentFilter; 3037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdilimport android.os.BatteryManager; 318735f07a698218d311826a140d08d611d3c23db1Narayan Kamathimport android.os.Environment; 327395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstromimport android.os.ServiceManager; 338735f07a698218d311826a140d08d611d3c23db1Narayan Kamathimport android.os.storage.StorageManager; 349f837a99d48c5bb8ad7fbc133943e5bf622ce065Jeff Sharkeyimport android.util.ArraySet; 357395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstromimport android.util.Log; 367395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom 378735f07a698218d311826a140d08d611d3c23db1Narayan Kamathimport java.io.File; 387395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstromimport java.util.concurrent.atomic.AtomicBoolean; 3927c073796978106746e4a51f2100b29068ab37f6Nicolas Geoffrayimport java.util.concurrent.TimeUnit; 407395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom 417395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom/** 427395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom * {@hide} 437395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom */ 44cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tatepublic class BackgroundDexOptService extends JobService { 457395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom static final String TAG = "BackgroundDexOptService"; 467395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom 472c9655b3d4c1fb0687baa14730c6d97ab5a56789Christopher Tate static final long RETRY_LATENCY = 4 * AlarmManager.INTERVAL_HOUR; 482c9655b3d4c1fb0687baa14730c6d97ab5a56789Christopher Tate 4937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil static final int JOB_IDLE_OPTIMIZE = 800; 5037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil static final int JOB_POST_BOOT_UPDATE = 801; 5137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 52cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tate private static ComponentName sDexoptServiceName = new ComponentName( 531b8b3aa265190e84467f740e99a0ade3a0e3cd67Christopher Tate "android", 54cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tate BackgroundDexOptService.class.getName()); 557395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom 56a00be9b4d521287fdf4678fb196c3e3a0053c3e4Brian Carlstrom /** 57a00be9b4d521287fdf4678fb196c3e3a0053c3e4Brian Carlstrom * Set of failed packages remembered across job runs. 58a00be9b4d521287fdf4678fb196c3e3a0053c3e4Brian Carlstrom */ 59a00be9b4d521287fdf4678fb196c3e3a0053c3e4Brian Carlstrom static final ArraySet<String> sFailedPackageNames = new ArraySet<String>(); 60a00be9b4d521287fdf4678fb196c3e3a0053c3e4Brian Carlstrom 6137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil /** 6237a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil * Atomics set to true if the JobScheduler requests an abort. 6337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil */ 6437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil final AtomicBoolean mAbortPostBootUpdate = new AtomicBoolean(false); 6537a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil final AtomicBoolean mAbortIdleOptimization = new AtomicBoolean(false); 6637a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 6737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil /** 6837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil * Atomic set to true if one job should exit early because another job was started. 6937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil */ 7037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil final AtomicBoolean mExitPostBootUpdate = new AtomicBoolean(false); 717395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom 728735f07a698218d311826a140d08d611d3c23db1Narayan Kamath private final File dataDir = Environment.getDataDirectory(); 738735f07a698218d311826a140d08d611d3c23db1Narayan Kamath 74db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle public static void schedule(Context context) { 75cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tate JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); 7637a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 7737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // Schedule a one-off job which scans installed packages and updates 7837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // out-of-date oat files. 7937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil js.schedule(new JobInfo.Builder(JOB_POST_BOOT_UPDATE, sDexoptServiceName) 8037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil .setMinimumLatency(TimeUnit.MINUTES.toMillis(1)) 8137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil .setOverrideDeadline(TimeUnit.MINUTES.toMillis(1)) 8237a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil .build()); 8337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 8437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // Schedule a daily job which scans installed packages and compiles 8537a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // those with fresh profiling data. 8637a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil js.schedule(new JobInfo.Builder(JOB_IDLE_OPTIMIZE, sDexoptServiceName) 8737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil .setRequiresDeviceIdle(true) 8837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil .setRequiresCharging(true) 8937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil .setPeriodic(TimeUnit.DAYS.toMillis(1)) 9037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil .build()); 9137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 9237a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (DEBUG_DEXOPT) { 9337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil Log.i(TAG, "Jobs scheduled"); 9437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 957395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom } 967395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom 97ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil public static void notifyPackageChanged(String packageName) { 98ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil // The idle maintanance job skips packages which previously failed to 99ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil // compile. The given package has changed and may successfully compile 100ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil // now. Remove it from the list of known failing packages. 101ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil synchronized (sFailedPackageNames) { 102ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil sFailedPackageNames.remove(packageName); 103ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil } 104ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil } 105ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil 10637a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // Returns the current battery level as a 0-100 integer. 10737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil private int getBatteryLevel() { 10837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); 10937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil Intent intent = registerReceiver(null, filter); 11037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); 11137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); 112cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tate 11337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (level < 0 || scale <= 0) { 11437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // Battery data unavailable. This should never happen, so assume the worst. 11537a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil return 0; 1167395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom } 11737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 11837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil return (100 * level / scale); 11937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 12037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 1218735f07a698218d311826a140d08d611d3c23db1Narayan Kamath private long getLowStorageThreshold() { 1228735f07a698218d311826a140d08d611d3c23db1Narayan Kamath @SuppressWarnings("deprecation") 1238735f07a698218d311826a140d08d611d3c23db1Narayan Kamath final long lowThreshold = StorageManager.from(this).getStorageLowBytes(dataDir); 1248735f07a698218d311826a140d08d611d3c23db1Narayan Kamath if (lowThreshold == 0) { 1258735f07a698218d311826a140d08d611d3c23db1Narayan Kamath Log.e(TAG, "Invalid low storage threshold"); 1268735f07a698218d311826a140d08d611d3c23db1Narayan Kamath } 1278735f07a698218d311826a140d08d611d3c23db1Narayan Kamath 1288735f07a698218d311826a140d08d611d3c23db1Narayan Kamath return lowThreshold; 1298735f07a698218d311826a140d08d611d3c23db1Narayan Kamath } 1308735f07a698218d311826a140d08d611d3c23db1Narayan Kamath 13137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil private boolean runPostBootUpdate(final JobParameters jobParams, 13237a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil final PackageManagerService pm, final ArraySet<String> pkgs) { 13337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (mExitPostBootUpdate.get()) { 13437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // This job has already been superseded. Do not start it. 1357395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom return false; 1367395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom } 137cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tate 13837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // Load low battery threshold from the system config. This is a 0-100 integer. 13937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil final int lowBatteryThreshold = getResources().getInteger( 14037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil com.android.internal.R.integer.config_lowBatteryWarningLevel); 14137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 1428735f07a698218d311826a140d08d611d3c23db1Narayan Kamath final long lowThreshold = getLowStorageThreshold(); 1438735f07a698218d311826a140d08d611d3c23db1Narayan Kamath 14437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil mAbortPostBootUpdate.set(false); 14537a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil new Thread("BackgroundDexOptService_PostBootUpdate") { 1467395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom @Override 1477395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom public void run() { 1487395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom for (String pkg : pkgs) { 14937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (mAbortPostBootUpdate.get()) { 15037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // JobScheduler requested an early abort. 15137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil return; 15237a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 15337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (mExitPostBootUpdate.get()) { 15437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // Different job, which supersedes this one, is running. 15537a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil break; 15637a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 15737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (getBatteryLevel() < lowBatteryThreshold) { 15837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // Rather bail than completely drain the battery. 15937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil break; 16037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 1618735f07a698218d311826a140d08d611d3c23db1Narayan Kamath long usableSpace = dataDir.getUsableSpace(); 1628735f07a698218d311826a140d08d611d3c23db1Narayan Kamath if (usableSpace < lowThreshold) { 1638735f07a698218d311826a140d08d611d3c23db1Narayan Kamath // Rather bail than completely fill up the disk. 1648735f07a698218d311826a140d08d611d3c23db1Narayan Kamath Log.w(TAG, "Aborting background dex opt job due to low storage: " + 1658735f07a698218d311826a140d08d611d3c23db1Narayan Kamath usableSpace); 1668735f07a698218d311826a140d08d611d3c23db1Narayan Kamath break; 1678735f07a698218d311826a140d08d611d3c23db1Narayan Kamath } 1688735f07a698218d311826a140d08d611d3c23db1Narayan Kamath 16937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (DEBUG_DEXOPT) { 17037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil Log.i(TAG, "Updating package " + pkg); 17137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 1728412cf4daaa437003f4a79a82aa35465c4f0d418Calin Juravle 17337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // Update package if needed. Note that there can be no race between concurrent 17437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // jobs because PackageDexOptimizer.performDexOpt is synchronized. 1758412cf4daaa437003f4a79a82aa35465c4f0d418Calin Juravle 1768412cf4daaa437003f4a79a82aa35465c4f0d418Calin Juravle // checkProfiles is false to avoid merging profiles during boot which 1778412cf4daaa437003f4a79a82aa35465c4f0d418Calin Juravle // might interfere with background compilation (b/28612421). 1788412cf4daaa437003f4a79a82aa35465c4f0d418Calin Juravle // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will 1798412cf4daaa437003f4a79a82aa35465c4f0d418Calin Juravle // behave differently than "pm.dexopt.bg-dexopt=speed-profile" but that's a 1808412cf4daaa437003f4a79a82aa35465c4f0d418Calin Juravle // trade-off worth doing to save boot time work. 18137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil pm.performDexOpt(pkg, 1828412cf4daaa437003f4a79a82aa35465c4f0d418Calin Juravle /* checkProfiles */ false, 18337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil PackageManagerService.REASON_BOOT, 18437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil /* force */ false); 18537a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 18637a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // Ran to completion, so we abandon our timeslice and do not reschedule. 18737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil jobFinished(jobParams, /* reschedule */ false); 18837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 18937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil }.start(); 19037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil return true; 19137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 19237a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 19337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil private boolean runIdleOptimization(final JobParameters jobParams, 19437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil final PackageManagerService pm, final ArraySet<String> pkgs) { 19537a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // If post-boot update is still running, request that it exits early. 19637a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil mExitPostBootUpdate.set(true); 19737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 19837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil mAbortIdleOptimization.set(false); 1998735f07a698218d311826a140d08d611d3c23db1Narayan Kamath 2008735f07a698218d311826a140d08d611d3c23db1Narayan Kamath final long lowThreshold = getLowStorageThreshold(); 2018735f07a698218d311826a140d08d611d3c23db1Narayan Kamath 20237a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil new Thread("BackgroundDexOptService_IdleOptimization") { 20337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil @Override 20437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil public void run() { 20537a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil for (String pkg : pkgs) { 20637a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (mAbortIdleOptimization.get()) { 20737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // JobScheduler requested an early abort. 208cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tate return; 2097395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom } 210a00be9b4d521287fdf4678fb196c3e3a0053c3e4Brian Carlstrom if (sFailedPackageNames.contains(pkg)) { 21137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // Skip previously failing package 212a00be9b4d521287fdf4678fb196c3e3a0053c3e4Brian Carlstrom continue; 213a00be9b4d521287fdf4678fb196c3e3a0053c3e4Brian Carlstrom } 2148735f07a698218d311826a140d08d611d3c23db1Narayan Kamath 2158735f07a698218d311826a140d08d611d3c23db1Narayan Kamath long usableSpace = dataDir.getUsableSpace(); 2168735f07a698218d311826a140d08d611d3c23db1Narayan Kamath if (usableSpace < lowThreshold) { 2178735f07a698218d311826a140d08d611d3c23db1Narayan Kamath // Rather bail than completely fill up the disk. 2188735f07a698218d311826a140d08d611d3c23db1Narayan Kamath Log.w(TAG, "Aborting background dex opt job due to low storage: " + 2198735f07a698218d311826a140d08d611d3c23db1Narayan Kamath usableSpace); 2208735f07a698218d311826a140d08d611d3c23db1Narayan Kamath break; 2218735f07a698218d311826a140d08d611d3c23db1Narayan Kamath } 2228735f07a698218d311826a140d08d611d3c23db1Narayan Kamath 22380932c1418f22fa2ab49aa1eea8337b8f29b9bccDavid Brazdil // Conservatively add package to the list of failing ones in case performDexOpt 22480932c1418f22fa2ab49aa1eea8337b8f29b9bccDavid Brazdil // never returns. 225ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil synchronized (sFailedPackageNames) { 226ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil sFailedPackageNames.add(pkg); 227ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil } 22837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // Optimize package if needed. Note that there can be no race between 22937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized. 23080932c1418f22fa2ab49aa1eea8337b8f29b9bccDavid Brazdil if (pm.performDexOpt(pkg, 23137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil /* checkProfiles */ true, 23237a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil PackageManagerService.REASON_BACKGROUND_DEXOPT, 23337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil /* force */ false)) { 23480932c1418f22fa2ab49aa1eea8337b8f29b9bccDavid Brazdil // Dexopt succeeded, remove package from the list of failing ones. 235ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil synchronized (sFailedPackageNames) { 236ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil sFailedPackageNames.remove(pkg); 237ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil } 238a00be9b4d521287fdf4678fb196c3e3a0053c3e4Brian Carlstrom } 2397395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom } 24037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // Ran to completion, so we abandon our timeslice and do not reschedule. 24137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil jobFinished(jobParams, /* reschedule */ false); 2427395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom } 2437395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom }.start(); 2447395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom return true; 2457395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom } 2467395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom 247cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tate @Override 24837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil public boolean onStartJob(JobParameters params) { 24937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (DEBUG_DEXOPT) { 25037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil Log.i(TAG, "onStartJob"); 25137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 25237a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 2538735f07a698218d311826a140d08d611d3c23db1Narayan Kamath // NOTE: PackageManagerService.isStorageLow uses a different set of criteria from 2548735f07a698218d311826a140d08d611d3c23db1Narayan Kamath // the checks above. This check is not "live" - the value is determined by a background 2558735f07a698218d311826a140d08d611d3c23db1Narayan Kamath // restart with a period of ~1 minute. 25637a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package"); 25737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (pm.isStorageLow()) { 25837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (DEBUG_DEXOPT) { 25937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil Log.i(TAG, "Low storage, skipping this run"); 26037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 26137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil return false; 26237a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 26337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 26437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil final ArraySet<String> pkgs = pm.getOptimizablePackages(); 26537a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (pkgs == null || pkgs.isEmpty()) { 26637a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (DEBUG_DEXOPT) { 26737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil Log.i(TAG, "No packages to optimize"); 26837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 26937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil return false; 27037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 27137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 27237a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (params.getJobId() == JOB_POST_BOOT_UPDATE) { 27337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil return runPostBootUpdate(params, pm, pkgs); 27437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } else { 27537a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil return runIdleOptimization(params, pm, pkgs); 27637a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 27737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 27837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 27937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil @Override 280cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tate public boolean onStopJob(JobParameters params) { 28137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (DEBUG_DEXOPT) { 28237a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil Log.i(TAG, "onStopJob"); 28337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 28437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 28537a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (params.getJobId() == JOB_POST_BOOT_UPDATE) { 28637a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil mAbortPostBootUpdate.set(true); 28737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } else { 28837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil mAbortIdleOptimization.set(true); 28937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 290cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tate return false; 2917395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom } 2927395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom} 293