diff options
| author | 2018-07-09 17:57:10 +0200 | |
|---|---|---|
| committer | 2018-07-13 15:16:48 +0200 | |
| commit | 402d78ebb74e9642f6e291b7b13768b993d7519c (patch) | |
| tree | 35b76eedc10d0cb138bfd57b43a4e3ca8b9546b5 | |
| parent | ca8a8a999b271c65148e70970f6dda4389b8e458 (diff) | |
Pin compiled code of HOME app
Keeping the code in memory of the currently set home app is
important for latency as we don't have any kind of starting
window/splash screen when pressing the home app to hide any latency.
Memory impact:
Pinning dex/vdex:
In practical scenarios, this should be < 500kb.
The home app is usually profile-speed compiled, for which the
resulting dex/vdex files are about 2 mb. However, during regular
use, at least 1.5 MB of it is referenced in memory. This makes
sense: By definition profile-speed only compiles the things that
is usually frequently executed during regular execution.
Pinning apk:
With Launcher 3 in practical scenarios this should be about 3.7 MB,
as the APK is about 5.7 MB but 2 MB are usually referenced in any
case.
Bug: 111132016
Bug: 78585335
Test: Inspect "adb shell dumpsys pinner" after boot.
Test: Check for pinned files after updating camera/home.
Test: Check for pinned files after user switch with different
default apps.
Test: Check for pinned files after bg-dexopt.
Test: Check for pinned files after bg-dexopt + kill pid.
Change-Id: I6cdbc06d089efeb1c72a51216879ba0573502009
6 files changed, 371 insertions, 106 deletions
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 7a9a553bb287..2e4404c0feed 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -223,6 +223,12 @@ public abstract class ActivityManagerInternal { * intercept activity launches for work apps when the Work Challenge is present. */ public abstract boolean shouldConfirmCredentials(int userId); + + /** + * @return The intent used to launch the home activity. + */ + public abstract Intent getHomeIntent(); + public abstract int[] getCurrentProfileIds(); public abstract UserInfo getCurrentUser(); public abstract void ensureNotSpecialUser(int userId); diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index e4ce2b1e91ca..ee81c7cefdd5 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -3182,6 +3182,9 @@ <!-- True if camera app should be pinned via Pinner Service --> <bool name="config_pinnerCameraApp">false</bool> + <!-- True if home app should be pinned via Pinner Service --> + <bool name="config_pinnerHomeApp">false</bool> + <!-- Number of days preloaded file cache should be preserved on a device before it can be deleted --> <integer name="config_keepPreloadsMinDays">7</integer> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 6a58b670b666..3d2ebf3afc6c 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2922,6 +2922,7 @@ <!-- Pinner Service --> <java-symbol type="array" name="config_defaultPinnerServiceFiles" /> <java-symbol type="bool" name="config_pinnerCameraApp" /> + <java-symbol type="bool" name="config_pinnerHomeApp" /> <java-symbol type="string" name="config_doubleTouchGestureEnableFile" /> diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java index 5a25f48c38e3..cec2028dddae 100644 --- a/services/core/java/com/android/server/PinnerService.java +++ b/services/core/java/com/android/server/PinnerService.java @@ -16,8 +16,16 @@ package com.android.server; +import static android.app.ActivityManager.UID_OBSERVER_ACTIVE; +import static android.app.ActivityManager.UID_OBSERVER_GONE; + +import android.annotation.IntDef; import android.annotation.Nullable; +import android.app.ActivityManager; +import android.app.ActivityManagerInternal; +import android.app.IActivityManager; +import android.app.IUidObserver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -32,18 +40,21 @@ import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.os.RemoteException; import android.os.UserHandle; import android.provider.MediaStore; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; -import android.system.StructStat; +import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; +import com.android.internal.annotations.GuardedBy; import com.android.internal.app.ResolverActivity; import com.android.internal.os.BackgroundThread; import com.android.internal.util.DumpUtils; +import com.android.internal.util.function.pooled.PooledLambda; import dalvik.system.DexFile; import dalvik.system.VMRuntime; @@ -53,12 +64,12 @@ import java.io.Closeable; import java.io.InputStream; import java.io.DataInputStream; import java.io.IOException; -import java.io.EOFException; import java.io.PrintWriter; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.zip.ZipFile; -import java.util.zip.ZipException; import java.util.zip.ZipEntry; /** @@ -70,16 +81,50 @@ import java.util.zip.ZipEntry; public final class PinnerService extends SystemService { private static final boolean DEBUG = false; private static final String TAG = "PinnerService"; - private static final int MAX_CAMERA_PIN_SIZE = 80 * (1 << 20); //80MB max + private static final String PIN_META_FILENAME = "pinlist.meta"; private static final int PAGE_SIZE = (int) Os.sysconf(OsConstants._SC_PAGESIZE); + private static final int MATCH_FLAGS = PackageManager.MATCH_DEFAULT_ONLY + | PackageManager.MATCH_DIRECT_BOOT_AWARE + | PackageManager.MATCH_DIRECT_BOOT_UNAWARE; + + private static final int KEY_CAMERA = 0; + private static final int KEY_HOME = 1; + + private static final int MAX_CAMERA_PIN_SIZE = 80 * (1 << 20); // 80MB max for camera app. + private static final int MAX_HOME_PIN_SIZE = 6 * (1 << 20); // 6MB max for home app. + + @IntDef({KEY_CAMERA, KEY_HOME}) + @Retention(RetentionPolicy.SOURCE) + public @interface AppKey {} private final Context mContext; - private final boolean mShouldPinCamera; + private final ActivityManagerInternal mAmInternal; + private final IActivityManager mAm; + + /** The list of the statically pinned files. */ + @GuardedBy("this") + private final ArrayList<PinnedFile> mPinnedFiles = new ArrayList<>(); + + /** The list of the pinned apps. This is a map from {@link AppKey} to a pinned app. */ + @GuardedBy("this") + private final ArrayMap<Integer, PinnedApp> mPinnedApps = new ArrayMap<>(); + + /** + * The list of the pinned apps that need to be repinned as soon as the all processes of a given + * uid are no longer active. Note that with background dex opt, the new dex/vdex files are only + * loaded into the processes once it restarts. So in case background dex opt recompiled these + * files, we still need to keep the old ones pinned until the processes restart. + * <p> + * This is a map from uid to {@link AppKey} + */ + @GuardedBy("this") + private final ArrayMap<Integer, Integer> mPendingRepin = new ArrayMap<>(); - /* These lists protected by PinnerService monitor lock */ - private final ArrayList<PinnedFile> mPinnedFiles = new ArrayList<PinnedFile>(); - private final ArrayList<PinnedFile> mPinnedCameraFiles = new ArrayList<PinnedFile>(); + /** + * A set of {@link AppKey} that are configured to be pinned. + */ + private final ArraySet<Integer> mPinKeys = new ArraySet<>(); private BinderService mBinderService; private PinnerHandler mPinnerHandler = null; @@ -87,13 +132,13 @@ public final class PinnerService extends SystemService { private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - // If this user's camera app has been updated, update pinned files accordingly. - if (intent.getAction() == Intent.ACTION_PACKAGE_REPLACED) { + // If an app has updated, update pinned files accordingly. + if (Intent.ACTION_PACKAGE_REPLACED.equals(intent.getAction())) { Uri packageUri = intent.getData(); String packageName = packageUri.getSchemeSpecificPart(); ArraySet<String> updatedPackages = new ArraySet<>(); updatedPackages.add(packageName); - update(updatedPackages); + update(updatedPackages, true /* force */); } } }; @@ -102,14 +147,26 @@ public final class PinnerService extends SystemService { super(context); mContext = context; - mShouldPinCamera = context.getResources().getBoolean( + boolean shouldPinCamera = context.getResources().getBoolean( com.android.internal.R.bool.config_pinnerCameraApp); + boolean shouldPinHome = context.getResources().getBoolean( + com.android.internal.R.bool.config_pinnerHomeApp); + if (shouldPinCamera) { + mPinKeys.add(KEY_CAMERA); + } + if (shouldPinHome) { + mPinKeys.add(KEY_HOME); + } mPinnerHandler = new PinnerHandler(BackgroundThread.get().getLooper()); + mAmInternal = LocalServices.getService(ActivityManagerInternal.class); + mAm = ActivityManager.getService(); + IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_PACKAGE_REPLACED); filter.addDataScheme("package"); mContext.registerReceiver(mBroadcastReceiver, filter); + registerUidListener(); } @Override @@ -122,32 +179,39 @@ public final class PinnerService extends SystemService { publishLocalService(PinnerService.class, this); mPinnerHandler.obtainMessage(PinnerHandler.PIN_ONSTART_MSG).sendToTarget(); - mPinnerHandler.obtainMessage(PinnerHandler.PIN_CAMERA_MSG, UserHandle.USER_SYSTEM, 0) - .sendToTarget(); + sendPinAppsMessage(UserHandle.USER_SYSTEM); } /** - * Pin camera on user switch. - * If more than one user is using the device - * each user may set a different preference for the camera app. - * Make sure that user's preference is pinned into memory. + * Repin apps on user switch. + * <p> + * If more than one user is using the device each user may set a different preference for the + * individual apps. Make sure that user's preference is pinned into memory. */ @Override public void onSwitchUser(int userHandle) { - mPinnerHandler.obtainMessage(PinnerHandler.PIN_CAMERA_MSG, userHandle, 0).sendToTarget(); + sendPinAppsMessage(userHandle); + } + + @Override + public void onUnlockUser(int userHandle) { + sendPinAppsMessage(userHandle); } /** * Update the currently pinned files. - * Specifically, this only updates camera pinning. + * Specifically, this only updates pinning for the apps that need to be pinned. * The other files pinned in onStart will not need to be updated. */ - public void update(ArraySet<String> updatedPackages) { - ApplicationInfo cameraInfo = getCameraInfo(UserHandle.USER_SYSTEM); - if (cameraInfo != null && updatedPackages.contains(cameraInfo.packageName)) { - Slog.i(TAG, "Updating pinned files."); - mPinnerHandler.obtainMessage(PinnerHandler.PIN_CAMERA_MSG, UserHandle.USER_SYSTEM, 0) - .sendToTarget(); + public void update(ArraySet<String> updatedPackages, boolean force) { + int currentUser = ActivityManager.getCurrentUser(); + for (int i = mPinKeys.size() - 1; i >= 0; i--) { + int key = mPinKeys.valueAt(i); + ApplicationInfo info = getInfoForKey(key, currentUser); + if (info != null && updatedPackages.contains(info.packageName)) { + Slog.i(TAG, "Updating pinned files for " + info.packageName + " force=" + force); + sendPinAppMessage(key, currentUser, force); + } } } @@ -174,25 +238,80 @@ public final class PinnerService extends SystemService { } } - /** - * Handler for camera pinning message - */ - private void handlePinCamera(int userHandle) { - if (!mShouldPinCamera) return; - if (!pinCamera(userHandle)) { - if (DEBUG) { - Slog.v(TAG, "Failed to pin camera."); + private void registerUidListener() { + try { + mAm.registerUidObserver(new IUidObserver.Stub() { + @Override + public void onUidGone(int uid, boolean disabled) throws RemoteException { + mPinnerHandler.sendMessage(PooledLambda.obtainMessage( + PinnerService::handleUidGone, PinnerService.this, uid)); + } + + @Override + public void onUidActive(int uid) throws RemoteException { + mPinnerHandler.sendMessage(PooledLambda.obtainMessage( + PinnerService::handleUidActive, PinnerService.this, uid)); + } + + @Override + public void onUidIdle(int uid, boolean disabled) throws RemoteException { + } + + @Override + public void onUidStateChanged(int uid, int procState, long procStateSeq) + throws RemoteException { + } + + @Override + public void onUidCachedChanged(int uid, boolean cached) throws RemoteException { + } + }, UID_OBSERVER_GONE | UID_OBSERVER_ACTIVE, 0, "system"); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to register uid observer", e); + } + } + + private void handleUidGone(int uid) { + updateActiveState(uid, false /* active */); + int key; + synchronized (this) { + + // In case we have a pending repin, repin now. See mPendingRepin for more information. + key = mPendingRepin.getOrDefault(uid, -1); + if (key == -1) { + return; + } + mPendingRepin.remove(uid); + } + pinApp(key, ActivityManager.getCurrentUser(), false /* force */); + } + + private void handleUidActive(int uid) { + updateActiveState(uid, true /* active */); + } + + private void updateActiveState(int uid, boolean active) { + synchronized (this) { + for (int i = mPinnedApps.size() - 1; i >= 0; i--) { + PinnedApp app = mPinnedApps.valueAt(i); + if (app.uid == uid) { + app.active = active; + } } } } - private void unpinCameraApp() { - ArrayList<PinnedFile> pinnedCameraFiles; + private void unpinApp(@AppKey int key) { + ArrayList<PinnedFile> pinnedAppFiles; synchronized (this) { - pinnedCameraFiles = new ArrayList<>(mPinnedCameraFiles); - mPinnedCameraFiles.clear(); + PinnedApp app = mPinnedApps.get(key); + if (app == null) { + return; + } + mPinnedApps.remove(key); + pinnedAppFiles = new ArrayList<>(app.mFiles); } - for (PinnedFile pinnedFile : pinnedCameraFiles) { + for (PinnedFile pinnedFile : pinnedAppFiles) { pinnedFile.close(); } } @@ -206,64 +325,167 @@ public final class PinnerService extends SystemService { // use INTENT_ACTION_STILL_IMAGE_CAMERA instead of _SECURE. On a // device without a fbe enabled, the _SECURE intent will never get set. Intent cameraIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); - PackageManager pm = mContext.getPackageManager(); - ResolveInfo cameraResolveInfo = pm.resolveActivityAsUser(cameraIntent, - PackageManager.MATCH_DEFAULT_ONLY | PackageManager.MATCH_DIRECT_BOOT_AWARE - | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, - userHandle); - if (cameraResolveInfo == null ) { - //this is not necessarily an error - if (DEBUG) { - Slog.v(TAG, "Unable to resolve camera intent"); - } + return getApplicationInfoForIntent(cameraIntent, userHandle); + } + + private ApplicationInfo getHomeInfo(int userHandle) { + Intent intent = mAmInternal.getHomeIntent(); + return getApplicationInfoForIntent(intent, userHandle); + } + + private ApplicationInfo getApplicationInfoForIntent(Intent intent, int userHandle) { + if (intent == null) { + return null; + } + ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(intent, + MATCH_FLAGS, userHandle); + if (info == null) { + return null; + } + if (isResolverActivity(info.activityInfo)) { return null; } + return info.activityInfo.applicationInfo; + } - if (isResolverActivity(cameraResolveInfo.activityInfo)) - { - if (DEBUG) { - Slog.v(TAG, "cameraIntent returned resolverActivity"); + private void sendPinAppsMessage(int userHandle) { + mPinnerHandler.sendMessage(PooledLambda.obtainMessage(PinnerService::pinApps, this, + userHandle)); + } + + private void pinApps(int userHandle) { + for (int i = mPinKeys.size() - 1; i >= 0; i--) { + int key = mPinKeys.valueAt(i); + pinApp(key, userHandle, true /* force */); + } + } + + /** + * @see #pinApp(int, int, boolean) + */ + private void sendPinAppMessage(int key, int userHandle, boolean force) { + mPinnerHandler.sendMessage(PooledLambda.obtainMessage(PinnerService::pinApp, this, + key, userHandle, force)); + } + + /** + * Pins an app of a specific type {@code key}. + * + * @param force If false, this will not repin the app if it's currently active. See + * {@link #mPendingRepin}. + */ + private void pinApp(int key, int userHandle, boolean force) { + int uid = getUidForKey(key); + + // In case the app is currently active, don't repin until next process restart. See + // mPendingRepin for more information. + if (!force && uid != -1) { + synchronized (this) { + mPendingRepin.put(uid, key); } - return null; + return; } + unpinApp(key); + ApplicationInfo info = getInfoForKey(key, userHandle); + if (info != null) { + pinApp(key, info); + } + } + + /** + * Checks whether the pinned package with {@code key} is active or not. - return cameraResolveInfo.activityInfo.applicationInfo; + * @return The uid of the pinned app, or {@code -1} otherwise. + */ + private int getUidForKey(@AppKey int key) { + synchronized (this) { + PinnedApp existing = mPinnedApps.get(key); + return existing != null && existing.active + ? existing.uid + : -1; + } } /** - * If the camera app is already pinned, unpin and repin it. + * Retrieves the current application info for the given app type. + * + * @param key The app type to retrieve the info for. + * @param userHandle The user id of the current user. */ - private boolean pinCamera(int userHandle){ - ApplicationInfo cameraInfo = getCameraInfo(userHandle); - if (cameraInfo == null) { - return false; - } - - //unpin after checking that the camera intent has resolved - //this prevents us from thrashing when switching users with - //FBE enabled, because the intent won't resolve until the unlock - unpinCameraApp(); - - //pin APK - String camAPK = cameraInfo.sourceDir; - PinnedFile pf = pinFile(camAPK, - MAX_CAMERA_PIN_SIZE, - /*attemptPinIntrospection=*/true); + private @Nullable ApplicationInfo getInfoForKey(@AppKey int key, int userHandle) { + switch (key) { + case KEY_CAMERA: + return getCameraInfo(userHandle); + case KEY_HOME: + return getHomeInfo(userHandle); + default: + return null; + } + } + + /** + * @return The app type name for {@code key}. + */ + private String getNameForKey(@AppKey int key) { + switch (key) { + case KEY_CAMERA: + return "Camera"; + case KEY_HOME: + return "Home"; + default: + return null; + } + } + + /** + * @return The maximum amount of bytes to be pinned for an app of type {@code key}. + */ + private int getSizeLimitForKey(@AppKey int key) { + switch (key) { + case KEY_CAMERA: + return MAX_CAMERA_PIN_SIZE; + case KEY_HOME: + return MAX_HOME_PIN_SIZE; + default: + return 0; + } + } + + /** + * Pins an application. + * + * @param key The key of the app to pin. + * @param appInfo The corresponding app info. + */ + private void pinApp(@AppKey int key, @Nullable ApplicationInfo appInfo) { + if (appInfo == null) { + return; + } + + PinnedApp pinnedApp = new PinnedApp(appInfo); + synchronized (this) { + mPinnedApps.put(key, pinnedApp); + } + + // pin APK + int pinSizeLimit = getSizeLimitForKey(key); + String apk = appInfo.sourceDir; + PinnedFile pf = pinFile(apk, pinSizeLimit, /*attemptPinIntrospection=*/true); if (pf == null) { - Slog.e(TAG, "Failed to pin " + camAPK); - return false; + Slog.e(TAG, "Failed to pin " + apk); + return; } if (DEBUG) { Slog.i(TAG, "Pinned " + pf.fileName); } synchronized (this) { - mPinnedCameraFiles.add(pf); + pinnedApp.mFiles.add(pf); } // determine the ABI from either ApplicationInfo or Build String arch = "arm"; - if (cameraInfo.primaryCpuAbi != null) { - if (VMRuntime.is64BitAbi(cameraInfo.primaryCpuAbi)) { + if (appInfo.primaryCpuAbi != null) { + if (VMRuntime.is64BitAbi(appInfo.primaryCpuAbi)) { arch = arch + "64"; } } else { @@ -273,32 +495,29 @@ public final class PinnerService extends SystemService { } // get the path to the odex or oat file - String baseCodePath = cameraInfo.getBaseCodePath(); + String baseCodePath = appInfo.getBaseCodePath(); String[] files = null; try { files = DexFile.getDexFileOutputPaths(baseCodePath, arch); } catch (IOException ioe) {} if (files == null) { - return true; + return; } //not pinning the oat/odex is not a fatal error for (String file : files) { - pf = pinFile(file, MAX_CAMERA_PIN_SIZE, /*attemptPinIntrospection=*/false); + pf = pinFile(file, pinSizeLimit, /*attemptPinIntrospection=*/false); if (pf != null) { synchronized (this) { - mPinnedCameraFiles.add(pf); + pinnedApp.mFiles.add(pf); } if (DEBUG) { Slog.i(TAG, "Pinned " + pf.fileName); } } } - - return true; } - /** mlock length bytes of fileToPin in memory * * If attemptPinIntrospection is true, then treat the file to pin as a zip file and @@ -581,24 +800,38 @@ public final class PinnerService extends SystemService { } } - private synchronized ArrayList<PinnedFile> snapshotPinnedFiles() { - int nrPinnedFiles = mPinnedFiles.size() + mPinnedCameraFiles.size(); - ArrayList<PinnedFile> pinnedFiles = new ArrayList<>(nrPinnedFiles); - pinnedFiles.addAll(mPinnedFiles); - pinnedFiles.addAll(mPinnedCameraFiles); - return pinnedFiles; - } - private final class BinderService extends Binder { @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; - long totalSize = 0; - for (PinnedFile pinnedFile : snapshotPinnedFiles()) { - pw.format("%s %s\n", pinnedFile.fileName, pinnedFile.bytesPinned); - totalSize += pinnedFile.bytesPinned; + synchronized (PinnerService.this) { + long totalSize = 0; + for (PinnedFile pinnedFile : mPinnedFiles) { + pw.format("%s %s\n", pinnedFile.fileName, pinnedFile.bytesPinned); + totalSize += pinnedFile.bytesPinned; + } + pw.println(); + for (int key : mPinnedApps.keySet()) { + PinnedApp app = mPinnedApps.get(key); + pw.print(getNameForKey(key)); + pw.print(" uid="); pw.print(app.uid); + pw.print(" active="); pw.print(app.active); + pw.println(); + for (PinnedFile pf : mPinnedApps.get(key).mFiles) { + pw.print(" "); pw.format("%s %s\n", pf.fileName, pf.bytesPinned); + totalSize += pf.bytesPinned; + } + } + pw.format("Total size: %s\n", totalSize); + pw.println(); + if (!mPendingRepin.isEmpty()) { + pw.print("Pending repin: "); + for (int key : mPendingRepin.values()) { + pw.print(getNameForKey(key)); pw.print(' '); + } + pw.println(); + } } - pw.format("Total size: %s\n", totalSize); } } @@ -634,8 +867,30 @@ public final class PinnerService extends SystemService { int length; } + /** + * Represents an app that was pinned. + */ + private final class PinnedApp { + + /** + * The uid of the package being pinned. This stays constant while the package stays + * installed. + */ + final int uid; + + /** Whether it is currently active, i.e. there is a running process from that package. */ + boolean active; + + /** List of pinned files. */ + final ArrayList<PinnedFile> mFiles = new ArrayList<>(); + + private PinnedApp(ApplicationInfo appInfo) { + uid = appInfo.uid; + active = mAmInternal.isUidActive(uid); + } + } + final class PinnerHandler extends Handler { - static final int PIN_CAMERA_MSG = 4000; static final int PIN_ONSTART_MSG = 4001; public PinnerHandler(Looper looper) { @@ -645,13 +900,6 @@ public final class PinnerService extends SystemService { @Override public void handleMessage(Message msg) { switch (msg.what) { - - case PIN_CAMERA_MSG: - { - handlePinCamera(msg.arg1); - } - break; - case PIN_ONSTART_MSG: { handlePinOnStart(); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 14eeb7853263..b873d3930e13 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -22465,6 +22465,13 @@ public class ActivityManagerService extends IActivityManager.Stub public void finishUserSwitch(Object uss) { mUserController.finishUserSwitch((UserState) uss); } + + @Override + public Intent getHomeIntent() { + synchronized (ActivityManagerService.this) { + return ActivityManagerService.this.getHomeIntent(); + } + } } /** diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java index 0774672b2fdc..d6ab5f717568 100644 --- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java +++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java @@ -489,7 +489,7 @@ public class BackgroundDexOptService extends JobService { PinnerService pinnerService = LocalServices.getService(PinnerService.class); if (pinnerService != null) { Log.i(TAG, "Pinning optimized code " + updatedPackages); - pinnerService.update(updatedPackages); + pinnerService.update(updatedPackages, false /* force */); } } |