diff options
7 files changed, 213 insertions, 360 deletions
diff --git a/core/tests/overlaytests/device/TEST_MAPPING b/core/tests/overlaytests/device/TEST_MAPPING deleted file mode 100644 index 43ee00f47e84..000000000000 --- a/core/tests/overlaytests/device/TEST_MAPPING +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presubmit": [ - { - "name" : "OverlayDeviceTests" - } - ] -} diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index 437e33d66c91..0f8c9c789a3f 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -29,8 +29,6 @@ import static android.os.Trace.TRACE_TAG_RRO; import static android.os.Trace.traceBegin; import static android.os.Trace.traceEnd; -import static com.android.server.om.OverlayManagerServiceImpl.OperationFailedException; - import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; @@ -50,7 +48,6 @@ import android.content.res.ApkAssets; import android.net.Uri; import android.os.Binder; import android.os.Environment; -import android.os.HandlerThread; import android.os.IBinder; import android.os.RemoteException; import android.os.ResultReceiver; @@ -67,6 +64,7 @@ import android.util.SparseArray; import com.android.internal.content.om.OverlayConfig; import com.android.server.FgThread; +import com.android.server.IoThread; import com.android.server.LocalServices; import com.android.server.SystemConfig; import com.android.server.SystemService; @@ -89,7 +87,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.function.Consumer; +import java.util.concurrent.atomic.AtomicBoolean; /** * Service to manage asset overlays. @@ -238,9 +236,7 @@ public final class OverlayManagerService extends SystemService { private final OverlayActorEnforcer mActorEnforcer; - private final Consumer<PackageAndUser> mOnOverlaysChanged = (pair) -> { - onOverlaysChanged(pair.packageName, pair.userId); - }; + private final AtomicBoolean mPersistSettingsScheduled = new AtomicBoolean(false); public OverlayManagerService(@NonNull final Context context) { super(context); @@ -253,19 +249,17 @@ public final class OverlayManagerService extends SystemService { IdmapManager im = new IdmapManager(IdmapDaemon.getInstance(), mPackageManager); mSettings = new OverlayManagerSettings(); mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings, - OverlayConfig.getSystemInstance(), getDefaultOverlayPackages()); + OverlayConfig.getSystemInstance(), getDefaultOverlayPackages(), + new OverlayChangeListener()); mActorEnforcer = new OverlayActorEnforcer(mPackageManager); - HandlerThread packageReceiverThread = new HandlerThread(TAG); - packageReceiverThread.start(); - final IntentFilter packageFilter = new IntentFilter(); packageFilter.addAction(ACTION_PACKAGE_ADDED); packageFilter.addAction(ACTION_PACKAGE_CHANGED); packageFilter.addAction(ACTION_PACKAGE_REMOVED); packageFilter.addDataScheme("package"); getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL, - packageFilter, null, packageReceiverThread.getThreadHandler()); + packageFilter, null, null); final IntentFilter userFilter = new IntentFilter(); userFilter.addAction(ACTION_USER_ADDED); @@ -318,7 +312,7 @@ public final class OverlayManagerService extends SystemService { final List<String> targets = mImpl.updateOverlaysForUser(newUserId); updateAssets(newUserId, targets); } - persistSettings(); + schedulePersistSettings(); } finally { traceEnd(TRACE_TAG_RRO); } @@ -402,17 +396,10 @@ public final class OverlayManagerService extends SystemService { false); if (pi != null && !pi.applicationInfo.isInstantApp()) { mPackageManager.cachePackageInfo(packageName, userId, pi); - - try { - if (pi.isOverlayPackage()) { - mImpl.onOverlayPackageAdded(packageName, userId) - .ifPresent(mOnOverlaysChanged); - } else { - mImpl.onTargetPackageAdded(packageName, userId) - .ifPresent(mOnOverlaysChanged); - } - } catch (OperationFailedException e) { - Slog.e(TAG, "onPackageAdded internal error", e); + if (pi.isOverlayPackage()) { + mImpl.onOverlayPackageAdded(packageName, userId); + } else { + mImpl.onTargetPackageAdded(packageName, userId); } } } @@ -432,17 +419,10 @@ public final class OverlayManagerService extends SystemService { false); if (pi != null && pi.applicationInfo.isInstantApp()) { mPackageManager.cachePackageInfo(packageName, userId, pi); - - try { - if (pi.isOverlayPackage()) { - mImpl.onOverlayPackageChanged(packageName, userId) - .ifPresent(mOnOverlaysChanged); - } else { - mImpl.onTargetPackageChanged(packageName, userId) - .ifPresent(mOnOverlaysChanged); - } - } catch (OperationFailedException e) { - Slog.e(TAG, "onPackageChanged internal error", e); + if (pi.isOverlayPackage()) { + mImpl.onOverlayPackageChanged(packageName, userId); + } else { + mImpl.onTargetPackageChanged(packageName, userId); } } } @@ -461,12 +441,7 @@ public final class OverlayManagerService extends SystemService { mPackageManager.forgetPackageInfo(packageName, userId); final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId); if (oi != null) { - try { - mImpl.onOverlayPackageReplacing(packageName, userId) - .ifPresent(mOnOverlaysChanged); - } catch (OperationFailedException e) { - Slog.e(TAG, "onPackageReplacing internal error", e); - } + mImpl.onOverlayPackageReplacing(packageName, userId); } } } @@ -485,16 +460,10 @@ public final class OverlayManagerService extends SystemService { false); if (pi != null && !pi.applicationInfo.isInstantApp()) { mPackageManager.cachePackageInfo(packageName, userId, pi); - try { - if (pi.isOverlayPackage()) { - mImpl.onOverlayPackageReplaced(packageName, userId) - .ifPresent(mOnOverlaysChanged); - } else { - mImpl.onTargetPackageReplaced(packageName, userId) - .ifPresent(mOnOverlaysChanged); - } - } catch (OperationFailedException e) { - Slog.e(TAG, "onPackageReplaced internal error", e); + if (pi.isOverlayPackage()) { + mImpl.onOverlayPackageReplaced(packageName, userId); + } else { + mImpl.onTargetPackageReplaced(packageName, userId); } } } @@ -512,17 +481,10 @@ public final class OverlayManagerService extends SystemService { synchronized (mLock) { mPackageManager.forgetPackageInfo(packageName, userId); final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId); - - try { - if (oi != null) { - mImpl.onOverlayPackageRemoved(packageName, userId) - .ifPresent(mOnOverlaysChanged); - } else { - mImpl.onTargetPackageRemoved(packageName, userId) - .ifPresent(mOnOverlaysChanged); - } - } catch (OperationFailedException e) { - Slog.e(TAG, "onPackageRemoved internal error", e); + if (oi != null) { + mImpl.onOverlayPackageRemoved(packageName, userId); + } else { + mImpl.onTargetPackageRemoved(packageName, userId); } } } @@ -640,13 +602,7 @@ public final class OverlayManagerService extends SystemService { final long ident = Binder.clearCallingIdentity(); try { synchronized (mLock) { - try { - mImpl.setEnabled(packageName, enable, realUserId) - .ifPresent(mOnOverlaysChanged); - return true; - } catch (OperationFailedException e) { - return false; - } + return mImpl.setEnabled(packageName, enable, realUserId); } } finally { Binder.restoreCallingIdentity(ident); @@ -671,14 +627,8 @@ public final class OverlayManagerService extends SystemService { final long ident = Binder.clearCallingIdentity(); try { synchronized (mLock) { - try { - mImpl.setEnabledExclusive(packageName, - false /* withinCategory */, realUserId) - .ifPresent(mOnOverlaysChanged); - return true; - } catch (OperationFailedException e) { - return false; - } + return mImpl.setEnabledExclusive(packageName, false /* withinCategory */, + realUserId); } } finally { Binder.restoreCallingIdentity(ident); @@ -704,14 +654,8 @@ public final class OverlayManagerService extends SystemService { final long ident = Binder.clearCallingIdentity(); try { synchronized (mLock) { - try { - mImpl.setEnabledExclusive(packageName, - true /* withinCategory */, realUserId) - .ifPresent(mOnOverlaysChanged); - return true; - } catch (OperationFailedException e) { - return false; - } + return mImpl.setEnabledExclusive(packageName, true /* withinCategory */, + realUserId); } } finally { Binder.restoreCallingIdentity(ident); @@ -737,13 +681,7 @@ public final class OverlayManagerService extends SystemService { final long ident = Binder.clearCallingIdentity(); try { synchronized (mLock) { - try { - mImpl.setPriority(packageName, parentPackageName, realUserId) - .ifPresent(mOnOverlaysChanged); - return true; - } catch (OperationFailedException e) { - return false; - } + return mImpl.setPriority(packageName, parentPackageName, realUserId); } } finally { Binder.restoreCallingIdentity(ident); @@ -767,13 +705,7 @@ public final class OverlayManagerService extends SystemService { final long ident = Binder.clearCallingIdentity(); try { synchronized (mLock) { - try { - mImpl.setHighestPriority(packageName, realUserId) - .ifPresent(mOnOverlaysChanged); - return true; - } catch (OperationFailedException e) { - return false; - } + return mImpl.setHighestPriority(packageName, realUserId); } } finally { Binder.restoreCallingIdentity(ident); @@ -797,13 +729,7 @@ public final class OverlayManagerService extends SystemService { final long ident = Binder.clearCallingIdentity(); try { synchronized (mLock) { - try { - mImpl.setLowestPriority(packageName, realUserId) - .ifPresent(mOnOverlaysChanged); - return true; - } catch (OperationFailedException e) { - return false; - } + return mImpl.setLowestPriority(packageName, realUserId); } } finally { Binder.restoreCallingIdentity(ident); @@ -972,27 +898,31 @@ public final class OverlayManagerService extends SystemService { } }; - private void onOverlaysChanged(@NonNull final String targetPackageName, final int userId) { - persistSettings(); - FgThread.getHandler().post(() -> { - updateAssets(userId, targetPackageName); + private final class OverlayChangeListener + implements OverlayManagerServiceImpl.OverlayChangeListener { + @Override + public void onOverlaysChanged(@NonNull final String targetPackageName, final int userId) { + schedulePersistSettings(); + FgThread.getHandler().post(() -> { + updateAssets(userId, targetPackageName); - final Intent intent = new Intent(ACTION_OVERLAY_CHANGED, - Uri.fromParts("package", targetPackageName, null)); - intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + final Intent intent = new Intent(ACTION_OVERLAY_CHANGED, + Uri.fromParts("package", targetPackageName, null)); + intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - if (DEBUG) { - Slog.d(TAG, "send broadcast " + intent); - } + if (DEBUG) { + Slog.d(TAG, "send broadcast " + intent); + } - try { - ActivityManager.getService().broadcastIntent(null, intent, null, null, 0, - null, null, null, android.app.AppOpsManager.OP_NONE, null, false, false, - userId); - } catch (RemoteException e) { - // Intentionally left empty. - } - }); + try { + ActivityManager.getService().broadcastIntentWithFeature(null, null, intent, + null, null, 0, null, null, null, android.app.AppOpsManager.OP_NONE, + null, false, false, userId); + } catch (RemoteException e) { + // Intentionally left empty. + } + }); + } } /** @@ -1065,21 +995,27 @@ public final class OverlayManagerService extends SystemService { } } - private void persistSettings() { - if (DEBUG) { - Slog.d(TAG, "Writing overlay settings"); + private void schedulePersistSettings() { + if (mPersistSettingsScheduled.getAndSet(true)) { + return; } - synchronized (mLock) { - FileOutputStream stream = null; - try { - stream = mSettingsFile.startWrite(); - mSettings.persist(stream); - mSettingsFile.finishWrite(stream); - } catch (IOException | XmlPullParserException e) { - mSettingsFile.failWrite(stream); - Slog.e(TAG, "failed to persist overlay state", e); + IoThread.getHandler().post(() -> { + mPersistSettingsScheduled.set(false); + if (DEBUG) { + Slog.d(TAG, "Writing overlay settings"); } - } + synchronized (mLock) { + FileOutputStream stream = null; + try { + stream = mSettingsFile.startWrite(); + mSettings.persist(stream); + mSettingsFile.finishWrite(stream); + } catch (IOException | XmlPullParserException e) { + mSettingsFile.failWrite(stream); + Slog.e(TAG, "failed to persist overlay state", e); + } + } + }); } private void restoreSettings() { diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java index e60411bb78c5..05a4a38feef1 100644 --- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java +++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java @@ -45,7 +45,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.Set; /** @@ -72,6 +71,7 @@ final class OverlayManagerServiceImpl { private final OverlayManagerSettings mSettings; private final OverlayConfig mOverlayConfig; private final String[] mDefaultOverlays; + private final OverlayChangeListener mListener; /** * Helper method to merge the overlay manager's (as read from overlays.xml) @@ -114,12 +114,14 @@ final class OverlayManagerServiceImpl { @NonNull final IdmapManager idmapManager, @NonNull final OverlayManagerSettings settings, @NonNull final OverlayConfig overlayConfig, - @NonNull final String[] defaultOverlays) { + @NonNull final String[] defaultOverlays, + @NonNull final OverlayChangeListener listener) { mPackageManager = packageManager; mIdmapManager = idmapManager; mSettings = settings; mOverlayConfig = overlayConfig; mDefaultOverlays = defaultOverlays; + mListener = listener; } /** @@ -257,58 +259,52 @@ final class OverlayManagerServiceImpl { mSettings.removeUser(userId); } - Optional<PackageAndUser> onTargetPackageAdded(@NonNull final String packageName, - final int userId) throws OperationFailedException { + void onTargetPackageAdded(@NonNull final String packageName, final int userId) { if (DEBUG) { Slog.d(TAG, "onTargetPackageAdded packageName=" + packageName + " userId=" + userId); } - return updateAndRefreshOverlaysForTarget(packageName, userId, 0); + updateAndRefreshOverlaysForTarget(packageName, userId, 0); } - Optional<PackageAndUser> onTargetPackageChanged(@NonNull final String packageName, - final int userId) throws OperationFailedException { + void onTargetPackageChanged(@NonNull final String packageName, final int userId) { if (DEBUG) { Slog.d(TAG, "onTargetPackageChanged packageName=" + packageName + " userId=" + userId); } - return updateAndRefreshOverlaysForTarget(packageName, userId, 0); + updateAndRefreshOverlaysForTarget(packageName, userId, 0); } - Optional<PackageAndUser> onTargetPackageReplacing(@NonNull final String packageName, - final int userId) throws OperationFailedException { + void onTargetPackageReplacing(@NonNull final String packageName, final int userId) { if (DEBUG) { Slog.d(TAG, "onTargetPackageReplacing packageName=" + packageName + " userId=" + userId); } - return updateAndRefreshOverlaysForTarget(packageName, userId, 0); + updateAndRefreshOverlaysForTarget(packageName, userId, 0); } - Optional<PackageAndUser> onTargetPackageReplaced(@NonNull final String packageName, - final int userId) throws OperationFailedException { + void onTargetPackageReplaced(@NonNull final String packageName, final int userId) { if (DEBUG) { Slog.d(TAG, "onTargetPackageReplaced packageName=" + packageName + " userId=" + userId); } - return updateAndRefreshOverlaysForTarget(packageName, userId, 0); + updateAndRefreshOverlaysForTarget(packageName, userId, 0); } - Optional<PackageAndUser> onTargetPackageRemoved(@NonNull final String packageName, - final int userId) throws OperationFailedException { + void onTargetPackageRemoved(@NonNull final String packageName, final int userId) { if (DEBUG) { Slog.d(TAG, "onTargetPackageRemoved packageName=" + packageName + " userId=" + userId); } - return updateAndRefreshOverlaysForTarget(packageName, userId, 0); + updateAndRefreshOverlaysForTarget(packageName, userId, 0); } /** * Update the state of any overlays for this target. */ - private Optional<PackageAndUser> updateAndRefreshOverlaysForTarget( - @NonNull final String targetPackageName, final int userId, final int flags) - throws OperationFailedException { + private void updateAndRefreshOverlaysForTarget(@NonNull final String targetPackageName, + final int userId, final int flags) { final List<OverlayInfo> targetOverlays = mSettings.getOverlaysForTarget(targetPackageName, userId); @@ -368,13 +364,11 @@ final class OverlayManagerServiceImpl { } if (modified) { - return Optional.of(new PackageAndUser(targetPackageName, userId)); + mListener.onOverlaysChanged(targetPackageName, userId); } - return Optional.empty(); } - Optional<PackageAndUser> onOverlayPackageAdded(@NonNull final String packageName, - final int userId) throws OperationFailedException { + void onOverlayPackageAdded(@NonNull final String packageName, final int userId) { if (DEBUG) { Slog.d(TAG, "onOverlayPackageAdded packageName=" + packageName + " userId=" + userId); } @@ -382,7 +376,8 @@ final class OverlayManagerServiceImpl { final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId); if (overlayPackage == null) { Slog.w(TAG, "overlay package " + packageName + " was added, but couldn't be found"); - return onOverlayPackageRemoved(packageName, userId); + onOverlayPackageRemoved(packageName, userId); + return; } mSettings.init(packageName, userId, overlayPackage.overlayTarget, @@ -394,17 +389,15 @@ final class OverlayManagerServiceImpl { overlayPackage.overlayCategory); try { if (updateState(overlayPackage.overlayTarget, packageName, userId, 0)) { - return Optional.of(new PackageAndUser(overlayPackage.overlayTarget, userId)); + mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId); } - return Optional.empty(); } catch (OverlayManagerSettings.BadKeyException e) { + Slog.e(TAG, "failed to update settings", e); mSettings.remove(packageName, userId); - throw new OperationFailedException("failed to update settings", e); } } - Optional<PackageAndUser> onOverlayPackageChanged(@NonNull final String packageName, - final int userId) throws OperationFailedException { + void onOverlayPackageChanged(@NonNull final String packageName, final int userId) { if (DEBUG) { Slog.d(TAG, "onOverlayPackageChanged packageName=" + packageName + " userId=" + userId); } @@ -412,16 +405,14 @@ final class OverlayManagerServiceImpl { try { final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId); if (updateState(oi.targetPackageName, packageName, userId, 0)) { - return Optional.of(new PackageAndUser(oi.targetPackageName, userId)); + mListener.onOverlaysChanged(oi.targetPackageName, userId); } - return Optional.empty(); } catch (OverlayManagerSettings.BadKeyException e) { - throw new OperationFailedException("failed to update settings", e); + Slog.e(TAG, "failed to update settings", e); } } - Optional<PackageAndUser> onOverlayPackageReplacing(@NonNull final String packageName, - final int userId) throws OperationFailedException { + void onOverlayPackageReplacing(@NonNull final String packageName, final int userId) { if (DEBUG) { Slog.d(TAG, "onOverlayPackageReplacing packageName=" + packageName + " userId=" + userId); @@ -432,16 +423,14 @@ final class OverlayManagerServiceImpl { if (updateState(oi.targetPackageName, packageName, userId, FLAG_OVERLAY_IS_BEING_REPLACED)) { removeIdmapIfPossible(oi); - return Optional.of(new PackageAndUser(oi.targetPackageName, userId)); + mListener.onOverlaysChanged(oi.targetPackageName, userId); } - return Optional.empty(); } catch (OverlayManagerSettings.BadKeyException e) { - throw new OperationFailedException("failed to update settings", e); + Slog.e(TAG, "failed to update settings", e); } } - Optional<PackageAndUser> onOverlayPackageReplaced(@NonNull final String packageName, - final int userId) throws OperationFailedException { + void onOverlayPackageReplaced(@NonNull final String packageName, final int userId) { if (DEBUG) { Slog.d(TAG, "onOverlayPackageReplaced packageName=" + packageName + " userId=" + userId); @@ -450,12 +439,16 @@ final class OverlayManagerServiceImpl { final PackageInfo pkg = mPackageManager.getPackageInfo(packageName, userId); if (pkg == null) { Slog.w(TAG, "overlay package " + packageName + " was replaced, but couldn't be found"); - return onOverlayPackageRemoved(packageName, userId); + onOverlayPackageRemoved(packageName, userId); + return; } try { final OverlayInfo oldOi = mSettings.getOverlayInfo(packageName, userId); if (mustReinitializeOverlay(pkg, oldOi)) { + if (oldOi != null && !oldOi.targetPackageName.equals(pkg.overlayTarget)) { + mListener.onOverlaysChanged(pkg.overlayTarget, userId); + } mSettings.init(packageName, userId, pkg.overlayTarget, pkg.targetOverlayableName, pkg.applicationInfo.getBaseCodePath(), isPackageConfiguredMutable(pkg.packageName), @@ -464,25 +457,22 @@ final class OverlayManagerServiceImpl { } if (updateState(pkg.overlayTarget, packageName, userId, 0)) { - return Optional.of(new PackageAndUser(pkg.overlayTarget, userId)); + mListener.onOverlaysChanged(pkg.overlayTarget, userId); } - return Optional.empty(); } catch (OverlayManagerSettings.BadKeyException e) { - throw new OperationFailedException("failed to update settings", e); + Slog.e(TAG, "failed to update settings", e); } } - Optional<PackageAndUser> onOverlayPackageRemoved(@NonNull final String packageName, - final int userId) throws OperationFailedException { + void onOverlayPackageRemoved(@NonNull final String packageName, final int userId) { try { final OverlayInfo overlayInfo = mSettings.getOverlayInfo(packageName, userId); if (mSettings.remove(packageName, userId)) { removeIdmapIfPossible(overlayInfo); - return Optional.of(new PackageAndUser(overlayInfo.targetPackageName, userId)); + mListener.onOverlaysChanged(overlayInfo.targetPackageName, userId); } - return Optional.empty(); } catch (OverlayManagerSettings.BadKeyException e) { - throw new OperationFailedException("failed to remove overlay", e); + Slog.e(TAG, "failed to remove overlay", e); } } @@ -503,8 +493,8 @@ final class OverlayManagerServiceImpl { return mSettings.getOverlaysForUser(userId); } - Optional<PackageAndUser> setEnabled(@NonNull final String packageName, final boolean enable, - final int userId) throws OperationFailedException { + boolean setEnabled(@NonNull final String packageName, final boolean enable, + final int userId) { if (DEBUG) { Slog.d(TAG, String.format("setEnabled packageName=%s enable=%s userId=%d", packageName, enable, userId)); @@ -512,33 +502,30 @@ final class OverlayManagerServiceImpl { final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId); if (overlayPackage == null) { - throw new OperationFailedException( - String.format("failed to find overlay package %s for user %d", - packageName, userId)); + return false; } try { final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId); if (!oi.isMutable) { // Ignore immutable overlays. - throw new OperationFailedException( - "cannot enable immutable overlay packages in runtime"); + return false; } boolean modified = mSettings.setEnabled(packageName, userId, enable); modified |= updateState(oi.targetPackageName, oi.packageName, userId, 0); if (modified) { - return Optional.of(new PackageAndUser(oi.targetPackageName, userId)); + mListener.onOverlaysChanged(oi.targetPackageName, userId); } - return Optional.empty(); + return true; } catch (OverlayManagerSettings.BadKeyException e) { - throw new OperationFailedException("failed to update settings", e); + return false; } } - Optional<PackageAndUser> setEnabledExclusive(@NonNull final String packageName, - boolean withinCategory, final int userId) throws OperationFailedException { + boolean setEnabledExclusive(@NonNull final String packageName, boolean withinCategory, + final int userId) { if (DEBUG) { Slog.d(TAG, String.format("setEnabledExclusive packageName=%s" + " withinCategory=%s userId=%d", packageName, withinCategory, userId)); @@ -546,8 +533,7 @@ final class OverlayManagerServiceImpl { final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId); if (overlayPackage == null) { - throw new OperationFailedException(String.format( - "failed to find overlay package %s for user %d", packageName, userId)); + return false; } try { @@ -590,11 +576,11 @@ final class OverlayManagerServiceImpl { modified |= updateState(targetPackageName, packageName, userId, 0); if (modified) { - return Optional.of(new PackageAndUser(targetPackageName, userId)); + mListener.onOverlaysChanged(targetPackageName, userId); } - return Optional.empty(); + return true; } catch (OverlayManagerSettings.BadKeyException e) { - throw new OperationFailedException("failed to update settings", e); + return false; } } @@ -610,75 +596,66 @@ final class OverlayManagerServiceImpl { return mOverlayConfig.isEnabled(packageName); } - Optional<PackageAndUser> setPriority(@NonNull final String packageName, - @NonNull final String newParentPackageName, final int userId) - throws OperationFailedException { + boolean setPriority(@NonNull final String packageName, + @NonNull final String newParentPackageName, final int userId) { if (DEBUG) { Slog.d(TAG, "setPriority packageName=" + packageName + " newParentPackageName=" + newParentPackageName + " userId=" + userId); } if (!isPackageConfiguredMutable(packageName)) { - throw new OperationFailedException(String.format( - "overlay package %s user %d is not updatable", packageName, userId)); + return false; } final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId); if (overlayPackage == null) { - throw new OperationFailedException(String.format( - "failed to find overlay package %s for user %d", packageName, userId)); + return false; } if (mSettings.setPriority(packageName, newParentPackageName, userId)) { - return Optional.of(new PackageAndUser(overlayPackage.overlayTarget, userId)); + mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId); } - return Optional.empty(); + return true; } - Optional<PackageAndUser> setHighestPriority(@NonNull final String packageName, - final int userId) throws OperationFailedException { + boolean setHighestPriority(@NonNull final String packageName, final int userId) { if (DEBUG) { Slog.d(TAG, "setHighestPriority packageName=" + packageName + " userId=" + userId); } if (!isPackageConfiguredMutable(packageName)) { - throw new OperationFailedException(String.format( - "overlay package %s user %d is not updatable", packageName, userId)); + return false; } final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId); if (overlayPackage == null) { - throw new OperationFailedException(String.format( - "failed to find overlay package %s for user %d", packageName, userId)); + return false; } if (mSettings.setHighestPriority(packageName, userId)) { - return Optional.of(new PackageAndUser(overlayPackage.overlayTarget, userId)); + mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId); } - return Optional.empty(); + return true; } - Optional<PackageAndUser> setLowestPriority(@NonNull final String packageName, final int userId) - throws OperationFailedException { + boolean setLowestPriority(@NonNull final String packageName, final int userId) { if (DEBUG) { Slog.d(TAG, "setLowestPriority packageName=" + packageName + " userId=" + userId); } if (!isPackageConfiguredMutable(packageName)) { - throw new OperationFailedException(String.format( - "overlay package %s user %d is not updatable", packageName, userId)); + return false; } final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId); if (overlayPackage == null) { - throw new OperationFailedException(String.format( - "failed to find overlay package %s for user %d", packageName, userId)); + return false; } if (mSettings.setLowestPriority(packageName, userId)) { - return Optional.of(new PackageAndUser(overlayPackage.overlayTarget, userId)); + mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId); } - return Optional.empty(); + return true; } void dump(@NonNull final PrintWriter pw, @NonNull DumpState dumpState) { @@ -820,13 +797,12 @@ final class OverlayManagerServiceImpl { mIdmapManager.removeIdmap(oi, oi.userId); } - static final class OperationFailedException extends Exception { - OperationFailedException(@NonNull final String message) { - super(message); - } + interface OverlayChangeListener { - OperationFailedException(@NonNull final String message, @NonNull Throwable cause) { - super(message, cause); - } + /** + * An event triggered by changes made to overlay state or settings as well as changes that + * add or remove target packages of overlays. + **/ + void onOverlaysChanged(@NonNull String targetPackage, int userId); } } diff --git a/services/core/java/com/android/server/om/PackageAndUser.java b/services/core/java/com/android/server/om/PackageAndUser.java deleted file mode 100644 index 5c38ba7ce97b..000000000000 --- a/services/core/java/com/android/server/om/PackageAndUser.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2020 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.om; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.UserIdInt; - -final class PackageAndUser { - public final @NonNull String packageName; - public final @UserIdInt int userId; - - PackageAndUser(@NonNull String packageName, @UserIdInt int userId) { - this.packageName = packageName; - this.userId = userId; - } - - @Override - public boolean equals(@Nullable Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof PackageAndUser)) { - return false; - } - PackageAndUser other = (PackageAndUser) obj; - return packageName.equals(other.packageName) && userId == other.userId; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + packageName.hashCode(); - result = prime * result + userId; - return result; - } - - @Override - public String toString() { - return String.format("PackageAndUser{packageName=%s, userId=%d}", packageName, userId); - } -} diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java index 5468fba59c10..391611b72dab 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java @@ -78,7 +78,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI } @Test - public void testImmutableEnabledChange() throws Exception { + public void testImmutableEnabledChange() { final OverlayManagerServiceImpl impl = getImpl(); installNewPackage(target(TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER); @@ -106,7 +106,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI } @Test - public void testMutableEnabledChangeHasNoEffect() throws Exception { + public void testMutableEnabledChangeHasNoEffect() { final OverlayManagerServiceImpl impl = getImpl(); installNewPackage(target(TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER); @@ -134,7 +134,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI } @Test - public void testMutableEnabledToImmutableEnabled() throws Exception { + public void testMutableEnabledToImmutableEnabled() { final OverlayManagerServiceImpl impl = getImpl(); installNewPackage(target(TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER); @@ -178,7 +178,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI } @Test - public void testMutablePriorityChange() throws Exception { + public void testMutablePriorityChange() { final OverlayManagerServiceImpl impl = getImpl(); installNewPackage(target(TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER); @@ -218,7 +218,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI } @Test - public void testImmutablePriorityChange() throws Exception { + public void testImmutablePriorityChange() { final OverlayManagerServiceImpl impl = getImpl(); installNewPackage(target(TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER); diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java index 33dbcc0855be..4f882ce13dd4 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java @@ -22,14 +22,11 @@ import static android.content.om.OverlayInfo.STATE_MISSING_TARGET; import static android.os.OverlayablePolicy.CONFIG_SIGNATURE; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import static org.testng.Assert.assertThrows; import android.content.om.OverlayInfo; -import android.util.Pair; import androidx.test.runner.AndroidJUnit4; @@ -38,7 +35,6 @@ import org.junit.runner.RunWith; import java.util.List; import java.util.Map; -import java.util.Optional; @RunWith(AndroidJUnit4.class) public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTestsBase { @@ -59,7 +55,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes private static final String CERT_CONFIG_NOK = "config_certificate_nok"; @Test - public void testGetOverlayInfo() throws Exception { + public void testGetOverlayInfo() { installNewPackage(overlay(OVERLAY, TARGET), USER); final OverlayManagerServiceImpl impl = getImpl(); @@ -71,7 +67,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes } @Test - public void testGetOverlayInfosForTarget() throws Exception { + public void testGetOverlayInfosForTarget() { installNewPackage(overlay(OVERLAY, TARGET), USER); installNewPackage(overlay(OVERLAY2, TARGET), USER); installNewPackage(overlay(OVERLAY3, TARGET), USER2); @@ -96,7 +92,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes } @Test - public void testGetOverlayInfosForUser() throws Exception { + public void testGetOverlayInfosForUser() { installNewPackage(target(TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER); installNewPackage(overlay(OVERLAY2, TARGET), USER); @@ -123,7 +119,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes } @Test - public void testPriority() throws Exception { + public void testPriority() { installNewPackage(overlay(OVERLAY, TARGET), USER); installNewPackage(overlay(OVERLAY2, TARGET), USER); installNewPackage(overlay(OVERLAY3, TARGET), USER); @@ -135,21 +131,18 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes assertOverlayInfoForTarget(TARGET, USER, o1, o2, o3); - assertEquals(impl.setLowestPriority(OVERLAY3, USER), - Optional.of(new PackageAndUser(TARGET, USER))); + assertTrue(impl.setLowestPriority(OVERLAY3, USER)); assertOverlayInfoForTarget(TARGET, USER, o3, o1, o2); - assertEquals(impl.setHighestPriority(OVERLAY3, USER), - Optional.of(new PackageAndUser(TARGET, USER))); + assertTrue(impl.setHighestPriority(OVERLAY3, USER)); assertOverlayInfoForTarget(TARGET, USER, o1, o2, o3); - assertEquals(impl.setPriority(OVERLAY, OVERLAY2, USER), - Optional.of(new PackageAndUser(TARGET, USER))); + assertTrue(impl.setPriority(OVERLAY, OVERLAY2, USER)); assertOverlayInfoForTarget(TARGET, USER, o2, o1, o3); } @Test - public void testOverlayInfoStateTransitions() throws Exception { + public void testOverlayInfoStateTransitions() { final OverlayManagerServiceImpl impl = getImpl(); assertNull(impl.getOverlayInfo(OVERLAY, USER)); @@ -160,8 +153,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes installNewPackage(target, USER); assertState(STATE_DISABLED, OVERLAY, USER); - assertEquals(impl.setEnabled(OVERLAY, true, USER), - Optional.of(new PackageAndUser(TARGET, USER))); + impl.setEnabled(OVERLAY, true, USER); assertState(STATE_ENABLED, OVERLAY, USER); // target upgrades do not change the state of the overlay @@ -176,40 +168,50 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes } @Test - public void testOnOverlayPackageUpgraded() throws Exception { + public void testOnOverlayPackageUpgraded() { + final FakeListener listener = getListener(); final FakeDeviceState.PackageBuilder target = target(TARGET); final FakeDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET); installNewPackage(target, USER); installNewPackage(overlay, USER); + listener.count = 0; upgradePackage(overlay, USER); + assertEquals(2, listener.count); // upgrade to a version where the overlay has changed its target + // expect once for the old target package, once for the new target package + listener.count = 0; final FakeDeviceState.PackageBuilder overlay2 = overlay(OVERLAY, "some.other.target"); - final Pair<Optional<PackageAndUser>, Optional<PackageAndUser>> pair = - upgradePackage(overlay2, USER); - assertEquals(pair.first, Optional.of(new PackageAndUser(TARGET, USER))); - assertEquals(pair.second, Optional.of(new PackageAndUser("some.other.target", USER))); + upgradePackage(overlay2, USER); + assertEquals(3, listener.count); + + listener.count = 0; + upgradePackage(overlay2, USER); + assertEquals(2, listener.count); } @Test - public void testSetEnabledAtVariousConditions() throws Exception { + public void testListener() { final OverlayManagerServiceImpl impl = getImpl(); - assertThrows(OverlayManagerServiceImpl.OperationFailedException.class, - () -> impl.setEnabled(OVERLAY, true, USER)); + final FakeListener listener = getListener(); + installNewPackage(overlay(OVERLAY, TARGET), USER); + assertEquals(1, listener.count); + listener.count = 0; - // request succeeded, and there was a change that needs to be - // propagated to the rest of the system installNewPackage(target(TARGET), USER); - installNewPackage(overlay(OVERLAY, TARGET), USER); - assertEquals(impl.setEnabled(OVERLAY, true, USER), - Optional.of(new PackageAndUser(TARGET, USER))); + assertEquals(1, listener.count); + listener.count = 0; + + impl.setEnabled(OVERLAY, true, USER); + assertEquals(1, listener.count); + listener.count = 0; - // request succeeded, but nothing changed - assertFalse(impl.setEnabled(OVERLAY, true, USER).isPresent()); + impl.setEnabled(OVERLAY, true, USER); + assertEquals(0, listener.count); } @Test - public void testConfigSignaturePolicyOk() throws Exception { + public void testConfigSignaturePolicyOk() { setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG); reinitializeImpl(); @@ -227,7 +229,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes } @Test - public void testConfigSignaturePolicyCertNok() throws Exception { + public void testConfigSignaturePolicyCertNok() { setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG); reinitializeImpl(); @@ -245,7 +247,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes } @Test - public void testConfigSignaturePolicyNoConfig() throws Exception { + public void testConfigSignaturePolicyNoConfig() { addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER); installNewPackage(target(TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER); @@ -260,7 +262,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes } @Test - public void testConfigSignaturePolicyNoRefPkg() throws Exception { + public void testConfigSignaturePolicyNoRefPkg() { installNewPackage(target(TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER); @@ -274,7 +276,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes } @Test - public void testConfigSignaturePolicyRefPkgNotSystem() throws Exception { + public void testConfigSignaturePolicyRefPkgNotSystem() { setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG); reinitializeImpl(); diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java index 2c477c897b30..006dda0f80e3 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java @@ -16,8 +16,6 @@ package com.android.server.om; -import static com.android.server.om.OverlayManagerServiceImpl.OperationFailedException; - import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; @@ -32,7 +30,6 @@ import android.content.pm.PackageInfo; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; -import android.util.Pair; import androidx.annotation.Nullable; @@ -46,13 +43,13 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.stream.Collectors; /** Base class for creating {@link OverlayManagerServiceImplTests} tests. */ class OverlayManagerServiceImplTestsBase { private OverlayManagerServiceImpl mImpl; private FakeDeviceState mState; + private FakeListener mListener; private FakePackageManagerHelper mPackageManager; private FakeIdmapDaemon mIdmapDaemon; private OverlayConfig mOverlayConfig; @@ -61,6 +58,7 @@ class OverlayManagerServiceImplTestsBase { @Before public void setUp() { mState = new FakeDeviceState(); + mListener = new FakeListener(); mPackageManager = new FakePackageManagerHelper(mState); mIdmapDaemon = new FakeIdmapDaemon(mState); mOverlayConfig = mock(OverlayConfig.class); @@ -75,13 +73,18 @@ class OverlayManagerServiceImplTestsBase { new IdmapManager(mIdmapDaemon, mPackageManager), new OverlayManagerSettings(), mOverlayConfig, - new String[0]); + new String[0], + mListener); } OverlayManagerServiceImpl getImpl() { return mImpl; } + FakeListener getListener() { + return mListener; + } + FakeIdmapDaemon getIdmapd() { return mIdmapDaemon; } @@ -152,8 +155,7 @@ class OverlayManagerServiceImplTestsBase { * * @throws IllegalStateException if the package is currently installed */ - void installNewPackage(FakeDeviceState.PackageBuilder pkg, int userId) - throws OperationFailedException { + void installNewPackage(FakeDeviceState.PackageBuilder pkg, int userId) { if (mState.select(pkg.packageName, userId) != null) { throw new IllegalStateException("package " + pkg.packageName + " already installed"); } @@ -174,30 +176,23 @@ class OverlayManagerServiceImplTestsBase { * {@link android.content.Intent#ACTION_PACKAGE_ADDED} broadcast with the * {@link android.content.Intent#EXTRA_REPLACING} extra. * - * @return the two Optional<PackageAndUser> objects from starting and finishing the upgrade - * * @throws IllegalStateException if the package is not currently installed */ - Pair<Optional<PackageAndUser>, Optional<PackageAndUser>> upgradePackage( - FakeDeviceState.PackageBuilder pkg, int userId) throws OperationFailedException { + void upgradePackage(FakeDeviceState.PackageBuilder pkg, int userId) { final FakeDeviceState.Package replacedPackage = mState.select(pkg.packageName, userId); if (replacedPackage == null) { throw new IllegalStateException("package " + pkg.packageName + " not installed"); } - Optional<PackageAndUser> opt1 = Optional.empty(); if (replacedPackage.targetPackageName != null) { - opt1 = mImpl.onOverlayPackageReplacing(pkg.packageName, userId); + mImpl.onOverlayPackageReplacing(pkg.packageName, userId); } mState.add(pkg, userId); - Optional<PackageAndUser> opt2; if (pkg.targetPackage == null) { - opt2 = mImpl.onTargetPackageReplaced(pkg.packageName, userId); + mImpl.onTargetPackageReplaced(pkg.packageName, userId); } else { - opt2 = mImpl.onOverlayPackageReplaced(pkg.packageName, userId); + mImpl.onOverlayPackageReplaced(pkg.packageName, userId); } - - return Pair.create(opt1, opt2); } /** @@ -208,7 +203,7 @@ class OverlayManagerServiceImplTestsBase { * * @throws IllegalStateException if the package is not currently installed */ - void uninstallPackage(String packageName, int userId) throws OperationFailedException { + void uninstallPackage(String packageName, int userId) { final FakeDeviceState.Package pkg = mState.select(packageName, userId); if (pkg == null) { throw new IllegalStateException("package " + packageName+ " not installed"); @@ -490,4 +485,12 @@ class OverlayManagerServiceImplTestsBase { } } } + + static class FakeListener implements OverlayManagerServiceImpl.OverlayChangeListener { + public int count; + + public void onOverlaysChanged(@NonNull String targetPackage, int userId) { + count++; + } + } } |