Loading core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java +7 −4 Original line number Diff line number Diff line Loading @@ -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)); Loading @@ -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); } } Loading Loading @@ -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)); Loading Loading @@ -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(); } Loading services/core/java/com/android/server/om/OverlayManagerService.java +19 −18 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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) { Loading @@ -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()); Loading Loading @@ -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) { Loading @@ -1113,20 +1128,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). * Loading services/core/java/com/android/server/om/OverlayManagerServiceImpl.java +1 −10 Original line number Diff line number Diff line Loading @@ -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(); Loading services/core/java/com/android/server/om/OverlayManagerSettings.java +25 −1 Original line number Diff line number Diff line Loading @@ -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)); Loading services/core/java/com/android/server/om/OverlayManagerShellCommand.java +10 −12 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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:"); Loading @@ -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) { Loading Loading @@ -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) { Loading Loading @@ -269,7 +270,6 @@ final class OverlayManagerShellCommand extends ShellCommand { return 1; } int userId = UserHandle.USER_SYSTEM; String targetPackage = ""; String targetOverlayable = ""; String name = ""; Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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) { Loading Loading @@ -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) { Loading @@ -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(); Loading Loading
core/tests/overlaytests/host/src/com/android/server/om/hosttest/InstallOverlayTests.java +7 −4 Original line number Diff line number Diff line Loading @@ -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)); Loading @@ -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); } } Loading Loading @@ -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)); Loading Loading @@ -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(); } Loading
services/core/java/com/android/server/om/OverlayManagerService.java +19 −18 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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) { Loading @@ -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()); Loading Loading @@ -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) { Loading @@ -1113,20 +1128,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). * Loading
services/core/java/com/android/server/om/OverlayManagerServiceImpl.java +1 −10 Original line number Diff line number Diff line Loading @@ -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(); Loading
services/core/java/com/android/server/om/OverlayManagerSettings.java +25 −1 Original line number Diff line number Diff line Loading @@ -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)); Loading
services/core/java/com/android/server/om/OverlayManagerShellCommand.java +10 −12 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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:"); Loading @@ -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) { Loading Loading @@ -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) { Loading Loading @@ -269,7 +270,6 @@ final class OverlayManagerShellCommand extends ShellCommand { return 1; } int userId = UserHandle.USER_SYSTEM; String targetPackage = ""; String targetOverlayable = ""; String name = ""; Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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) { Loading Loading @@ -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) { Loading @@ -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(); Loading