BackgroundDexOptService.java revision 246dccf9327631597767afe418ce43ae6d07d102
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 21cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tateimport android.app.job.JobInfo; 22cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tateimport android.app.job.JobParameters; 23cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tateimport android.app.job.JobScheduler; 24cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tateimport android.app.job.JobService; 25cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tateimport android.content.ComponentName; 267395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstromimport android.content.Context; 2737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdilimport android.content.Intent; 2837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdilimport android.content.IntentFilter; 2937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdilimport android.os.BatteryManager; 308735f07a698218d311826a140d08d611d3c23db1Narayan Kamathimport android.os.Environment; 317395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstromimport android.os.ServiceManager; 3251f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravleimport android.os.SystemProperties; 338735f07a698218d311826a140d08d611d3c23db1Narayan Kamathimport android.os.storage.StorageManager; 349f837a99d48c5bb8ad7fbc133943e5bf622ce065Jeff Sharkeyimport android.util.ArraySet; 357395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstromimport android.util.Log; 367395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom 3751f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravleimport com.android.server.pm.dex.DexManager; 38f107a23ff165bbb7f0ae145f9ac85ddca8b43ed7Carmen Jacksonimport com.android.server.LocalServices; 39f107a23ff165bbb7f0ae145f9ac85ddca8b43ed7Carmen Jacksonimport com.android.server.PinnerService; 4051f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle 418735f07a698218d311826a140d08d611d3c23db1Narayan Kamathimport java.io.File; 42246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmeraimport java.util.Set; 437395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstromimport java.util.concurrent.atomic.AtomicBoolean; 4427c073796978106746e4a51f2100b29068ab37f6Nicolas Geoffrayimport java.util.concurrent.TimeUnit; 457395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom 467395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom/** 477395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom * {@hide} 487395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom */ 49cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tatepublic class BackgroundDexOptService extends JobService { 50a50d58e22630cd651a815381639e70476991bdbfCalin Juravle private static final String TAG = "BackgroundDexOptService"; 517395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom 52a50d58e22630cd651a815381639e70476991bdbfCalin Juravle private static final boolean DEBUG = false; 532c9655b3d4c1fb0687baa14730c6d97ab5a56789Christopher Tate 54a50d58e22630cd651a815381639e70476991bdbfCalin Juravle private static final int JOB_IDLE_OPTIMIZE = 800; 55a50d58e22630cd651a815381639e70476991bdbfCalin Juravle private static final int JOB_POST_BOOT_UPDATE = 801; 56a50d58e22630cd651a815381639e70476991bdbfCalin Juravle 57a50d58e22630cd651a815381639e70476991bdbfCalin Juravle private static final long IDLE_OPTIMIZATION_PERIOD = DEBUG 58a50d58e22630cd651a815381639e70476991bdbfCalin Juravle ? TimeUnit.MINUTES.toMillis(1) 59a50d58e22630cd651a815381639e70476991bdbfCalin Juravle : TimeUnit.DAYS.toMillis(1); 6037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 61cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tate private static ComponentName sDexoptServiceName = new ComponentName( 621b8b3aa265190e84467f740e99a0ade3a0e3cd67Christopher Tate "android", 63cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tate BackgroundDexOptService.class.getName()); 647395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom 6551f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle // Possible return codes of individual optimization steps. 6651f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle 6751f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle // Optimizations finished. All packages were processed. 6851f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle private static final int OPTIMIZE_PROCESSED = 0; 6951f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle // Optimizations should continue. Issued after checking the scheduler, disk space or battery. 7051f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle private static final int OPTIMIZE_CONTINUE = 1; 7151f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle // Optimizations should be aborted. Job scheduler requested it. 7251f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle private static final int OPTIMIZE_ABORT_BY_JOB_SCHEDULER = 2; 7351f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle // Optimizations should be aborted. No space left on device. 7451f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle private static final int OPTIMIZE_ABORT_NO_SPACE_LEFT = 3; 7551f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle 76246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera // Used for calculating space threshold for downgrading unused apps. 77246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera private static final int LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE = 2; 78246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera 79a00be9b4d521287fdf4678fb196c3e3a0053c3e4Brian Carlstrom /** 80a00be9b4d521287fdf4678fb196c3e3a0053c3e4Brian Carlstrom * Set of failed packages remembered across job runs. 81a00be9b4d521287fdf4678fb196c3e3a0053c3e4Brian Carlstrom */ 8251f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle static final ArraySet<String> sFailedPackageNamesPrimary = new ArraySet<String>(); 8351f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle static final ArraySet<String> sFailedPackageNamesSecondary = new ArraySet<String>(); 84a00be9b4d521287fdf4678fb196c3e3a0053c3e4Brian Carlstrom 8537a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil /** 8637a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil * Atomics set to true if the JobScheduler requests an abort. 8737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil */ 8851f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle private final AtomicBoolean mAbortPostBootUpdate = new AtomicBoolean(false); 8951f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle private final AtomicBoolean mAbortIdleOptimization = new AtomicBoolean(false); 9037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 9137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil /** 9237a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil * Atomic set to true if one job should exit early because another job was started. 9337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil */ 9451f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle private final AtomicBoolean mExitPostBootUpdate = new AtomicBoolean(false); 957395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom 96be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle private final File mDataDir = Environment.getDataDirectory(); 978735f07a698218d311826a140d08d611d3c23db1Narayan Kamath 98246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera private static final long mDowngradeUnusedAppsThresholdInMillis = 99246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera getDowngradeUnusedAppsThresholdInMillis(); 100246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera 101db4a79a5d7d348e9d2286d95d4e5a59dd484456fCalin Juravle public static void schedule(Context context) { 102cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tate JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); 10337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 10437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // Schedule a one-off job which scans installed packages and updates 10537a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // out-of-date oat files. 10637a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil js.schedule(new JobInfo.Builder(JOB_POST_BOOT_UPDATE, sDexoptServiceName) 10737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil .setMinimumLatency(TimeUnit.MINUTES.toMillis(1)) 10837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil .setOverrideDeadline(TimeUnit.MINUTES.toMillis(1)) 10937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil .build()); 11037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 11137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // Schedule a daily job which scans installed packages and compiles 11237a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // those with fresh profiling data. 11337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil js.schedule(new JobInfo.Builder(JOB_IDLE_OPTIMIZE, sDexoptServiceName) 11437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil .setRequiresDeviceIdle(true) 11537a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil .setRequiresCharging(true) 116a50d58e22630cd651a815381639e70476991bdbfCalin Juravle .setPeriodic(IDLE_OPTIMIZATION_PERIOD) 11737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil .build()); 11837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 11937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (DEBUG_DEXOPT) { 12037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil Log.i(TAG, "Jobs scheduled"); 12137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 1227395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom } 1237395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom 124ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil public static void notifyPackageChanged(String packageName) { 125ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil // The idle maintanance job skips packages which previously failed to 126ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil // compile. The given package has changed and may successfully compile 127ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil // now. Remove it from the list of known failing packages. 12851f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle synchronized (sFailedPackageNamesPrimary) { 12951f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle sFailedPackageNamesPrimary.remove(packageName); 13051f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle } 13151f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle synchronized (sFailedPackageNamesSecondary) { 13251f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle sFailedPackageNamesSecondary.remove(packageName); 133ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil } 134ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil } 135ace80c56d7c63dadead34539b643f69a1b7336e8David Brazdil 13637a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // Returns the current battery level as a 0-100 integer. 13737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil private int getBatteryLevel() { 13837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); 13937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil Intent intent = registerReceiver(null, filter); 14037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); 14137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); 142cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tate 14337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (level < 0 || scale <= 0) { 14437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // Battery data unavailable. This should never happen, so assume the worst. 14537a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil return 0; 1467395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom } 14737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 14837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil return (100 * level / scale); 14937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 15037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 151c660475aafe91269be306c802823cf543005ce36Calin Juravle private long getLowStorageThreshold(Context context) { 1528735f07a698218d311826a140d08d611d3c23db1Narayan Kamath @SuppressWarnings("deprecation") 153c660475aafe91269be306c802823cf543005ce36Calin Juravle final long lowThreshold = StorageManager.from(context).getStorageLowBytes(mDataDir); 1548735f07a698218d311826a140d08d611d3c23db1Narayan Kamath if (lowThreshold == 0) { 1558735f07a698218d311826a140d08d611d3c23db1Narayan Kamath Log.e(TAG, "Invalid low storage threshold"); 1568735f07a698218d311826a140d08d611d3c23db1Narayan Kamath } 1578735f07a698218d311826a140d08d611d3c23db1Narayan Kamath 1588735f07a698218d311826a140d08d611d3c23db1Narayan Kamath return lowThreshold; 1598735f07a698218d311826a140d08d611d3c23db1Narayan Kamath } 1608735f07a698218d311826a140d08d611d3c23db1Narayan Kamath 16137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil private boolean runPostBootUpdate(final JobParameters jobParams, 16237a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil final PackageManagerService pm, final ArraySet<String> pkgs) { 16337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (mExitPostBootUpdate.get()) { 16437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // This job has already been superseded. Do not start it. 1657395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom return false; 1667395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom } 167be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle new Thread("BackgroundDexOptService_PostBootUpdate") { 168be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle @Override 169be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle public void run() { 170be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle postBootUpdate(jobParams, pm, pkgs); 171be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle } 172be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle 173be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle }.start(); 174be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle return true; 175be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle } 176cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tate 177be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle private void postBootUpdate(JobParameters jobParams, PackageManagerService pm, 178be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle ArraySet<String> pkgs) { 17937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // Load low battery threshold from the system config. This is a 0-100 integer. 18037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil final int lowBatteryThreshold = getResources().getInteger( 18137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil com.android.internal.R.integer.config_lowBatteryWarningLevel); 182c660475aafe91269be306c802823cf543005ce36Calin Juravle final long lowThreshold = getLowStorageThreshold(this); 1838735f07a698218d311826a140d08d611d3c23db1Narayan Kamath 18437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil mAbortPostBootUpdate.set(false); 185be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle 18631ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle ArraySet<String> updatedPackages = new ArraySet<>(); 187be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle for (String pkg : pkgs) { 188be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle if (mAbortPostBootUpdate.get()) { 189be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle // JobScheduler requested an early abort. 190be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle return; 191be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle } 192be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle if (mExitPostBootUpdate.get()) { 193be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle // Different job, which supersedes this one, is running. 194be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle break; 195be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle } 196be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle if (getBatteryLevel() < lowBatteryThreshold) { 197be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle // Rather bail than completely drain the battery. 198be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle break; 199be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle } 200be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle long usableSpace = mDataDir.getUsableSpace(); 201be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle if (usableSpace < lowThreshold) { 202be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle // Rather bail than completely fill up the disk. 203be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle Log.w(TAG, "Aborting background dex opt job due to low storage: " + 204be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle usableSpace); 205be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle break; 206be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle } 207be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle 208be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle if (DEBUG_DEXOPT) { 209be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle Log.i(TAG, "Updating package " + pkg); 210be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle } 211be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle 212be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle // Update package if needed. Note that there can be no race between concurrent 213be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle // jobs because PackageDexOptimizer.performDexOpt is synchronized. 214be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle 215be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle // checkProfiles is false to avoid merging profiles during boot which 216be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle // might interfere with background compilation (b/28612421). 217be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will 218be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle // behave differently than "pm.dexopt.bg-dexopt=speed-profile" but that's a 219be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle // trade-off worth doing to save boot time work. 22031ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle int result = pm.performDexOptWithStatus(pkg, 221be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle /* checkProfiles */ false, 222be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle PackageManagerService.REASON_BOOT, 2233b4359a06c482095338080fa908a67441ad23a2bNicolas Geoffray /* force */ false, 224246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera /* bootComplete */ true, 225246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera /* downgrade */ false); 22631ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle if (result == PackageDexOptimizer.DEX_OPT_PERFORMED) { 22731ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle updatedPackages.add(pkg); 22831ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle } 229be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle } 23031ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle notifyPinService(updatedPackages); 231be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle // Ran to completion, so we abandon our timeslice and do not reschedule. 232be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle jobFinished(jobParams, /* reschedule */ false); 233be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle } 234be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle 235be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle private boolean runIdleOptimization(final JobParameters jobParams, 236be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle final PackageManagerService pm, final ArraySet<String> pkgs) { 237be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle new Thread("BackgroundDexOptService_IdleOptimization") { 2387395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom @Override 2397395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom public void run() { 24051f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle int result = idleOptimization(pm, pkgs, BackgroundDexOptService.this); 24151f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle if (result != OPTIMIZE_ABORT_BY_JOB_SCHEDULER) { 24251f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle Log.w(TAG, "Idle optimizations aborted because of space constraints."); 243c660475aafe91269be306c802823cf543005ce36Calin Juravle // If we didn't abort we ran to completion (or stopped because of space). 244c660475aafe91269be306c802823cf543005ce36Calin Juravle // Abandon our timeslice and do not reschedule. 245c660475aafe91269be306c802823cf543005ce36Calin Juravle jobFinished(jobParams, /* reschedule */ false); 246c660475aafe91269be306c802823cf543005ce36Calin Juravle } 24737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 24837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil }.start(); 24937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil return true; 25037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 25137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 25251f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle // Optimize the given packages and return the optimization result (one of the OPTIMIZE_* codes). 253246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera private int idleOptimization(PackageManagerService pm, ArraySet<String> pkgs, 254246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera Context context) { 255a50d58e22630cd651a815381639e70476991bdbfCalin Juravle Log.i(TAG, "Performing idle optimizations"); 25637a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil // If post-boot update is still running, request that it exits early. 25737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil mExitPostBootUpdate.set(true); 25837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil mAbortIdleOptimization.set(false); 2598735f07a698218d311826a140d08d611d3c23db1Narayan Kamath 260c660475aafe91269be306c802823cf543005ce36Calin Juravle long lowStorageThreshold = getLowStorageThreshold(context); 26151f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle // Optimize primary apks. 26251f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle int result = optimizePackages(pm, pkgs, lowStorageThreshold, /*is_for_primary_dex*/ true, 26351f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle sFailedPackageNamesPrimary); 26451f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle 26551f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle if (result == OPTIMIZE_ABORT_BY_JOB_SCHEDULER) { 26651f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle return result; 26751f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle } 26851f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle 2694466c5ad84e4429284b7d5e13ad8a87c924ea7fcCalin Juravle if (SystemProperties.getBoolean("dalvik.vm.dexopt.secondary", false)) { 27051f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle result = reconcileSecondaryDexFiles(pm.getDexManager()); 27151f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle if (result == OPTIMIZE_ABORT_BY_JOB_SCHEDULER) { 27251f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle return result; 27351f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle } 27451f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle 27551f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle result = optimizePackages(pm, pkgs, lowStorageThreshold, /*is_for_primary_dex*/ false, 27651f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle sFailedPackageNamesSecondary); 27751f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle } 27851f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle return result; 279c660475aafe91269be306c802823cf543005ce36Calin Juravle } 280c660475aafe91269be306c802823cf543005ce36Calin Juravle 28151f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle private int optimizePackages(PackageManagerService pm, ArraySet<String> pkgs, 28251f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle long lowStorageThreshold, boolean is_for_primary_dex, 28351f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle ArraySet<String> failedPackageNames) { 28431ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle ArraySet<String> updatedPackages = new ArraySet<>(); 285246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera Set<String> unusedPackages = pm.getUnusedPackages(mDowngradeUnusedAppsThresholdInMillis); 286246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera // Only downgrade apps when space is low on device. 287246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera // Threshold is selected above the lowStorageThreshold so that we can pro-actively clean 288246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera // up disk before user hits the actual lowStorageThreshold. 289246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera final long lowStorageThresholdForDowngrade = LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE * 290246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera lowStorageThreshold; 291246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera boolean shouldDowngrade = shouldDowngrade(lowStorageThresholdForDowngrade); 292be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle for (String pkg : pkgs) { 29351f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle int abort_code = abortIdleOptimizations(lowStorageThreshold); 294246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera if (abort_code == OPTIMIZE_ABORT_BY_JOB_SCHEDULER) { 29551f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle return abort_code; 296be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle } 2978735f07a698218d311826a140d08d611d3c23db1Narayan Kamath 29851f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle synchronized (failedPackageNames) { 29951f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle if (failedPackageNames.contains(pkg)) { 300be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle // Skip previously failing package 301be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle continue; 302246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera } 303246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera } 304246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera 305246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera int reason; 306246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera boolean downgrade; 307246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera // Downgrade unused packages. 308246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera if (unusedPackages.contains(pkg) && shouldDowngrade) { 309246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera // This applies for system apps or if packages location is not a directory, i.e. 310246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera // monolithic install. 311246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera if (is_for_primary_dex && !pm.canHaveOatDir(pkg)) { 312246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera // For apps that don't have the oat directory, instead of downgrading, 313246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera // remove their compiler artifacts from dalvik cache. 314246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera pm.deleteOatArtifactsOfPackage(pkg); 315246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera continue; 316c660475aafe91269be306c802823cf543005ce36Calin Juravle } else { 317246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera reason = PackageManagerService.REASON_INACTIVE_PACKAGE_DOWNGRADE; 318246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera downgrade = true; 3197395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom } 320246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera } else if (abort_code != OPTIMIZE_ABORT_NO_SPACE_LEFT) { 321246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera reason = PackageManagerService.REASON_BACKGROUND_DEXOPT; 322246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera downgrade = false; 323246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera } else { 324246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera // can't dexopt because of low space. 325246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera continue; 326246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera } 327246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera 328246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera synchronized (failedPackageNames) { 329246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera // Conservatively add package to the list of failing ones in case 330246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera // performDexOpt never returns. 331246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera failedPackageNames.add(pkg); 3327395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom } 333be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle 334be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle // Optimize package if needed. Note that there can be no race between 335be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle // concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized. 33631ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle boolean success; 33731ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle if (is_for_primary_dex) { 33831ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle int result = pm.performDexOptWithStatus(pkg, 33931ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle /* checkProfiles */ true, 340246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera reason, 341246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera false /* forceCompile*/, 342246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera true /* bootComplete */, 343246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera downgrade); 34431ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle success = result != PackageDexOptimizer.DEX_OPT_FAILED; 34531ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle if (result == PackageDexOptimizer.DEX_OPT_PERFORMED) { 34631ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle updatedPackages.add(pkg); 34731ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle } 34831ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle } else { 34931ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle success = pm.performDexOptSecondary(pkg, 350246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera reason, 351246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera false /* force */, 352246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera downgrade); 35331ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle } 35451f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle if (success) { 355be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle // Dexopt succeeded, remove package from the list of failing ones. 35651f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle synchronized (failedPackageNames) { 35751f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle failedPackageNames.remove(pkg); 358be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle } 359be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle } 360be6a71a0b3f369843a26c91dd5123d0499f00e7eCalin Juravle } 36131ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle notifyPinService(updatedPackages); 36251f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle return OPTIMIZE_PROCESSED; 36351f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle } 36451f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle 36551f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle private int reconcileSecondaryDexFiles(DexManager dm) { 36651f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle // TODO(calin): should we blacklist packages for which we fail to reconcile? 36751f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle for (String p : dm.getAllPackagesWithSecondaryDexFiles()) { 36851f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle if (mAbortIdleOptimization.get()) { 36951f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle return OPTIMIZE_ABORT_BY_JOB_SCHEDULER; 37051f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle } 37151f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle dm.reconcileSecondaryDexFiles(p); 37251f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle } 37351f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle return OPTIMIZE_PROCESSED; 374c660475aafe91269be306c802823cf543005ce36Calin Juravle } 375c660475aafe91269be306c802823cf543005ce36Calin Juravle 37651f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle // Evaluate whether or not idle optimizations should continue. 37751f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle private int abortIdleOptimizations(long lowStorageThreshold) { 378c660475aafe91269be306c802823cf543005ce36Calin Juravle if (mAbortIdleOptimization.get()) { 379c660475aafe91269be306c802823cf543005ce36Calin Juravle // JobScheduler requested an early abort. 38051f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle return OPTIMIZE_ABORT_BY_JOB_SCHEDULER; 381c660475aafe91269be306c802823cf543005ce36Calin Juravle } 382c660475aafe91269be306c802823cf543005ce36Calin Juravle long usableSpace = mDataDir.getUsableSpace(); 383c660475aafe91269be306c802823cf543005ce36Calin Juravle if (usableSpace < lowStorageThreshold) { 384c660475aafe91269be306c802823cf543005ce36Calin Juravle // Rather bail than completely fill up the disk. 385c660475aafe91269be306c802823cf543005ce36Calin Juravle Log.w(TAG, "Aborting background dex opt job due to low storage: " + usableSpace); 38651f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle return OPTIMIZE_ABORT_NO_SPACE_LEFT; 387c660475aafe91269be306c802823cf543005ce36Calin Juravle } 388c660475aafe91269be306c802823cf543005ce36Calin Juravle 38951f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle return OPTIMIZE_CONTINUE; 3907395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom } 3917395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom 392246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera // Evaluate whether apps should be downgraded. 393246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera private boolean shouldDowngrade(long lowStorageThresholdForDowngrade) { 394246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera long usableSpace = mDataDir.getUsableSpace(); 395246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera if (usableSpace < lowStorageThresholdForDowngrade) { 396246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera return true; 397246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera } 398246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera 399246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera return false; 400246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera } 401246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera 402cb5f41ea11b1a6fcd0977a64ee146dde8f537076Calin Juravle /** 403cb5f41ea11b1a6fcd0977a64ee146dde8f537076Calin Juravle * Execute the idle optimizations immediately. 404cb5f41ea11b1a6fcd0977a64ee146dde8f537076Calin Juravle */ 405cb5f41ea11b1a6fcd0977a64ee146dde8f537076Calin Juravle public static boolean runIdleOptimizationsNow(PackageManagerService pm, Context context) { 406cb5f41ea11b1a6fcd0977a64ee146dde8f537076Calin Juravle // Create a new object to make sure we don't interfere with the scheduled jobs. 407cb5f41ea11b1a6fcd0977a64ee146dde8f537076Calin Juravle // Note that this may still run at the same time with the job scheduled by the 408cb5f41ea11b1a6fcd0977a64ee146dde8f537076Calin Juravle // JobScheduler but the scheduler will not be able to cancel it. 409cb5f41ea11b1a6fcd0977a64ee146dde8f537076Calin Juravle BackgroundDexOptService bdos = new BackgroundDexOptService(); 41051f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle int result = bdos.idleOptimization(pm, pm.getOptimizablePackages(), context); 41151f521c3bf46e6040f36757bc53ea57ddc7be85eCalin Juravle return result == OPTIMIZE_PROCESSED; 412cb5f41ea11b1a6fcd0977a64ee146dde8f537076Calin Juravle } 413cb5f41ea11b1a6fcd0977a64ee146dde8f537076Calin Juravle 414cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tate @Override 41537a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil public boolean onStartJob(JobParameters params) { 41637a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (DEBUG_DEXOPT) { 41737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil Log.i(TAG, "onStartJob"); 41837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 41937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 4208735f07a698218d311826a140d08d611d3c23db1Narayan Kamath // NOTE: PackageManagerService.isStorageLow uses a different set of criteria from 4218735f07a698218d311826a140d08d611d3c23db1Narayan Kamath // the checks above. This check is not "live" - the value is determined by a background 4228735f07a698218d311826a140d08d611d3c23db1Narayan Kamath // restart with a period of ~1 minute. 42337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package"); 42437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (pm.isStorageLow()) { 42537a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (DEBUG_DEXOPT) { 42637a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil Log.i(TAG, "Low storage, skipping this run"); 42737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 42837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil return false; 42937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 43037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 43137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil final ArraySet<String> pkgs = pm.getOptimizablePackages(); 432c660475aafe91269be306c802823cf543005ce36Calin Juravle if (pkgs.isEmpty()) { 43337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (DEBUG_DEXOPT) { 43437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil Log.i(TAG, "No packages to optimize"); 43537a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 43637a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil return false; 43737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 43837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 439f107a23ff165bbb7f0ae145f9ac85ddca8b43ed7Carmen Jackson boolean result; 44037a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (params.getJobId() == JOB_POST_BOOT_UPDATE) { 441f107a23ff165bbb7f0ae145f9ac85ddca8b43ed7Carmen Jackson result = runPostBootUpdate(params, pm, pkgs); 44237a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } else { 443f107a23ff165bbb7f0ae145f9ac85ddca8b43ed7Carmen Jackson result = runIdleOptimization(params, pm, pkgs); 44437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 445f107a23ff165bbb7f0ae145f9ac85ddca8b43ed7Carmen Jackson 446f107a23ff165bbb7f0ae145f9ac85ddca8b43ed7Carmen Jackson return result; 44737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 44837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 44937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil @Override 450cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tate public boolean onStopJob(JobParameters params) { 45137a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (DEBUG_DEXOPT) { 45237a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil Log.i(TAG, "onStopJob"); 45337a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 45437a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil 45537a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil if (params.getJobId() == JOB_POST_BOOT_UPDATE) { 45637a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil mAbortPostBootUpdate.set(true); 45737a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } else { 45837a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil mAbortIdleOptimization.set(true); 45937a87698f5b13e8d24475cb05d48a3da7339192cDavid Brazdil } 460cf1a2f73fc102be2ac7060ac97d4682bb2565ca5Christopher Tate return false; 4617395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom } 46231ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle 46331ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle private void notifyPinService(ArraySet<String> updatedPackages) { 46431ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle PinnerService pinnerService = LocalServices.getService(PinnerService.class); 46531ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle if (pinnerService != null) { 46631ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle Log.i(TAG, "Pinning optimized code " + updatedPackages); 46731ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle pinnerService.update(updatedPackages); 46831ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle } 46931ce3a8a56e78ecc17d9befbc64a1e529b6b78e9Calin Juravle } 470246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera 471246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera private static long getDowngradeUnusedAppsThresholdInMillis() { 472246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera final String sysPropKey = "pm.dexopt.downgrade_after_inactive_days"; 473246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera String sysPropValue = SystemProperties.get(sysPropKey); 474246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera if (sysPropValue == null || sysPropValue.isEmpty()) { 475246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera Log.w(TAG, "SysProp " + sysPropKey + " not set"); 476246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera return Long.MAX_VALUE; 477246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera } 478246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera return TimeUnit.DAYS.toMillis(Long.parseLong(sysPropValue)); 479246dccf9327631597767afe418ce43ae6d07d102Shubham Ajmera } 4807395a8ab8a7c6b03c32500c934694dde80b9ade1Brian Carlstrom} 481