summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jorim Jaggi <jjaggi@google.com> 2018-07-09 17:57:10 +0200
committer Jorim Jaggi <jjaggi@google.com> 2018-07-13 15:16:48 +0200
commit402d78ebb74e9642f6e291b7b13768b993d7519c (patch)
tree35b76eedc10d0cb138bfd57b43a4e3ca8b9546b5
parentca8a8a999b271c65148e70970f6dda4389b8e458 (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
-rw-r--r--core/java/android/app/ActivityManagerInternal.java6
-rw-r--r--core/res/res/values/config.xml3
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--services/core/java/com/android/server/PinnerService.java458
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java7
-rw-r--r--services/core/java/com/android/server/pm/BackgroundDexOptService.java2
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 */);
}
}