diff options
5 files changed, 8 insertions, 315 deletions
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index c991f22b6294..58e4051b5111 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3593,7 +3593,7 @@ android:permission="android.permission.BIND_JOB_SERVICE" > </service> - <service android:name="com.android.server.BackgroundDexOptJobService" + <service android:name="com.android.server.pm.BackgroundDexOptService" android:exported="true" android:permission="android.permission.BIND_JOB_SERVICE"> </service> diff --git a/services/core/java/com/android/server/BackgroundDexOptJobService.java b/services/core/java/com/android/server/BackgroundDexOptJobService.java deleted file mode 100644 index 69e6ac50fa8a..000000000000 --- a/services/core/java/com/android/server/BackgroundDexOptJobService.java +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT; - -import android.app.job.JobInfo; -import android.app.job.JobParameters; -import android.app.job.JobScheduler; -import android.app.job.JobService; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.os.BatteryManager; -import android.os.Environment; -import android.os.ServiceManager; -import android.os.storage.StorageManager; -import android.util.ArraySet; -import android.util.Log; -import com.android.server.pm.PackageManagerService; - -import java.io.File; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.TimeUnit; - -public class BackgroundDexOptJobService extends JobService { - private static final String TAG = "BackgroundDexOptJobService"; - - private static final boolean DEBUG = false; - - private static final int JOB_IDLE_OPTIMIZE = 800; - private static final int JOB_POST_BOOT_UPDATE = 801; - - private static final long IDLE_OPTIMIZATION_PERIOD = DEBUG - ? TimeUnit.MINUTES.toMillis(1) - : TimeUnit.DAYS.toMillis(1); - - private static ComponentName sDexoptServiceName = new ComponentName( - "android", - BackgroundDexOptJobService.class.getName()); - - /** - * Set of failed packages remembered across job runs. - */ - static final ArraySet<String> sFailedPackageNames = new ArraySet<String>(); - - /** - * Atomics set to true if the JobScheduler requests an abort. - */ - final AtomicBoolean mAbortPostBootUpdate = new AtomicBoolean(false); - final AtomicBoolean mAbortIdleOptimization = new AtomicBoolean(false); - - /** - * Atomic set to true if one job should exit early because another job was started. - */ - final AtomicBoolean mExitPostBootUpdate = new AtomicBoolean(false); - - private final File mDataDir = Environment.getDataDirectory(); - - public static void schedule(Context context) { - JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); - - // Schedule a one-off job which scans installed packages and updates - // out-of-date oat files. - js.schedule(new JobInfo.Builder(JOB_POST_BOOT_UPDATE, sDexoptServiceName) - .setMinimumLatency(TimeUnit.MINUTES.toMillis(1)) - .setOverrideDeadline(TimeUnit.MINUTES.toMillis(1)) - .build()); - - // Schedule a daily job which scans installed packages and compiles - // those with fresh profiling data. - js.schedule(new JobInfo.Builder(JOB_IDLE_OPTIMIZE, sDexoptServiceName) - .setRequiresDeviceIdle(true) - .setRequiresCharging(true) - .setPeriodic(IDLE_OPTIMIZATION_PERIOD) - .build()); - - if (DEBUG_DEXOPT) { - Log.i(TAG, "Jobs scheduled"); - } - } - - public static void notifyPackageChanged(String packageName) { - // The idle maintanance job skips packages which previously failed to - // compile. The given package has changed and may successfully compile - // now. Remove it from the list of known failing packages. - synchronized (sFailedPackageNames) { - sFailedPackageNames.remove(packageName); - } - } - - // Returns the current battery level as a 0-100 integer. - private int getBatteryLevel() { - IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); - Intent intent = registerReceiver(null, filter); - int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); - int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); - - if (level < 0 || scale <= 0) { - // Battery data unavailable. This should never happen, so assume the worst. - return 0; - } - - return (100 * level / scale); - } - - private long getLowStorageThreshold() { - @SuppressWarnings("deprecation") - final long lowThreshold = StorageManager.from(this).getStorageLowBytes(mDataDir); - if (lowThreshold == 0) { - Log.e(TAG, "Invalid low storage threshold"); - } - - return lowThreshold; - } - - private boolean runPostBootUpdate(final JobParameters jobParams, - final PackageManagerService pm, final ArraySet<String> pkgs) { - if (mExitPostBootUpdate.get()) { - // This job has already been superseded. Do not start it. - return false; - } - new Thread("BackgroundDexOptService_PostBootUpdate") { - @Override - public void run() { - postBootUpdate(jobParams, pm, pkgs); - } - - }.start(); - return true; - } - - private void postBootUpdate(JobParameters jobParams, PackageManagerService pm, - ArraySet<String> pkgs) { - // Load low battery threshold from the system config. This is a 0-100 integer. - final int lowBatteryThreshold = getResources().getInteger( - com.android.internal.R.integer.config_lowBatteryWarningLevel); - final long lowThreshold = getLowStorageThreshold(); - - mAbortPostBootUpdate.set(false); - - for (String pkg : pkgs) { - if (mAbortPostBootUpdate.get()) { - // JobScheduler requested an early abort. - return; - } - if (mExitPostBootUpdate.get()) { - // Different job, which supersedes this one, is running. - break; - } - if (getBatteryLevel() < lowBatteryThreshold) { - // Rather bail than completely drain the battery. - break; - } - long usableSpace = mDataDir.getUsableSpace(); - if (usableSpace < lowThreshold) { - // Rather bail than completely fill up the disk. - Log.w(TAG, "Aborting background dex opt job due to low storage: " + - usableSpace); - break; - } - - if (DEBUG_DEXOPT) { - Log.i(TAG, "Updating package " + pkg); - } - - // Update package if needed. Note that there can be no race between concurrent - // jobs because PackageDexOptimizer.performDexOpt is synchronized. - - // checkProfiles is false to avoid merging profiles during boot which - // might interfere with background compilation (b/28612421). - // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will - // behave differently than "pm.dexopt.bg-dexopt=speed-profile" but that's a - // trade-off worth doing to save boot time work. - pm.performDexOpt(pkg, - /* checkProfiles */ false, - PackageManagerService.REASON_BOOT, - /* force */ false); - } - // Ran to completion, so we abandon our timeslice and do not reschedule. - jobFinished(jobParams, /* reschedule */ false); - } - - private boolean runIdleOptimization(final JobParameters jobParams, - final PackageManagerService pm, final ArraySet<String> pkgs) { - new Thread("BackgroundDexOptService_IdleOptimization") { - @Override - public void run() { - idleOptimization(jobParams, pm, pkgs); - } - }.start(); - return true; - } - - private void idleOptimization(JobParameters jobParams, PackageManagerService pm, - ArraySet<String> pkgs) { - Log.i(TAG, "Performing idle optimizations"); - // If post-boot update is still running, request that it exits early. - mExitPostBootUpdate.set(true); - - mAbortIdleOptimization.set(false); - - final long lowThreshold = getLowStorageThreshold(); - for (String pkg : pkgs) { - if (mAbortIdleOptimization.get()) { - // JobScheduler requested an early abort. - return; - } - - synchronized (sFailedPackageNames) { - if (sFailedPackageNames.contains(pkg)) { - // Skip previously failing package - continue; - } - } - - long usableSpace = mDataDir.getUsableSpace(); - if (usableSpace < lowThreshold) { - // Rather bail than completely fill up the disk. - Log.w(TAG, "Aborting background dex opt job due to low storage: " + - usableSpace); - break; - } - - // Conservatively add package to the list of failing ones in case performDexOpt - // never returns. - synchronized (sFailedPackageNames) { - sFailedPackageNames.add(pkg); - } - // Optimize package if needed. Note that there can be no race between - // concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized. - if (pm.performDexOpt(pkg, - /* checkProfiles */ true, - PackageManagerService.REASON_BACKGROUND_DEXOPT, - /* force */ false)) { - // Dexopt succeeded, remove package from the list of failing ones. - synchronized (sFailedPackageNames) { - sFailedPackageNames.remove(pkg); - } - } - } - // Ran to completion, so we abandon our timeslice and do not reschedule. - jobFinished(jobParams, /* reschedule */ false); - } - - @Override - public boolean onStartJob(JobParameters params) { - if (DEBUG_DEXOPT) { - Log.i(TAG, "onStartJob"); - } - - // NOTE: PackageManagerService.isStorageLow uses a different set of criteria from - // the checks above. This check is not "live" - the value is determined by a background - // restart with a period of ~1 minute. - PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package"); - if (pm.isStorageLow()) { - if (DEBUG_DEXOPT) { - Log.i(TAG, "Low storage, skipping this run"); - } - return false; - } - - final ArraySet<String> pkgs = pm.getOptimizablePackages(); - if (pkgs == null || pkgs.isEmpty()) { - if (DEBUG_DEXOPT) { - Log.i(TAG, "No packages to optimize"); - } - return false; - } - - if (params.getJobId() == JOB_POST_BOOT_UPDATE) { - return runPostBootUpdate(params, pm, pkgs); - } else { - return runIdleOptimization(params, pm, pkgs); - } - } - - @Override - public boolean onStopJob(JobParameters params) { - if (DEBUG_DEXOPT) { - Log.i(TAG, "onStopJob"); - } - - if (params.getJobId() == JOB_POST_BOOT_UPDATE) { - mAbortPostBootUpdate.set(true); - } else { - mAbortIdleOptimization.set(true); - } - return false; - } -} diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java index 7aa96cfddc62..d8900c0546fd 100644 --- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java +++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java @@ -49,8 +49,6 @@ public class BackgroundDexOptService extends JobService { private static final boolean DEBUG = false; - private static final long RETRY_LATENCY = 4 * AlarmManager.INTERVAL_HOUR; - private static final int JOB_IDLE_OPTIMIZE = 800; private static final int JOB_POST_BOOT_UPDATE = 801; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 4ac1cce91402..4640d2018608 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -260,7 +260,6 @@ import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; import com.android.internal.util.XmlUtils; import com.android.server.AttributeCache; -import com.android.server.BackgroundDexOptJobService; import com.android.server.DeviceIdleController; import com.android.server.EventLogTags; import com.android.server.FgThread; @@ -272,6 +271,7 @@ import com.android.server.SystemConfig; import com.android.server.SystemServerInitThreadPool; import com.android.server.Watchdog; import com.android.server.net.NetworkPolicyManagerInternal; +import com.android.server.pm.BackgroundDexOptService; import com.android.server.pm.Installer.InstallerException; import com.android.server.pm.PermissionsState.PermissionState; import com.android.server.pm.Settings.DatabaseVersion; @@ -16850,11 +16850,11 @@ public class PackageManagerService extends IPackageManager.Stub { mDexManager.isUsedByOtherApps(pkg.packageName)); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); - // Notify BackgroundDexOptJobService that the package has been changed. + // Notify BackgroundDexOptService that the package has been changed. // If this is an update of a package which used to fail to compile, // BDOS will remove it from its blacklist. // TODO: Layering violation - BackgroundDexOptJobService.notifyPackageChanged(pkg.packageName); + BackgroundDexOptService.notifyPackageChanged(pkg.packageName); } if (!args.doRename(res.returnCode, pkg, oldCodePath)) { diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index a8423e2e8a11..f84bfef530a3 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -86,6 +86,7 @@ import com.android.server.notification.NotificationManagerService; import com.android.server.om.OverlayManagerService; import com.android.server.os.DeviceIdentifiersPolicyService; import com.android.server.os.SchedulingPolicyService; +import com.android.server.pm.BackgroundDexOptService; import com.android.server.pm.Installer; import com.android.server.pm.LauncherAppsService; import com.android.server.pm.OtaDexoptService; @@ -1428,11 +1429,11 @@ public final class SystemServer { traceEnd(); } - traceBeginAndSlog("StartBackgroundDexOptJobService"); + traceBeginAndSlog("StartBackgroundDexOptService"); try { - BackgroundDexOptJobService.schedule(context); + BackgroundDexOptService.schedule(context); } catch (Throwable e) { - reportWtf("starting StartBackgroundDexOptJobService", e); + reportWtf("starting StartBackgroundDexOptService", e); } traceEnd(); |