summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/om/OverlayManagerService.java168
-rw-r--r--services/core/java/com/android/server/om/OverlayManagerServiceImpl.java172
-rw-r--r--services/core/java/com/android/server/om/PackageAndUser.java57
-rw-r--r--services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java76
-rw-r--r--services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java41
6 files changed, 335 insertions, 189 deletions
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 0f8c9c789a3f..40ac204e440c 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -29,6 +29,8 @@ 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;
@@ -88,6 +90,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Consumer;
/**
* Service to manage asset overlays.
@@ -238,6 +241,10 @@ public final class OverlayManagerService extends SystemService {
private final AtomicBoolean mPersistSettingsScheduled = new AtomicBoolean(false);
+ private final Consumer<PackageAndUser> mOnOverlaysChanged = (pair) -> {
+ onOverlaysChanged(pair.packageName, pair.userId);
+ };
+
public OverlayManagerService(@NonNull final Context context) {
super(context);
try {
@@ -249,8 +256,7 @@ 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(),
- new OverlayChangeListener());
+ OverlayConfig.getSystemInstance(), getDefaultOverlayPackages());
mActorEnforcer = new OverlayActorEnforcer(mPackageManager);
final IntentFilter packageFilter = new IntentFilter();
@@ -396,10 +402,17 @@ public final class OverlayManagerService extends SystemService {
false);
if (pi != null && !pi.applicationInfo.isInstantApp()) {
mPackageManager.cachePackageInfo(packageName, userId, pi);
- if (pi.isOverlayPackage()) {
- mImpl.onOverlayPackageAdded(packageName, userId);
- } else {
- mImpl.onTargetPackageAdded(packageName, userId);
+
+ 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);
}
}
}
@@ -419,10 +432,17 @@ public final class OverlayManagerService extends SystemService {
false);
if (pi != null && pi.applicationInfo.isInstantApp()) {
mPackageManager.cachePackageInfo(packageName, userId, pi);
- if (pi.isOverlayPackage()) {
- mImpl.onOverlayPackageChanged(packageName, userId);
- } else {
- mImpl.onTargetPackageChanged(packageName, userId);
+
+ 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);
}
}
}
@@ -441,7 +461,12 @@ public final class OverlayManagerService extends SystemService {
mPackageManager.forgetPackageInfo(packageName, userId);
final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
if (oi != null) {
- mImpl.onOverlayPackageReplacing(packageName, userId);
+ try {
+ mImpl.onOverlayPackageReplacing(packageName, userId)
+ .ifPresent(mOnOverlaysChanged);
+ } catch (OperationFailedException e) {
+ Slog.e(TAG, "onPackageReplacing internal error", e);
+ }
}
}
}
@@ -460,10 +485,16 @@ public final class OverlayManagerService extends SystemService {
false);
if (pi != null && !pi.applicationInfo.isInstantApp()) {
mPackageManager.cachePackageInfo(packageName, userId, pi);
- if (pi.isOverlayPackage()) {
- mImpl.onOverlayPackageReplaced(packageName, userId);
- } else {
- mImpl.onTargetPackageReplaced(packageName, userId);
+ 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);
}
}
}
@@ -481,10 +512,17 @@ public final class OverlayManagerService extends SystemService {
synchronized (mLock) {
mPackageManager.forgetPackageInfo(packageName, userId);
final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
- if (oi != null) {
- mImpl.onOverlayPackageRemoved(packageName, userId);
- } else {
- mImpl.onTargetPackageRemoved(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);
}
}
}
@@ -602,7 +640,13 @@ public final class OverlayManagerService extends SystemService {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- return mImpl.setEnabled(packageName, enable, realUserId);
+ try {
+ mImpl.setEnabled(packageName, enable, realUserId)
+ .ifPresent(mOnOverlaysChanged);
+ return true;
+ } catch (OperationFailedException e) {
+ return false;
+ }
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -627,8 +671,14 @@ public final class OverlayManagerService extends SystemService {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- return mImpl.setEnabledExclusive(packageName, false /* withinCategory */,
- realUserId);
+ try {
+ mImpl.setEnabledExclusive(packageName,
+ false /* withinCategory */, realUserId)
+ .ifPresent(mOnOverlaysChanged);
+ return true;
+ } catch (OperationFailedException e) {
+ return false;
+ }
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -654,8 +704,14 @@ public final class OverlayManagerService extends SystemService {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- return mImpl.setEnabledExclusive(packageName, true /* withinCategory */,
- realUserId);
+ try {
+ mImpl.setEnabledExclusive(packageName,
+ true /* withinCategory */, realUserId)
+ .ifPresent(mOnOverlaysChanged);
+ return true;
+ } catch (OperationFailedException e) {
+ return false;
+ }
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -681,7 +737,13 @@ public final class OverlayManagerService extends SystemService {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- return mImpl.setPriority(packageName, parentPackageName, realUserId);
+ try {
+ mImpl.setPriority(packageName, parentPackageName, realUserId)
+ .ifPresent(mOnOverlaysChanged);
+ return true;
+ } catch (OperationFailedException e) {
+ return false;
+ }
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -705,7 +767,13 @@ public final class OverlayManagerService extends SystemService {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- return mImpl.setHighestPriority(packageName, realUserId);
+ try {
+ mImpl.setHighestPriority(packageName, realUserId)
+ .ifPresent(mOnOverlaysChanged);
+ return true;
+ } catch (OperationFailedException e) {
+ return false;
+ }
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -729,7 +797,13 @@ public final class OverlayManagerService extends SystemService {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- return mImpl.setLowestPriority(packageName, realUserId);
+ try {
+ mImpl.setLowestPriority(packageName, realUserId)
+ .ifPresent(mOnOverlaysChanged);
+ return true;
+ } catch (OperationFailedException e) {
+ return false;
+ }
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -898,31 +972,27 @@ public final class OverlayManagerService extends SystemService {
}
};
- 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);
+ private 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().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.
- }
- });
- }
+ 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.
+ }
+ });
}
/**
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index 05a4a38feef1..e60411bb78c5 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -45,6 +45,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
/**
@@ -71,7 +72,6 @@ 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,14 +114,12 @@ final class OverlayManagerServiceImpl {
@NonNull final IdmapManager idmapManager,
@NonNull final OverlayManagerSettings settings,
@NonNull final OverlayConfig overlayConfig,
- @NonNull final String[] defaultOverlays,
- @NonNull final OverlayChangeListener listener) {
+ @NonNull final String[] defaultOverlays) {
mPackageManager = packageManager;
mIdmapManager = idmapManager;
mSettings = settings;
mOverlayConfig = overlayConfig;
mDefaultOverlays = defaultOverlays;
- mListener = listener;
}
/**
@@ -259,52 +257,58 @@ final class OverlayManagerServiceImpl {
mSettings.removeUser(userId);
}
- void onTargetPackageAdded(@NonNull final String packageName, final int userId) {
+ Optional<PackageAndUser> onTargetPackageAdded(@NonNull final String packageName,
+ final int userId) throws OperationFailedException {
if (DEBUG) {
Slog.d(TAG, "onTargetPackageAdded packageName=" + packageName + " userId=" + userId);
}
- updateAndRefreshOverlaysForTarget(packageName, userId, 0);
+ return updateAndRefreshOverlaysForTarget(packageName, userId, 0);
}
- void onTargetPackageChanged(@NonNull final String packageName, final int userId) {
+ Optional<PackageAndUser> onTargetPackageChanged(@NonNull final String packageName,
+ final int userId) throws OperationFailedException {
if (DEBUG) {
Slog.d(TAG, "onTargetPackageChanged packageName=" + packageName + " userId=" + userId);
}
- updateAndRefreshOverlaysForTarget(packageName, userId, 0);
+ return updateAndRefreshOverlaysForTarget(packageName, userId, 0);
}
- void onTargetPackageReplacing(@NonNull final String packageName, final int userId) {
+ Optional<PackageAndUser> onTargetPackageReplacing(@NonNull final String packageName,
+ final int userId) throws OperationFailedException {
if (DEBUG) {
Slog.d(TAG, "onTargetPackageReplacing packageName=" + packageName + " userId="
+ userId);
}
- updateAndRefreshOverlaysForTarget(packageName, userId, 0);
+ return updateAndRefreshOverlaysForTarget(packageName, userId, 0);
}
- void onTargetPackageReplaced(@NonNull final String packageName, final int userId) {
+ Optional<PackageAndUser> onTargetPackageReplaced(@NonNull final String packageName,
+ final int userId) throws OperationFailedException {
if (DEBUG) {
Slog.d(TAG, "onTargetPackageReplaced packageName=" + packageName + " userId=" + userId);
}
- updateAndRefreshOverlaysForTarget(packageName, userId, 0);
+ return updateAndRefreshOverlaysForTarget(packageName, userId, 0);
}
- void onTargetPackageRemoved(@NonNull final String packageName, final int userId) {
+ Optional<PackageAndUser> onTargetPackageRemoved(@NonNull final String packageName,
+ final int userId) throws OperationFailedException {
if (DEBUG) {
Slog.d(TAG, "onTargetPackageRemoved packageName=" + packageName + " userId=" + userId);
}
- updateAndRefreshOverlaysForTarget(packageName, userId, 0);
+ return updateAndRefreshOverlaysForTarget(packageName, userId, 0);
}
/**
* Update the state of any overlays for this target.
*/
- private void updateAndRefreshOverlaysForTarget(@NonNull final String targetPackageName,
- final int userId, final int flags) {
+ private Optional<PackageAndUser> updateAndRefreshOverlaysForTarget(
+ @NonNull final String targetPackageName, final int userId, final int flags)
+ throws OperationFailedException {
final List<OverlayInfo> targetOverlays = mSettings.getOverlaysForTarget(targetPackageName,
userId);
@@ -364,11 +368,13 @@ final class OverlayManagerServiceImpl {
}
if (modified) {
- mListener.onOverlaysChanged(targetPackageName, userId);
+ return Optional.of(new PackageAndUser(targetPackageName, userId));
}
+ return Optional.empty();
}
- void onOverlayPackageAdded(@NonNull final String packageName, final int userId) {
+ Optional<PackageAndUser> onOverlayPackageAdded(@NonNull final String packageName,
+ final int userId) throws OperationFailedException {
if (DEBUG) {
Slog.d(TAG, "onOverlayPackageAdded packageName=" + packageName + " userId=" + userId);
}
@@ -376,8 +382,7 @@ 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");
- onOverlayPackageRemoved(packageName, userId);
- return;
+ return onOverlayPackageRemoved(packageName, userId);
}
mSettings.init(packageName, userId, overlayPackage.overlayTarget,
@@ -389,15 +394,17 @@ final class OverlayManagerServiceImpl {
overlayPackage.overlayCategory);
try {
if (updateState(overlayPackage.overlayTarget, packageName, userId, 0)) {
- mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
+ return Optional.of(new PackageAndUser(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);
}
}
- void onOverlayPackageChanged(@NonNull final String packageName, final int userId) {
+ Optional<PackageAndUser> onOverlayPackageChanged(@NonNull final String packageName,
+ final int userId) throws OperationFailedException {
if (DEBUG) {
Slog.d(TAG, "onOverlayPackageChanged packageName=" + packageName + " userId=" + userId);
}
@@ -405,14 +412,16 @@ final class OverlayManagerServiceImpl {
try {
final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
if (updateState(oi.targetPackageName, packageName, userId, 0)) {
- mListener.onOverlaysChanged(oi.targetPackageName, userId);
+ return Optional.of(new PackageAndUser(oi.targetPackageName, userId));
}
+ return Optional.empty();
} catch (OverlayManagerSettings.BadKeyException e) {
- Slog.e(TAG, "failed to update settings", e);
+ throw new OperationFailedException("failed to update settings", e);
}
}
- void onOverlayPackageReplacing(@NonNull final String packageName, final int userId) {
+ Optional<PackageAndUser> onOverlayPackageReplacing(@NonNull final String packageName,
+ final int userId) throws OperationFailedException {
if (DEBUG) {
Slog.d(TAG, "onOverlayPackageReplacing packageName=" + packageName + " userId="
+ userId);
@@ -423,14 +432,16 @@ final class OverlayManagerServiceImpl {
if (updateState(oi.targetPackageName, packageName, userId,
FLAG_OVERLAY_IS_BEING_REPLACED)) {
removeIdmapIfPossible(oi);
- mListener.onOverlaysChanged(oi.targetPackageName, userId);
+ return Optional.of(new PackageAndUser(oi.targetPackageName, userId));
}
+ return Optional.empty();
} catch (OverlayManagerSettings.BadKeyException e) {
- Slog.e(TAG, "failed to update settings", e);
+ throw new OperationFailedException("failed to update settings", e);
}
}
- void onOverlayPackageReplaced(@NonNull final String packageName, final int userId) {
+ Optional<PackageAndUser> onOverlayPackageReplaced(@NonNull final String packageName,
+ final int userId) throws OperationFailedException {
if (DEBUG) {
Slog.d(TAG, "onOverlayPackageReplaced packageName=" + packageName + " userId="
+ userId);
@@ -439,16 +450,12 @@ 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");
- onOverlayPackageRemoved(packageName, userId);
- return;
+ return onOverlayPackageRemoved(packageName, userId);
}
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),
@@ -457,22 +464,25 @@ final class OverlayManagerServiceImpl {
}
if (updateState(pkg.overlayTarget, packageName, userId, 0)) {
- mListener.onOverlaysChanged(pkg.overlayTarget, userId);
+ return Optional.of(new PackageAndUser(pkg.overlayTarget, userId));
}
+ return Optional.empty();
} catch (OverlayManagerSettings.BadKeyException e) {
- Slog.e(TAG, "failed to update settings", e);
+ throw new OperationFailedException("failed to update settings", e);
}
}
- void onOverlayPackageRemoved(@NonNull final String packageName, final int userId) {
+ Optional<PackageAndUser> onOverlayPackageRemoved(@NonNull final String packageName,
+ final int userId) throws OperationFailedException {
try {
final OverlayInfo overlayInfo = mSettings.getOverlayInfo(packageName, userId);
if (mSettings.remove(packageName, userId)) {
removeIdmapIfPossible(overlayInfo);
- mListener.onOverlaysChanged(overlayInfo.targetPackageName, userId);
+ return Optional.of(new PackageAndUser(overlayInfo.targetPackageName, userId));
}
+ return Optional.empty();
} catch (OverlayManagerSettings.BadKeyException e) {
- Slog.e(TAG, "failed to remove overlay", e);
+ throw new OperationFailedException("failed to remove overlay", e);
}
}
@@ -493,8 +503,8 @@ final class OverlayManagerServiceImpl {
return mSettings.getOverlaysForUser(userId);
}
- boolean setEnabled(@NonNull final String packageName, final boolean enable,
- final int userId) {
+ Optional<PackageAndUser> setEnabled(@NonNull final String packageName, final boolean enable,
+ final int userId) throws OperationFailedException {
if (DEBUG) {
Slog.d(TAG, String.format("setEnabled packageName=%s enable=%s userId=%d",
packageName, enable, userId));
@@ -502,30 +512,33 @@ final class OverlayManagerServiceImpl {
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
if (overlayPackage == null) {
- return false;
+ throw new OperationFailedException(
+ String.format("failed to find overlay package %s for user %d",
+ packageName, userId));
}
try {
final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
if (!oi.isMutable) {
// Ignore immutable overlays.
- return false;
+ throw new OperationFailedException(
+ "cannot enable immutable overlay packages in runtime");
}
boolean modified = mSettings.setEnabled(packageName, userId, enable);
modified |= updateState(oi.targetPackageName, oi.packageName, userId, 0);
if (modified) {
- mListener.onOverlaysChanged(oi.targetPackageName, userId);
+ return Optional.of(new PackageAndUser(oi.targetPackageName, userId));
}
- return true;
+ return Optional.empty();
} catch (OverlayManagerSettings.BadKeyException e) {
- return false;
+ throw new OperationFailedException("failed to update settings", e);
}
}
- boolean setEnabledExclusive(@NonNull final String packageName, boolean withinCategory,
- final int userId) {
+ Optional<PackageAndUser> setEnabledExclusive(@NonNull final String packageName,
+ boolean withinCategory, final int userId) throws OperationFailedException {
if (DEBUG) {
Slog.d(TAG, String.format("setEnabledExclusive packageName=%s"
+ " withinCategory=%s userId=%d", packageName, withinCategory, userId));
@@ -533,7 +546,8 @@ final class OverlayManagerServiceImpl {
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
if (overlayPackage == null) {
- return false;
+ throw new OperationFailedException(String.format(
+ "failed to find overlay package %s for user %d", packageName, userId));
}
try {
@@ -576,11 +590,11 @@ final class OverlayManagerServiceImpl {
modified |= updateState(targetPackageName, packageName, userId, 0);
if (modified) {
- mListener.onOverlaysChanged(targetPackageName, userId);
+ return Optional.of(new PackageAndUser(targetPackageName, userId));
}
- return true;
+ return Optional.empty();
} catch (OverlayManagerSettings.BadKeyException e) {
- return false;
+ throw new OperationFailedException("failed to update settings", e);
}
}
@@ -596,66 +610,75 @@ final class OverlayManagerServiceImpl {
return mOverlayConfig.isEnabled(packageName);
}
- boolean setPriority(@NonNull final String packageName,
- @NonNull final String newParentPackageName, final int userId) {
+ Optional<PackageAndUser> setPriority(@NonNull final String packageName,
+ @NonNull final String newParentPackageName, final int userId)
+ throws OperationFailedException {
if (DEBUG) {
Slog.d(TAG, "setPriority packageName=" + packageName + " newParentPackageName="
+ newParentPackageName + " userId=" + userId);
}
if (!isPackageConfiguredMutable(packageName)) {
- return false;
+ throw new OperationFailedException(String.format(
+ "overlay package %s user %d is not updatable", packageName, userId));
}
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
if (overlayPackage == null) {
- return false;
+ throw new OperationFailedException(String.format(
+ "failed to find overlay package %s for user %d", packageName, userId));
}
if (mSettings.setPriority(packageName, newParentPackageName, userId)) {
- mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
+ return Optional.of(new PackageAndUser(overlayPackage.overlayTarget, userId));
}
- return true;
+ return Optional.empty();
}
- boolean setHighestPriority(@NonNull final String packageName, final int userId) {
+ Optional<PackageAndUser> setHighestPriority(@NonNull final String packageName,
+ final int userId) throws OperationFailedException {
if (DEBUG) {
Slog.d(TAG, "setHighestPriority packageName=" + packageName + " userId=" + userId);
}
if (!isPackageConfiguredMutable(packageName)) {
- return false;
+ throw new OperationFailedException(String.format(
+ "overlay package %s user %d is not updatable", packageName, userId));
}
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
if (overlayPackage == null) {
- return false;
+ throw new OperationFailedException(String.format(
+ "failed to find overlay package %s for user %d", packageName, userId));
}
if (mSettings.setHighestPriority(packageName, userId)) {
- mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
+ return Optional.of(new PackageAndUser(overlayPackage.overlayTarget, userId));
}
- return true;
+ return Optional.empty();
}
- boolean setLowestPriority(@NonNull final String packageName, final int userId) {
+ Optional<PackageAndUser> setLowestPriority(@NonNull final String packageName, final int userId)
+ throws OperationFailedException {
if (DEBUG) {
Slog.d(TAG, "setLowestPriority packageName=" + packageName + " userId=" + userId);
}
if (!isPackageConfiguredMutable(packageName)) {
- return false;
+ throw new OperationFailedException(String.format(
+ "overlay package %s user %d is not updatable", packageName, userId));
}
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
if (overlayPackage == null) {
- return false;
+ throw new OperationFailedException(String.format(
+ "failed to find overlay package %s for user %d", packageName, userId));
}
if (mSettings.setLowestPriority(packageName, userId)) {
- mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
+ return Optional.of(new PackageAndUser(overlayPackage.overlayTarget, userId));
}
- return true;
+ return Optional.empty();
}
void dump(@NonNull final PrintWriter pw, @NonNull DumpState dumpState) {
@@ -797,12 +820,13 @@ final class OverlayManagerServiceImpl {
mIdmapManager.removeIdmap(oi, oi.userId);
}
- interface OverlayChangeListener {
+ static final class OperationFailedException extends Exception {
+ OperationFailedException(@NonNull final String message) {
+ super(message);
+ }
- /**
- * 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);
+ OperationFailedException(@NonNull final String message, @NonNull Throwable cause) {
+ super(message, cause);
+ }
}
}
diff --git a/services/core/java/com/android/server/om/PackageAndUser.java b/services/core/java/com/android/server/om/PackageAndUser.java
new file mode 100644
index 000000000000..5c38ba7ce97b
--- /dev/null
+++ b/services/core/java/com/android/server/om/PackageAndUser.java
@@ -0,0 +1,57 @@
+/*
+ * 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 391611b72dab..5468fba59c10 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() {
+ public void testImmutableEnabledChange() throws Exception {
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() {
+ public void testMutableEnabledChangeHasNoEffect() throws Exception {
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() {
+ public void testMutableEnabledToImmutableEnabled() throws Exception {
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() {
+ public void testMutablePriorityChange() throws Exception {
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() {
+ public void testImmutablePriorityChange() throws Exception {
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 4f882ce13dd4..33dbcc0855be 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
@@ -22,11 +22,14 @@ 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;
@@ -35,6 +38,7 @@ 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 {
@@ -55,7 +59,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
private static final String CERT_CONFIG_NOK = "config_certificate_nok";
@Test
- public void testGetOverlayInfo() {
+ public void testGetOverlayInfo() throws Exception {
installNewPackage(overlay(OVERLAY, TARGET), USER);
final OverlayManagerServiceImpl impl = getImpl();
@@ -67,7 +71,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
}
@Test
- public void testGetOverlayInfosForTarget() {
+ public void testGetOverlayInfosForTarget() throws Exception {
installNewPackage(overlay(OVERLAY, TARGET), USER);
installNewPackage(overlay(OVERLAY2, TARGET), USER);
installNewPackage(overlay(OVERLAY3, TARGET), USER2);
@@ -92,7 +96,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
}
@Test
- public void testGetOverlayInfosForUser() {
+ public void testGetOverlayInfosForUser() throws Exception {
installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET), USER);
installNewPackage(overlay(OVERLAY2, TARGET), USER);
@@ -119,7 +123,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
}
@Test
- public void testPriority() {
+ public void testPriority() throws Exception {
installNewPackage(overlay(OVERLAY, TARGET), USER);
installNewPackage(overlay(OVERLAY2, TARGET), USER);
installNewPackage(overlay(OVERLAY3, TARGET), USER);
@@ -131,18 +135,21 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
assertOverlayInfoForTarget(TARGET, USER, o1, o2, o3);
- assertTrue(impl.setLowestPriority(OVERLAY3, USER));
+ assertEquals(impl.setLowestPriority(OVERLAY3, USER),
+ Optional.of(new PackageAndUser(TARGET, USER)));
assertOverlayInfoForTarget(TARGET, USER, o3, o1, o2);
- assertTrue(impl.setHighestPriority(OVERLAY3, USER));
+ assertEquals(impl.setHighestPriority(OVERLAY3, USER),
+ Optional.of(new PackageAndUser(TARGET, USER)));
assertOverlayInfoForTarget(TARGET, USER, o1, o2, o3);
- assertTrue(impl.setPriority(OVERLAY, OVERLAY2, USER));
+ assertEquals(impl.setPriority(OVERLAY, OVERLAY2, USER),
+ Optional.of(new PackageAndUser(TARGET, USER)));
assertOverlayInfoForTarget(TARGET, USER, o2, o1, o3);
}
@Test
- public void testOverlayInfoStateTransitions() {
+ public void testOverlayInfoStateTransitions() throws Exception {
final OverlayManagerServiceImpl impl = getImpl();
assertNull(impl.getOverlayInfo(OVERLAY, USER));
@@ -153,7 +160,8 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
installNewPackage(target, USER);
assertState(STATE_DISABLED, OVERLAY, USER);
- impl.setEnabled(OVERLAY, true, USER);
+ assertEquals(impl.setEnabled(OVERLAY, true, USER),
+ Optional.of(new PackageAndUser(TARGET, USER)));
assertState(STATE_ENABLED, OVERLAY, USER);
// target upgrades do not change the state of the overlay
@@ -168,50 +176,40 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
}
@Test
- public void testOnOverlayPackageUpgraded() {
- final FakeListener listener = getListener();
+ public void testOnOverlayPackageUpgraded() throws Exception {
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");
- upgradePackage(overlay2, USER);
- assertEquals(3, listener.count);
-
- listener.count = 0;
- upgradePackage(overlay2, USER);
- assertEquals(2, listener.count);
+ 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)));
}
@Test
- public void testListener() {
+ public void testSetEnabledAtVariousConditions() throws Exception {
final OverlayManagerServiceImpl impl = getImpl();
- final FakeListener listener = getListener();
- installNewPackage(overlay(OVERLAY, TARGET), USER);
- assertEquals(1, listener.count);
- listener.count = 0;
+ assertThrows(OverlayManagerServiceImpl.OperationFailedException.class,
+ () -> impl.setEnabled(OVERLAY, true, USER));
+ // request succeeded, and there was a change that needs to be
+ // propagated to the rest of the system
installNewPackage(target(TARGET), USER);
- assertEquals(1, listener.count);
- listener.count = 0;
-
- impl.setEnabled(OVERLAY, true, USER);
- assertEquals(1, listener.count);
- listener.count = 0;
+ installNewPackage(overlay(OVERLAY, TARGET), USER);
+ assertEquals(impl.setEnabled(OVERLAY, true, USER),
+ Optional.of(new PackageAndUser(TARGET, USER)));
- impl.setEnabled(OVERLAY, true, USER);
- assertEquals(0, listener.count);
+ // request succeeded, but nothing changed
+ assertFalse(impl.setEnabled(OVERLAY, true, USER).isPresent());
}
@Test
- public void testConfigSignaturePolicyOk() {
+ public void testConfigSignaturePolicyOk() throws Exception {
setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG);
reinitializeImpl();
@@ -229,7 +227,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
}
@Test
- public void testConfigSignaturePolicyCertNok() {
+ public void testConfigSignaturePolicyCertNok() throws Exception {
setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG);
reinitializeImpl();
@@ -247,7 +245,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
}
@Test
- public void testConfigSignaturePolicyNoConfig() {
+ public void testConfigSignaturePolicyNoConfig() throws Exception {
addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
@@ -262,7 +260,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
}
@Test
- public void testConfigSignaturePolicyNoRefPkg() {
+ public void testConfigSignaturePolicyNoRefPkg() throws Exception {
installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
@@ -276,7 +274,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
}
@Test
- public void testConfigSignaturePolicyRefPkgNotSystem() {
+ public void testConfigSignaturePolicyRefPkgNotSystem() throws Exception {
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 006dda0f80e3..2c477c897b30 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
@@ -16,6 +16,8 @@
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;
@@ -30,6 +32,7 @@ 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;
@@ -43,13 +46,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;
@@ -58,7 +61,6 @@ class OverlayManagerServiceImplTestsBase {
@Before
public void setUp() {
mState = new FakeDeviceState();
- mListener = new FakeListener();
mPackageManager = new FakePackageManagerHelper(mState);
mIdmapDaemon = new FakeIdmapDaemon(mState);
mOverlayConfig = mock(OverlayConfig.class);
@@ -73,18 +75,13 @@ class OverlayManagerServiceImplTestsBase {
new IdmapManager(mIdmapDaemon, mPackageManager),
new OverlayManagerSettings(),
mOverlayConfig,
- new String[0],
- mListener);
+ new String[0]);
}
OverlayManagerServiceImpl getImpl() {
return mImpl;
}
- FakeListener getListener() {
- return mListener;
- }
-
FakeIdmapDaemon getIdmapd() {
return mIdmapDaemon;
}
@@ -155,7 +152,8 @@ class OverlayManagerServiceImplTestsBase {
*
* @throws IllegalStateException if the package is currently installed
*/
- void installNewPackage(FakeDeviceState.PackageBuilder pkg, int userId) {
+ void installNewPackage(FakeDeviceState.PackageBuilder pkg, int userId)
+ throws OperationFailedException {
if (mState.select(pkg.packageName, userId) != null) {
throw new IllegalStateException("package " + pkg.packageName + " already installed");
}
@@ -176,23 +174,30 @@ 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
*/
- void upgradePackage(FakeDeviceState.PackageBuilder pkg, int userId) {
+ Pair<Optional<PackageAndUser>, Optional<PackageAndUser>> upgradePackage(
+ FakeDeviceState.PackageBuilder pkg, int userId) throws OperationFailedException {
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) {
- mImpl.onOverlayPackageReplacing(pkg.packageName, userId);
+ opt1 = mImpl.onOverlayPackageReplacing(pkg.packageName, userId);
}
mState.add(pkg, userId);
+ Optional<PackageAndUser> opt2;
if (pkg.targetPackage == null) {
- mImpl.onTargetPackageReplaced(pkg.packageName, userId);
+ opt2 = mImpl.onTargetPackageReplaced(pkg.packageName, userId);
} else {
- mImpl.onOverlayPackageReplaced(pkg.packageName, userId);
+ opt2 = mImpl.onOverlayPackageReplaced(pkg.packageName, userId);
}
+
+ return Pair.create(opt1, opt2);
}
/**
@@ -203,7 +208,7 @@ class OverlayManagerServiceImplTestsBase {
*
* @throws IllegalStateException if the package is not currently installed
*/
- void uninstallPackage(String packageName, int userId) {
+ void uninstallPackage(String packageName, int userId) throws OperationFailedException {
final FakeDeviceState.Package pkg = mState.select(packageName, userId);
if (pkg == null) {
throw new IllegalStateException("package " + packageName+ " not installed");
@@ -485,12 +490,4 @@ class OverlayManagerServiceImplTestsBase {
}
}
}
-
- static class FakeListener implements OverlayManagerServiceImpl.OverlayChangeListener {
- public int count;
-
- public void onOverlaysChanged(@NonNull String targetPackage, int userId) {
- count++;
- }
- }
}