add cancellation to background dexopt
- Completely refactored BackgroundDexOptimizationService to make it work under PackageManagerService : BackgroundDexOptJobService is added for JobService. - Merged all post boot update code with idle opt code. - added dump through adb shell dumpsys package dexopt - cancel background dexopt when idle job is stopped. Bug: 179094324 Bug: 156537504 TODO: add unit test as separate CL Test: run idle job, stop it repeatedly and check cancellation $ adb shell cmd jobscheduler run android [800|801] $ adb shell cmd jobscheduler timeout android $ adb shell cmd jobscheduler run android [800|801] $ adb shell pm bg-dexopt-job ex) $ adb shell cmd jobscheduler run android 801; sleep 1; adb shell cmd jobscheduler timeout android ex) adb shell pm bg-dexopt-job, in a separate termainal: adb shell pm cancel-bg-dexopt-job $ adb shell dumpsys package dexopt Change-Id: Ifa706fe44b0be76d393608646ea9e98169ea8916
This commit is contained in:
@@ -598,12 +598,6 @@ interface IPackageManager {
|
||||
|
||||
void forceDexOpt(String packageName);
|
||||
|
||||
/**
|
||||
* Execute the background dexopt job immediately on packages in packageNames.
|
||||
* If null, then execute on all packages.
|
||||
*/
|
||||
boolean runBackgroundDexoptJob(in List<String> packageNames);
|
||||
|
||||
/**
|
||||
* Reconcile the information we have about the secondary dex files belonging to
|
||||
* {@code packagName} and the actual dex files. For all dex files that were
|
||||
|
||||
@@ -6291,7 +6291,7 @@
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" >
|
||||
</service>
|
||||
|
||||
<service android:name="com.android.server.pm.BackgroundDexOptService"
|
||||
<service android:name="com.android.server.pm.BackgroundDexOptJobService"
|
||||
android:exported="true"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE">
|
||||
</service>
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.pm;
|
||||
|
||||
import android.app.job.JobParameters;
|
||||
import android.app.job.JobService;
|
||||
|
||||
/**
|
||||
* JobService to run background dex optimization. This is a thin wrapper and most logic exits in
|
||||
* {@link BackgroundDexOptService}.
|
||||
*/
|
||||
public final class BackgroundDexOptJobService extends JobService {
|
||||
|
||||
@Override
|
||||
public boolean onStartJob(JobParameters params) {
|
||||
return BackgroundDexOptService.getService().onStartJob(this, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStopJob(JobParameters params) {
|
||||
return BackgroundDexOptService.getService().onStopJob(this, params);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -179,6 +179,7 @@ public class ComputerEngine implements Computer {
|
||||
private final PackageDexOptimizer mPackageDexOptimizer;
|
||||
private final DexManager mDexManager;
|
||||
private final CompilerStats mCompilerStats;
|
||||
private final BackgroundDexOptService mBackgroundDexOptService;
|
||||
|
||||
// PackageManagerService attributes that are primitives are referenced through the
|
||||
// pms object directly. Primitives are the only attributes so referenced.
|
||||
@@ -228,6 +229,7 @@ public class ComputerEngine implements Computer {
|
||||
mPackageDexOptimizer = args.service.mPackageDexOptimizer;
|
||||
mDexManager = args.service.getDexManager();
|
||||
mCompilerStats = args.service.mCompilerStats;
|
||||
mBackgroundDexOptService = args.service.mBackgroundDexOptService;
|
||||
|
||||
// Used to reference PMS attributes that are primitives and which are not
|
||||
// updated under control of the PMS lock.
|
||||
@@ -2929,6 +2931,10 @@ public class ComputerEngine implements Computer {
|
||||
mDexManager.getPackageUseInfoOrDefault(pkgName));
|
||||
ipw.decreaseIndent();
|
||||
}
|
||||
ipw.println("BgDexopt state:");
|
||||
ipw.increaseIndent();
|
||||
mBackgroundDexOptService.dump(ipw);
|
||||
ipw.decreaseIndent();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1973,7 +1973,7 @@ final class InstallParams extends HandlerParams {
|
||||
// If this is an update of a package which used to fail to compile,
|
||||
// BackgroundDexOptService will remove it from its denylist.
|
||||
// TODO: Layering violation
|
||||
BackgroundDexOptService.notifyPackageChanged(packageName);
|
||||
BackgroundDexOptService.getService().notifyPackageChanged(packageName);
|
||||
|
||||
notifyPackageChangeObserversOnUpdate(reconciledPkg);
|
||||
}
|
||||
|
||||
@@ -899,6 +899,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
final ArtManagerService mArtManagerService;
|
||||
|
||||
final PackageDexOptimizer mPackageDexOptimizer;
|
||||
final BackgroundDexOptService mBackgroundDexOptService;
|
||||
// DexManager handles the usage of dex files (e.g. secondary files, whether or not a package
|
||||
// is used by other apps).
|
||||
private final DexManager mDexManager;
|
||||
@@ -1531,7 +1532,8 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
},
|
||||
new DefaultSystemWrapper(),
|
||||
LocalServices::getService,
|
||||
context::getSystemService);
|
||||
context::getSystemService,
|
||||
(i, pm) -> new BackgroundDexOptService(i.getContext(), i.getDexManager()));
|
||||
|
||||
if (Build.VERSION.SDK_INT <= 0) {
|
||||
Slog.w(TAG, "**** ro.build.version.sdk not set!");
|
||||
@@ -1676,6 +1678,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
mApexManager = testParams.apexManager;
|
||||
mArtManagerService = testParams.artManagerService;
|
||||
mAvailableFeatures = testParams.availableFeatures;
|
||||
mBackgroundDexOptService = testParams.backgroundDexOptService;
|
||||
mDefParseFlags = testParams.defParseFlags;
|
||||
mDefaultAppProvider = testParams.defaultAppProvider;
|
||||
mLegacyPermissionManager = testParams.legacyPermissionManagerInternal;
|
||||
@@ -1852,6 +1855,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
|
||||
mPackageDexOptimizer = injector.getPackageDexOptimizer();
|
||||
mDexManager = injector.getDexManager();
|
||||
mBackgroundDexOptService = injector.getBackgroundDexOptService();
|
||||
mArtManagerService = injector.getArtManagerService();
|
||||
mMoveCallbacks = new MovePackageHelper.MoveCallbacks(FgThread.get().getLooper());
|
||||
mViewCompiler = injector.getViewCompiler();
|
||||
@@ -6140,6 +6144,10 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
/*package*/ void controlDexOptBlocking(boolean block) {
|
||||
mPackageDexOptimizer.controlDexOptBlocking(block);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform dexopt on the given package and return one of following result:
|
||||
* {@link PackageDexOptimizer#DEX_OPT_SKIPPED}
|
||||
@@ -6276,23 +6284,6 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
return mDexManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the background dexopt job immediately.
|
||||
*/
|
||||
@Override
|
||||
public boolean runBackgroundDexoptJob(@Nullable List<String> packageNames) {
|
||||
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
|
||||
return false;
|
||||
}
|
||||
enforceSystemOrRootOrShell("runBackgroundDexoptJob");
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return BackgroundDexOptService.runIdleOptimizationsNow(this, mContext, packageNames);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<SharedLibraryInfo> findSharedLibraries(PackageSetting pkgSetting) {
|
||||
if (!pkgSetting.getPkgState().getUsesLibraryInfos().isEmpty()) {
|
||||
ArrayList<SharedLibraryInfo> retValue = new ArrayList<>();
|
||||
@@ -11468,6 +11459,8 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
mPerUidReadTimeoutsCache = null;
|
||||
}
|
||||
});
|
||||
|
||||
mBackgroundDexOptService.systemReady();
|
||||
}
|
||||
|
||||
public void waitForAppDataPrepared() {
|
||||
|
||||
@@ -134,6 +134,7 @@ public class PackageManagerServiceInjector {
|
||||
private final Singleton<DomainVerificationManagerInternal>
|
||||
mDomainVerificationManagerInternalProducer;
|
||||
private final Singleton<Handler> mHandlerProducer;
|
||||
private final Singleton<BackgroundDexOptService> mBackgroundDexOptService;
|
||||
|
||||
PackageManagerServiceInjector(Context context, PackageManagerTracedLock lock,
|
||||
Installer installer, Object installLock, PackageAbiHelper abiHelper,
|
||||
@@ -168,7 +169,8 @@ public class PackageManagerServiceInjector {
|
||||
Producer<Handler> handlerProducer,
|
||||
SystemWrapper systemWrapper,
|
||||
ServiceProducer getLocalServiceProducer,
|
||||
ServiceProducer getSystemServiceProducer) {
|
||||
ServiceProducer getSystemServiceProducer,
|
||||
Producer<BackgroundDexOptService> backgroundDexOptService) {
|
||||
mContext = context;
|
||||
mLock = lock;
|
||||
mInstaller = installer;
|
||||
@@ -217,6 +219,7 @@ public class PackageManagerServiceInjector {
|
||||
new Singleton<>(
|
||||
domainVerificationManagerInternalProducer);
|
||||
mHandlerProducer = new Singleton<>(handlerProducer);
|
||||
mBackgroundDexOptService = new Singleton<>(backgroundDexOptService);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -377,6 +380,10 @@ public class PackageManagerServiceInjector {
|
||||
return getLocalService(ActivityManagerInternal.class);
|
||||
}
|
||||
|
||||
public BackgroundDexOptService getBackgroundDexOptService() {
|
||||
return mBackgroundDexOptService.get(this, mPackageManager);
|
||||
}
|
||||
|
||||
/** Provides an abstraction to static access to system state. */
|
||||
public interface SystemWrapper {
|
||||
void disablePackageCaches();
|
||||
|
||||
@@ -100,5 +100,6 @@ public final class PackageManagerServiceTestParams {
|
||||
public boolean isEngBuild;
|
||||
public boolean isUserDebugBuild;
|
||||
public int sdkInt = Build.VERSION.SDK_INT;
|
||||
public BackgroundDexOptService backgroundDexOptService;
|
||||
public final String incrementalVersion = Build.VERSION.INCREMENTAL;
|
||||
}
|
||||
|
||||
@@ -226,6 +226,8 @@ class PackageManagerShellCommand extends ShellCommand {
|
||||
return runForceDexOpt();
|
||||
case "bg-dexopt-job":
|
||||
return runDexoptJob();
|
||||
case "cancel-bg-dexopt-job":
|
||||
return cancelBgDexOptJob();
|
||||
case "dump-profiles":
|
||||
return runDumpProfiles();
|
||||
case "snapshot-profile":
|
||||
@@ -1863,12 +1865,18 @@ class PackageManagerShellCommand extends ShellCommand {
|
||||
while ((arg = getNextArg()) != null) {
|
||||
packageNames.add(arg);
|
||||
}
|
||||
boolean result = mInterface.runBackgroundDexoptJob(packageNames.isEmpty() ? null :
|
||||
packageNames);
|
||||
boolean result = BackgroundDexOptService.getService().runBackgroundDexoptJob(
|
||||
packageNames.isEmpty() ? null : packageNames);
|
||||
getOutPrintWriter().println(result ? "Success" : "Failure");
|
||||
return result ? 0 : -1;
|
||||
}
|
||||
|
||||
private int cancelBgDexOptJob() throws RemoteException {
|
||||
BackgroundDexOptService.getService().cancelBackgroundDexoptJob();
|
||||
getOutPrintWriter().println("Success");
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int runDumpProfiles() throws RemoteException {
|
||||
String packageName = getNextArg();
|
||||
mInterface.dumpProfiles(packageName);
|
||||
@@ -3940,6 +3948,11 @@ class PackageManagerShellCommand extends ShellCommand {
|
||||
pw.println(" overlap with the actual job but the job scheduler will not be able to");
|
||||
pw.println(" cancel it. It will also run even if the device is not in the idle");
|
||||
pw.println(" maintenance mode.");
|
||||
pw.println(" cancel-bg-dexopt-job");
|
||||
pw.println(" Cancels currently running background optimizations immediately.");
|
||||
pw.println(" This cancels optimizations run from bg-dexopt-job or from JobScjeduler.");
|
||||
pw.println(" Note that cancelling currently running bg-dexopt-job command requires");
|
||||
pw.println(" running this command from separate adb shell.");
|
||||
pw.println("");
|
||||
pw.println(" reconcile-secondary-dex-files TARGET-PACKAGE");
|
||||
pw.println(" Reconciles the package secondary dex files with the generated oat files.");
|
||||
|
||||
@@ -149,7 +149,6 @@ import com.android.server.os.DeviceIdentifiersPolicyService;
|
||||
import com.android.server.os.NativeTombstoneManagerService;
|
||||
import com.android.server.os.SchedulingPolicyService;
|
||||
import com.android.server.people.PeopleService;
|
||||
import com.android.server.pm.BackgroundDexOptService;
|
||||
import com.android.server.pm.CrossProfileAppsService;
|
||||
import com.android.server.pm.DataLoaderManagerService;
|
||||
import com.android.server.pm.DynamicCodeLoggingService;
|
||||
@@ -2408,15 +2407,6 @@ public final class SystemServer implements Dumpable {
|
||||
mSystemServiceManager.startService(AuthService.class);
|
||||
t.traceEnd();
|
||||
|
||||
|
||||
t.traceBegin("StartBackgroundDexOptService");
|
||||
try {
|
||||
BackgroundDexOptService.schedule(context);
|
||||
} catch (Throwable e) {
|
||||
reportWtf("starting StartBackgroundDexOptService", e);
|
||||
}
|
||||
t.traceEnd();
|
||||
|
||||
if (!isWatch) {
|
||||
// We don't run this on watches as there are no plans to use the data logged
|
||||
// on watch devices.
|
||||
|
||||
@@ -21,16 +21,13 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.job.JobInfo;
|
||||
import android.app.job.JobParameters;
|
||||
import android.app.job.JobService;
|
||||
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.pm.ActivityInfo;
|
||||
import android.os.IBinder;
|
||||
import android.os.IBinder.DeathRecipient;
|
||||
import android.os.Handler;
|
||||
import android.os.Parcel;
|
||||
import android.os.IBinder.DeathRecipient;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.SystemProperties;
|
||||
@@ -45,18 +42,15 @@ import com.android.server.SystemService;
|
||||
import com.android.server.pm.BackgroundDexOptService;
|
||||
import com.android.server.pm.PackageManagerService;
|
||||
import com.android.server.wm.ActivityMetricsLaunchObserver;
|
||||
import com.android.server.wm.ActivityMetricsLaunchObserver.ActivityRecordProto;
|
||||
import com.android.server.wm.ActivityMetricsLaunchObserver.Temperature;
|
||||
import com.android.server.wm.ActivityMetricsLaunchObserverRegistry;
|
||||
import com.android.server.wm.ActivityTaskManagerInternal;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* System-server-local proxy into the {@code IIorap} native service.
|
||||
@@ -347,7 +341,8 @@ public class IorapForwardingService extends SystemService {
|
||||
launchObserverRegistry.registerLaunchObserver(mAppLaunchObserver);
|
||||
launchObserverRegistry.registerLaunchObserver(mEventSequenceValidator);
|
||||
|
||||
BackgroundDexOptService.addPackagesUpdatedListener(mDexOptPackagesUpdated);
|
||||
BackgroundDexOptService.getService().addPackagesUpdatedListener(
|
||||
mDexOptPackagesUpdated);
|
||||
|
||||
|
||||
mRegisteredListeners = true;
|
||||
|
||||
Reference in New Issue
Block a user