diff options
5 files changed, 62 insertions, 45 deletions
diff --git a/core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java b/core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java index 36c73e2e979e..c42ddd3412be 100644 --- a/core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java +++ b/core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java @@ -44,8 +44,11 @@ public class InstallOverlayTests extends BaseHostJUnit4Test { "com.android.server.om.hosttest.update_overlay_test"; private static final String DEVICE_TEST_CLS = DEVICE_TEST_PKG + ".UpdateOverlayTest"; + private int mCurrentUserid; + @Before public void ensureNoOverlays() throws Exception { + mCurrentUserid = getDevice().getCurrentUser(); // Make sure we're starting with a clean slate. for (String pkg : ALL_PACKAGES) { assertFalse(pkg + " should not be installed", isPackageInstalled(pkg)); @@ -62,7 +65,7 @@ public class InstallOverlayTests extends BaseHostJUnit4Test { @After public void uninstallOverlays() throws Exception { for (String pkg : ALL_PACKAGES) { - uninstallPackage(pkg); + getDevice().uninstallPackageForUser(pkg, mCurrentUserid); } } @@ -166,7 +169,7 @@ public class InstallOverlayTests extends BaseHostJUnit4Test { installPackage("OverlayHostTests_AppOverlayV1.apk"); assertTrue(getDevice().executeShellCommand("cat /data/system/overlays.xml") .contains(APP_OVERLAY_PACKAGE_NAME)); - uninstallPackage(APP_OVERLAY_PACKAGE_NAME); + getDevice().uninstallPackageForUser(APP_OVERLAY_PACKAGE_NAME, mCurrentUserid); delay(); assertFalse(getDevice().executeShellCommand("cat /data/system/overlays.xml") .contains(APP_OVERLAY_PACKAGE_NAME)); @@ -200,12 +203,12 @@ public class InstallOverlayTests extends BaseHostJUnit4Test { } private void installPackage(String pkg) throws Exception { - super.installPackage(pkg); + super.installPackageAsUser(pkg, true /* grantPermission */, mCurrentUserid); delay(); } private void installInstantPackage(String pkg) throws Exception { - super.installPackage(pkg, "--instant"); + super.installPackageAsUser(pkg, true /* grantPermission */, mCurrentUserid, "--instant"); delay(); } diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index 8710438d76b3..0c2b712fc3ab 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -403,6 +403,20 @@ public final class OverlayManagerService extends SystemService { return userIds; } + /** + * Ensure that the caller has permission to interact with the given userId. + * If the calling user is not the same as the provided user, the caller needs + * to hold the INTERACT_ACROSS_USERS_FULL permission (or be system uid or + * root). + * + * @param userId the user to interact with + * @param message message for any SecurityException + */ + static int handleIncomingUser(final int userId, @NonNull final String message) { + return ActivityManager.handleIncomingUser(Binder.getCallingPid(), + Binder.getCallingUid(), userId, false, true, message, null); + } + private void handlePackageAdd(String packageName, Bundle extras, int userId) { final boolean replacing = extras.getBoolean(Intent.EXTRA_REPLACING, false); if (replacing) { @@ -1037,7 +1051,7 @@ public final class OverlayManagerService extends SystemService { @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { final DumpState dumpState = new DumpState(); - dumpState.setUserId(UserHandle.USER_ALL); + int userId = UserHandle.USER_ALL; int opti = 0; while (opti < args.length) { @@ -1064,9 +1078,7 @@ public final class OverlayManagerService extends SystemService { return; } try { - final int userId = UserHandle.parseUserArg(args[opti]); - final int realUserId = handleIncomingUser(userId, "dump"); - dumpState.setUserId(realUserId); + userId = UserHandle.parseUserArg(args[opti]); opti++; } catch (Exception e) { pw.println("Error: " + e.getMessage()); @@ -1105,6 +1117,9 @@ public final class OverlayManagerService extends SystemService { } enforceDumpPermission("dump"); + final int realUserId = userId != UserHandle.USER_ALL + ? handleIncomingUser(userId, "dump") : userId; + dumpState.setUserId(realUserId); synchronized (mLock) { mImpl.dump(pw, dumpState); if (dumpState.getPackageName() == null) { @@ -1114,20 +1129,6 @@ public final class OverlayManagerService extends SystemService { } /** - * Ensure that the caller has permission to interact with the given userId. - * If the calling user is not the same as the provided user, the caller needs - * to hold the INTERACT_ACROSS_USERS_FULL permission (or be system uid or - * root). - * - * @param userId the user to interact with - * @param message message for any SecurityException - */ - private int handleIncomingUser(final int userId, @NonNull final String message) { - return ActivityManager.handleIncomingUser(Binder.getCallingPid(), - Binder.getCallingUid(), userId, false, true, message, null); - } - - /** * Enforce that the caller holds the DUMP permission (or is system or root). * * @param message used as message if SecurityException is thrown diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java index 0e9ec4d71421..02c0190224d0 100644 --- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java +++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java @@ -715,20 +715,11 @@ final class OverlayManagerServiceImpl { } void dump(@NonNull final PrintWriter pw, @NonNull DumpState dumpState) { - Pair<OverlayIdentifier, String> overlayIdmap = null; - if (dumpState.getPackageName() != null) { - OverlayIdentifier id = new OverlayIdentifier(dumpState.getPackageName(), - dumpState.getOverlayName()); - OverlayInfo oi = mSettings.getNullableOverlayInfo(id, USER_SYSTEM); - if (oi != null) { - overlayIdmap = new Pair<>(id, oi.baseCodePath); - } - } - // settings mSettings.dump(pw, dumpState); // idmap data + final var overlayIdmap = mSettings.getIdentifierAndBaseCodePath(dumpState); if (dumpState.getField() == null) { Set<Pair<OverlayIdentifier, String>> allIdmaps = (overlayIdmap != null) ? Set.of(overlayIdmap) : mSettings.getAllIdentifiersAndBaseCodePaths(); diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java index f9758fcd5d01..e6b1c5f640f2 100644 --- a/services/core/java/com/android/server/om/OverlayManagerSettings.java +++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java @@ -212,17 +212,41 @@ final class OverlayManagerSettings { } Set<String> getAllBaseCodePaths() { + // Overlays installed for multiple users have the same code path, avoid duplicates with Set. final Set<String> paths = new ArraySet<>(); mItems.forEach(item -> paths.add(item.mBaseCodePath)); return paths; } Set<Pair<OverlayIdentifier, String>> getAllIdentifiersAndBaseCodePaths() { + // Overlays installed for multiple users have the same code path, avoid duplicates with Set. final Set<Pair<OverlayIdentifier, String>> set = new ArraySet<>(); - mItems.forEach(item -> set.add(new Pair(item.mOverlay, item.mBaseCodePath))); + mItems.forEach(item -> set.add(new Pair<>(item.mOverlay, item.mBaseCodePath))); return set; } + @Nullable + Pair<OverlayIdentifier, String> getIdentifierAndBaseCodePath(@NonNull DumpState dumpState) { + if (dumpState.getPackageName() == null) { + return null; + } + OverlayIdentifier id = new OverlayIdentifier(dumpState.getPackageName(), + dumpState.getOverlayName()); + final int userId = dumpState.getUserId(); + for (int i = 0; i < mItems.size(); i++) { + final var item = mItems.get(i); + if (userId != UserHandle.USER_ALL && userId != item.mUserId) { + continue; + } + if (!id.equals(item.mOverlay)) { + continue; + } + // Overlays installed for multiple users have the same code path, return first found. + return new Pair<>(id, item.mBaseCodePath); + } + return null; + } + @NonNull List<OverlayInfo> removeIf(@NonNull final Predicate<OverlayInfo> predicate, final int userId) { return removeIf(info -> (predicate.test(info) && info.userId == userId)); diff --git a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java index b7f21125148c..39a6b1895c3a 100644 --- a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java +++ b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java @@ -17,6 +17,7 @@ package com.android.server.om; import static com.android.internal.content.om.OverlayConfig.PARTITION_ORDER_FILE_PATH; +import static com.android.server.om.OverlayManagerService.handleIncomingUser; import android.annotation.NonNull; import android.annotation.Nullable; @@ -145,7 +146,7 @@ final class OverlayManagerShellCommand extends ShellCommand { out.println(" Load a package and print the value of a given resource"); out.println(" applying the current configuration and enabled overlays."); out.println(" For a more fine-grained alternative, use 'idmap2 lookup'."); - out.println(" fabricate [--user USER_ID] [--target-name OVERLAYABLE] --target PACKAGE"); + out.println(" fabricate [--target-name OVERLAYABLE] --target PACKAGE"); out.println(" --name NAME [--file FILE] "); out.println(" PACKAGE:TYPE/NAME ENCODED-TYPE-ID|TYPE-NAME ENCODED-VALUE"); out.println(" Create an overlay from a single resource. Caller must be root. Example:"); @@ -160,7 +161,7 @@ final class OverlayManagerShellCommand extends ShellCommand { final PrintWriter out = getOutPrintWriter(); final PrintWriter err = getErrPrintWriter(); - int userId = UserHandle.USER_SYSTEM; + int userId = UserHandle.USER_CURRENT; String opt; while ((opt = getNextOption()) != null) { switch (opt) { @@ -234,7 +235,7 @@ final class OverlayManagerShellCommand extends ShellCommand { private int runEnableDisable(final boolean enable) throws RemoteException { final PrintWriter err = getErrPrintWriter(); - int userId = UserHandle.USER_SYSTEM; + int userId = UserHandle.USER_CURRENT; String opt; while ((opt = getNextOption()) != null) { switch (opt) { @@ -269,7 +270,6 @@ final class OverlayManagerShellCommand extends ShellCommand { return 1; } - int userId = UserHandle.USER_SYSTEM; String targetPackage = ""; String targetOverlayable = ""; String name = ""; @@ -278,9 +278,6 @@ final class OverlayManagerShellCommand extends ShellCommand { String config = null; while ((opt = getNextOption()) != null) { switch (opt) { - case "--user": - userId = UserHandle.parseUserArg(getNextArgRequired()); - break; case "--target": targetPackage = getNextArgRequired(); break; @@ -442,7 +439,7 @@ final class OverlayManagerShellCommand extends ShellCommand { private int runEnableExclusive() throws RemoteException { final PrintWriter err = getErrPrintWriter(); - int userId = UserHandle.USER_SYSTEM; + int userId = UserHandle.USER_CURRENT; boolean inCategory = false; String opt; while ((opt = getNextOption()) != null) { @@ -469,7 +466,7 @@ final class OverlayManagerShellCommand extends ShellCommand { private int runSetPriority() throws RemoteException { final PrintWriter err = getErrPrintWriter(); - int userId = UserHandle.USER_SYSTEM; + int userId = UserHandle.USER_CURRENT; String opt; while ((opt = getNextOption()) != null) { switch (opt) { @@ -498,7 +495,7 @@ final class OverlayManagerShellCommand extends ShellCommand { final PrintWriter out = getOutPrintWriter(); final PrintWriter err = getErrPrintWriter(); - int userId = UserHandle.USER_SYSTEM; + int userId = UserHandle.USER_CURRENT; boolean verbose = false; String opt; while ((opt = getNextOption()) != null) { @@ -525,15 +522,16 @@ final class OverlayManagerShellCommand extends ShellCommand { return 1; } + final int realUserId = handleIncomingUser(userId, "runLookup"); final Resources res; try { res = mContext - .createContextAsUser(UserHandle.of(userId), /* flags */ 0) + .createContextAsUser(UserHandle.of(realUserId), /* flags */ 0) .getPackageManager() .getResourcesForApplication(packageToLoad); } catch (PackageManager.NameNotFoundException e) { err.println(String.format("Error: failed to get resources for package %s for user %d", - packageToLoad, userId)); + packageToLoad, realUserId)); return 1; } final AssetManager assets = res.getAssets(); |