Merge changes from topic "revert-1507500-oms-transactional-api-UQLIXJBEPB"

* changes:
  Revert "OverlayDeviceTests: add missing TEST_MAPPING"
  Revert "OMS: replace OMSImpl.OverlayChangeListener with return v..."
  Revert "OMS: block until settings are persisted"
This commit is contained in:
Ryan Mitchell
2021-01-13 15:07:48 +00:00
committed by Gerrit Code Review
7 changed files with 214 additions and 361 deletions

View File

@@ -1,7 +0,0 @@
{
"presubmit": [
{
"name" : "OverlayDeviceTests"
}
]
}

View File

@@ -29,8 +29,6 @@ import static android.os.Trace.TRACE_TAG_RRO;
import static android.os.Trace.traceBegin; import static android.os.Trace.traceBegin;
import static android.os.Trace.traceEnd; import static android.os.Trace.traceEnd;
import static com.android.server.om.OverlayManagerServiceImpl.OperationFailedException;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.app.ActivityManager; import android.app.ActivityManager;
@@ -50,7 +48,6 @@ import android.content.res.ApkAssets;
import android.net.Uri; import android.net.Uri;
import android.os.Binder; import android.os.Binder;
import android.os.Environment; import android.os.Environment;
import android.os.HandlerThread;
import android.os.IBinder; import android.os.IBinder;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ResultReceiver; import android.os.ResultReceiver;
@@ -67,6 +64,7 @@ import android.util.SparseArray;
import com.android.internal.content.om.OverlayConfig; import com.android.internal.content.om.OverlayConfig;
import com.android.server.FgThread; import com.android.server.FgThread;
import com.android.server.IoThread;
import com.android.server.LocalServices; import com.android.server.LocalServices;
import com.android.server.SystemConfig; import com.android.server.SystemConfig;
import com.android.server.SystemService; import com.android.server.SystemService;
@@ -89,7 +87,7 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer; import java.util.concurrent.atomic.AtomicBoolean;
/** /**
* Service to manage asset overlays. * Service to manage asset overlays.
@@ -238,9 +236,7 @@ public final class OverlayManagerService extends SystemService {
private final OverlayActorEnforcer mActorEnforcer; private final OverlayActorEnforcer mActorEnforcer;
private final Consumer<PackageAndUser> mOnOverlaysChanged = (pair) -> { private final AtomicBoolean mPersistSettingsScheduled = new AtomicBoolean(false);
onOverlaysChanged(pair.packageName, pair.userId);
};
public OverlayManagerService(@NonNull final Context context) { public OverlayManagerService(@NonNull final Context context) {
super(context); super(context);
@@ -253,19 +249,17 @@ public final class OverlayManagerService extends SystemService {
IdmapManager im = new IdmapManager(IdmapDaemon.getInstance(), mPackageManager); IdmapManager im = new IdmapManager(IdmapDaemon.getInstance(), mPackageManager);
mSettings = new OverlayManagerSettings(); mSettings = new OverlayManagerSettings();
mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings, mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings,
OverlayConfig.getSystemInstance(), getDefaultOverlayPackages()); OverlayConfig.getSystemInstance(), getDefaultOverlayPackages(),
new OverlayChangeListener());
mActorEnforcer = new OverlayActorEnforcer(mPackageManager); mActorEnforcer = new OverlayActorEnforcer(mPackageManager);
HandlerThread packageReceiverThread = new HandlerThread(TAG);
packageReceiverThread.start();
final IntentFilter packageFilter = new IntentFilter(); final IntentFilter packageFilter = new IntentFilter();
packageFilter.addAction(ACTION_PACKAGE_ADDED); packageFilter.addAction(ACTION_PACKAGE_ADDED);
packageFilter.addAction(ACTION_PACKAGE_CHANGED); packageFilter.addAction(ACTION_PACKAGE_CHANGED);
packageFilter.addAction(ACTION_PACKAGE_REMOVED); packageFilter.addAction(ACTION_PACKAGE_REMOVED);
packageFilter.addDataScheme("package"); packageFilter.addDataScheme("package");
getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL, getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL,
packageFilter, null, packageReceiverThread.getThreadHandler()); packageFilter, null, null);
final IntentFilter userFilter = new IntentFilter(); final IntentFilter userFilter = new IntentFilter();
userFilter.addAction(ACTION_USER_ADDED); userFilter.addAction(ACTION_USER_ADDED);
@@ -318,7 +312,7 @@ public final class OverlayManagerService extends SystemService {
final List<String> targets = mImpl.updateOverlaysForUser(newUserId); final List<String> targets = mImpl.updateOverlaysForUser(newUserId);
updateAssets(newUserId, targets); updateAssets(newUserId, targets);
} }
persistSettings(); schedulePersistSettings();
} finally { } finally {
traceEnd(TRACE_TAG_RRO); traceEnd(TRACE_TAG_RRO);
} }
@@ -402,17 +396,10 @@ public final class OverlayManagerService extends SystemService {
false); false);
if (pi != null && !pi.applicationInfo.isInstantApp()) { if (pi != null && !pi.applicationInfo.isInstantApp()) {
mPackageManager.cachePackageInfo(packageName, userId, pi); mPackageManager.cachePackageInfo(packageName, userId, pi);
if (pi.isOverlayPackage()) {
try { mImpl.onOverlayPackageAdded(packageName, userId);
if (pi.isOverlayPackage()) { } else {
mImpl.onOverlayPackageAdded(packageName, userId) mImpl.onTargetPackageAdded(packageName, userId);
.ifPresent(mOnOverlaysChanged);
} else {
mImpl.onTargetPackageAdded(packageName, userId)
.ifPresent(mOnOverlaysChanged);
}
} catch (OperationFailedException e) {
Slog.e(TAG, "onPackageAdded internal error", e);
} }
} }
} }
@@ -432,17 +419,10 @@ public final class OverlayManagerService extends SystemService {
false); false);
if (pi != null && pi.applicationInfo.isInstantApp()) { if (pi != null && pi.applicationInfo.isInstantApp()) {
mPackageManager.cachePackageInfo(packageName, userId, pi); mPackageManager.cachePackageInfo(packageName, userId, pi);
if (pi.isOverlayPackage()) {
try { mImpl.onOverlayPackageChanged(packageName, userId);
if (pi.isOverlayPackage()) { } else {
mImpl.onOverlayPackageChanged(packageName, userId) mImpl.onTargetPackageChanged(packageName, userId);
.ifPresent(mOnOverlaysChanged);
} else {
mImpl.onTargetPackageChanged(packageName, userId)
.ifPresent(mOnOverlaysChanged);
}
} catch (OperationFailedException e) {
Slog.e(TAG, "onPackageChanged internal error", e);
} }
} }
} }
@@ -461,12 +441,7 @@ public final class OverlayManagerService extends SystemService {
mPackageManager.forgetPackageInfo(packageName, userId); mPackageManager.forgetPackageInfo(packageName, userId);
final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId); final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
if (oi != null) { if (oi != null) {
try { mImpl.onOverlayPackageReplacing(packageName, userId);
mImpl.onOverlayPackageReplacing(packageName, userId)
.ifPresent(mOnOverlaysChanged);
} catch (OperationFailedException e) {
Slog.e(TAG, "onPackageReplacing internal error", e);
}
} }
} }
} }
@@ -485,16 +460,10 @@ public final class OverlayManagerService extends SystemService {
false); false);
if (pi != null && !pi.applicationInfo.isInstantApp()) { if (pi != null && !pi.applicationInfo.isInstantApp()) {
mPackageManager.cachePackageInfo(packageName, userId, pi); mPackageManager.cachePackageInfo(packageName, userId, pi);
try { if (pi.isOverlayPackage()) {
if (pi.isOverlayPackage()) { mImpl.onOverlayPackageReplaced(packageName, userId);
mImpl.onOverlayPackageReplaced(packageName, userId) } else {
.ifPresent(mOnOverlaysChanged); mImpl.onTargetPackageReplaced(packageName, userId);
} else {
mImpl.onTargetPackageReplaced(packageName, userId)
.ifPresent(mOnOverlaysChanged);
}
} catch (OperationFailedException e) {
Slog.e(TAG, "onPackageReplaced internal error", e);
} }
} }
} }
@@ -512,17 +481,10 @@ public final class OverlayManagerService extends SystemService {
synchronized (mLock) { synchronized (mLock) {
mPackageManager.forgetPackageInfo(packageName, userId); mPackageManager.forgetPackageInfo(packageName, userId);
final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId); final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
if (oi != null) {
try { mImpl.onOverlayPackageRemoved(packageName, userId);
if (oi != null) { } else {
mImpl.onOverlayPackageRemoved(packageName, userId) mImpl.onTargetPackageRemoved(packageName, userId);
.ifPresent(mOnOverlaysChanged);
} else {
mImpl.onTargetPackageRemoved(packageName, userId)
.ifPresent(mOnOverlaysChanged);
}
} catch (OperationFailedException e) {
Slog.e(TAG, "onPackageRemoved internal error", e);
} }
} }
} }
@@ -640,13 +602,7 @@ public final class OverlayManagerService extends SystemService {
final long ident = Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity();
try { try {
synchronized (mLock) { synchronized (mLock) {
try { return mImpl.setEnabled(packageName, enable, realUserId);
mImpl.setEnabled(packageName, enable, realUserId)
.ifPresent(mOnOverlaysChanged);
return true;
} catch (OperationFailedException e) {
return false;
}
} }
} finally { } finally {
Binder.restoreCallingIdentity(ident); Binder.restoreCallingIdentity(ident);
@@ -671,14 +627,8 @@ public final class OverlayManagerService extends SystemService {
final long ident = Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity();
try { try {
synchronized (mLock) { synchronized (mLock) {
try { return mImpl.setEnabledExclusive(packageName, false /* withinCategory */,
mImpl.setEnabledExclusive(packageName, realUserId);
false /* withinCategory */, realUserId)
.ifPresent(mOnOverlaysChanged);
return true;
} catch (OperationFailedException e) {
return false;
}
} }
} finally { } finally {
Binder.restoreCallingIdentity(ident); Binder.restoreCallingIdentity(ident);
@@ -704,14 +654,8 @@ public final class OverlayManagerService extends SystemService {
final long ident = Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity();
try { try {
synchronized (mLock) { synchronized (mLock) {
try { return mImpl.setEnabledExclusive(packageName, true /* withinCategory */,
mImpl.setEnabledExclusive(packageName, realUserId);
true /* withinCategory */, realUserId)
.ifPresent(mOnOverlaysChanged);
return true;
} catch (OperationFailedException e) {
return false;
}
} }
} finally { } finally {
Binder.restoreCallingIdentity(ident); Binder.restoreCallingIdentity(ident);
@@ -737,13 +681,7 @@ public final class OverlayManagerService extends SystemService {
final long ident = Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity();
try { try {
synchronized (mLock) { synchronized (mLock) {
try { return mImpl.setPriority(packageName, parentPackageName, realUserId);
mImpl.setPriority(packageName, parentPackageName, realUserId)
.ifPresent(mOnOverlaysChanged);
return true;
} catch (OperationFailedException e) {
return false;
}
} }
} finally { } finally {
Binder.restoreCallingIdentity(ident); Binder.restoreCallingIdentity(ident);
@@ -767,13 +705,7 @@ public final class OverlayManagerService extends SystemService {
final long ident = Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity();
try { try {
synchronized (mLock) { synchronized (mLock) {
try { return mImpl.setHighestPriority(packageName, realUserId);
mImpl.setHighestPriority(packageName, realUserId)
.ifPresent(mOnOverlaysChanged);
return true;
} catch (OperationFailedException e) {
return false;
}
} }
} finally { } finally {
Binder.restoreCallingIdentity(ident); Binder.restoreCallingIdentity(ident);
@@ -797,13 +729,7 @@ public final class OverlayManagerService extends SystemService {
final long ident = Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity();
try { try {
synchronized (mLock) { synchronized (mLock) {
try { return mImpl.setLowestPriority(packageName, realUserId);
mImpl.setLowestPriority(packageName, realUserId)
.ifPresent(mOnOverlaysChanged);
return true;
} catch (OperationFailedException e) {
return false;
}
} }
} finally { } finally {
Binder.restoreCallingIdentity(ident); Binder.restoreCallingIdentity(ident);
@@ -972,27 +898,31 @@ public final class OverlayManagerService extends SystemService {
} }
}; };
private void onOverlaysChanged(@NonNull final String targetPackageName, final int userId) { private final class OverlayChangeListener
persistSettings(); implements OverlayManagerServiceImpl.OverlayChangeListener {
FgThread.getHandler().post(() -> { @Override
updateAssets(userId, targetPackageName); 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, final Intent intent = new Intent(ACTION_OVERLAY_CHANGED,
Uri.fromParts("package", targetPackageName, null)); Uri.fromParts("package", targetPackageName, null));
intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, "send broadcast " + intent); Slog.d(TAG, "send broadcast " + intent);
} }
try { try {
ActivityManager.getService().broadcastIntent(null, intent, null, null, 0, ActivityManager.getService().broadcastIntentWithFeature(null, null, intent,
null, null, null, android.app.AppOpsManager.OP_NONE, null, false, false, null, null, 0, null, null, null, android.app.AppOpsManager.OP_NONE,
userId); null, false, false, userId);
} catch (RemoteException e) { } catch (RemoteException e) {
// Intentionally left empty. // Intentionally left empty.
} }
}); });
}
} }
/** /**
@@ -1065,21 +995,27 @@ public final class OverlayManagerService extends SystemService {
} }
} }
private void persistSettings() { private void schedulePersistSettings() {
if (DEBUG) { if (mPersistSettingsScheduled.getAndSet(true)) {
Slog.d(TAG, "Writing overlay settings"); return;
} }
synchronized (mLock) { IoThread.getHandler().post(() -> {
FileOutputStream stream = null; mPersistSettingsScheduled.set(false);
try { if (DEBUG) {
stream = mSettingsFile.startWrite(); Slog.d(TAG, "Writing overlay settings");
mSettings.persist(stream);
mSettingsFile.finishWrite(stream);
} catch (IOException | XmlPullParserException e) {
mSettingsFile.failWrite(stream);
Slog.e(TAG, "failed to persist overlay state", e);
} }
} 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() { private void restoreSettings() {

View File

@@ -45,7 +45,6 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import java.util.Set; import java.util.Set;
/** /**
@@ -72,6 +71,7 @@ final class OverlayManagerServiceImpl {
private final OverlayManagerSettings mSettings; private final OverlayManagerSettings mSettings;
private final OverlayConfig mOverlayConfig; private final OverlayConfig mOverlayConfig;
private final String[] mDefaultOverlays; private final String[] mDefaultOverlays;
private final OverlayChangeListener mListener;
/** /**
* Helper method to merge the overlay manager's (as read from overlays.xml) * 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 IdmapManager idmapManager,
@NonNull final OverlayManagerSettings settings, @NonNull final OverlayManagerSettings settings,
@NonNull final OverlayConfig overlayConfig, @NonNull final OverlayConfig overlayConfig,
@NonNull final String[] defaultOverlays) { @NonNull final String[] defaultOverlays,
@NonNull final OverlayChangeListener listener) {
mPackageManager = packageManager; mPackageManager = packageManager;
mIdmapManager = idmapManager; mIdmapManager = idmapManager;
mSettings = settings; mSettings = settings;
mOverlayConfig = overlayConfig; mOverlayConfig = overlayConfig;
mDefaultOverlays = defaultOverlays; mDefaultOverlays = defaultOverlays;
mListener = listener;
} }
/** /**
@@ -257,58 +259,52 @@ final class OverlayManagerServiceImpl {
mSettings.removeUser(userId); mSettings.removeUser(userId);
} }
Optional<PackageAndUser> onTargetPackageAdded(@NonNull final String packageName, void onTargetPackageAdded(@NonNull final String packageName, final int userId) {
final int userId) throws OperationFailedException {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, "onTargetPackageAdded packageName=" + packageName + " userId=" + userId); Slog.d(TAG, "onTargetPackageAdded packageName=" + packageName + " userId=" + userId);
} }
return updateAndRefreshOverlaysForTarget(packageName, userId, 0); updateAndRefreshOverlaysForTarget(packageName, userId, 0);
} }
Optional<PackageAndUser> onTargetPackageChanged(@NonNull final String packageName, void onTargetPackageChanged(@NonNull final String packageName, final int userId) {
final int userId) throws OperationFailedException {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, "onTargetPackageChanged packageName=" + packageName + " userId=" + userId); Slog.d(TAG, "onTargetPackageChanged packageName=" + packageName + " userId=" + userId);
} }
return updateAndRefreshOverlaysForTarget(packageName, userId, 0); updateAndRefreshOverlaysForTarget(packageName, userId, 0);
} }
Optional<PackageAndUser> onTargetPackageReplacing(@NonNull final String packageName, void onTargetPackageReplacing(@NonNull final String packageName, final int userId) {
final int userId) throws OperationFailedException {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, "onTargetPackageReplacing packageName=" + packageName + " userId=" Slog.d(TAG, "onTargetPackageReplacing packageName=" + packageName + " userId="
+ userId); + userId);
} }
return updateAndRefreshOverlaysForTarget(packageName, userId, 0); updateAndRefreshOverlaysForTarget(packageName, userId, 0);
} }
Optional<PackageAndUser> onTargetPackageReplaced(@NonNull final String packageName, void onTargetPackageReplaced(@NonNull final String packageName, final int userId) {
final int userId) throws OperationFailedException {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, "onTargetPackageReplaced packageName=" + packageName + " userId=" + userId); Slog.d(TAG, "onTargetPackageReplaced packageName=" + packageName + " userId=" + userId);
} }
return updateAndRefreshOverlaysForTarget(packageName, userId, 0); updateAndRefreshOverlaysForTarget(packageName, userId, 0);
} }
Optional<PackageAndUser> onTargetPackageRemoved(@NonNull final String packageName, void onTargetPackageRemoved(@NonNull final String packageName, final int userId) {
final int userId) throws OperationFailedException {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, "onTargetPackageRemoved packageName=" + packageName + " userId=" + userId); 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. * Update the state of any overlays for this target.
*/ */
private Optional<PackageAndUser> updateAndRefreshOverlaysForTarget( private void updateAndRefreshOverlaysForTarget(@NonNull final String targetPackageName,
@NonNull final String targetPackageName, final int userId, final int flags) final int userId, final int flags) {
throws OperationFailedException {
final List<OverlayInfo> targetOverlays = mSettings.getOverlaysForTarget(targetPackageName, final List<OverlayInfo> targetOverlays = mSettings.getOverlaysForTarget(targetPackageName,
userId); userId);
@@ -368,13 +364,11 @@ final class OverlayManagerServiceImpl {
} }
if (modified) { if (modified) {
return Optional.of(new PackageAndUser(targetPackageName, userId)); mListener.onOverlaysChanged(targetPackageName, userId);
} }
return Optional.empty();
} }
Optional<PackageAndUser> onOverlayPackageAdded(@NonNull final String packageName, void onOverlayPackageAdded(@NonNull final String packageName, final int userId) {
final int userId) throws OperationFailedException {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, "onOverlayPackageAdded packageName=" + packageName + " userId=" + userId); Slog.d(TAG, "onOverlayPackageAdded packageName=" + packageName + " userId=" + userId);
} }
@@ -382,7 +376,8 @@ final class OverlayManagerServiceImpl {
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId); final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
if (overlayPackage == null) { if (overlayPackage == null) {
Slog.w(TAG, "overlay package " + packageName + " was added, but couldn't be found"); 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, mSettings.init(packageName, userId, overlayPackage.overlayTarget,
@@ -394,17 +389,15 @@ final class OverlayManagerServiceImpl {
overlayPackage.overlayCategory); overlayPackage.overlayCategory);
try { try {
if (updateState(overlayPackage.overlayTarget, packageName, userId, 0)) { 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) { } catch (OverlayManagerSettings.BadKeyException e) {
Slog.e(TAG, "failed to update settings", e);
mSettings.remove(packageName, userId); mSettings.remove(packageName, userId);
throw new OperationFailedException("failed to update settings", e);
} }
} }
Optional<PackageAndUser> onOverlayPackageChanged(@NonNull final String packageName, void onOverlayPackageChanged(@NonNull final String packageName, final int userId) {
final int userId) throws OperationFailedException {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, "onOverlayPackageChanged packageName=" + packageName + " userId=" + userId); Slog.d(TAG, "onOverlayPackageChanged packageName=" + packageName + " userId=" + userId);
} }
@@ -412,16 +405,14 @@ final class OverlayManagerServiceImpl {
try { try {
final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId); final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
if (updateState(oi.targetPackageName, packageName, userId, 0)) { 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) { } 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, void onOverlayPackageReplacing(@NonNull final String packageName, final int userId) {
final int userId) throws OperationFailedException {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, "onOverlayPackageReplacing packageName=" + packageName + " userId=" Slog.d(TAG, "onOverlayPackageReplacing packageName=" + packageName + " userId="
+ userId); + userId);
@@ -432,16 +423,14 @@ final class OverlayManagerServiceImpl {
if (updateState(oi.targetPackageName, packageName, userId, if (updateState(oi.targetPackageName, packageName, userId,
FLAG_OVERLAY_IS_BEING_REPLACED)) { FLAG_OVERLAY_IS_BEING_REPLACED)) {
removeIdmapIfPossible(oi); removeIdmapIfPossible(oi);
return Optional.of(new PackageAndUser(oi.targetPackageName, userId)); mListener.onOverlaysChanged(oi.targetPackageName, userId);
} }
return Optional.empty();
} catch (OverlayManagerSettings.BadKeyException e) { } 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, void onOverlayPackageReplaced(@NonNull final String packageName, final int userId) {
final int userId) throws OperationFailedException {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, "onOverlayPackageReplaced packageName=" + packageName + " userId=" Slog.d(TAG, "onOverlayPackageReplaced packageName=" + packageName + " userId="
+ userId); + userId);
@@ -450,12 +439,16 @@ final class OverlayManagerServiceImpl {
final PackageInfo pkg = mPackageManager.getPackageInfo(packageName, userId); final PackageInfo pkg = mPackageManager.getPackageInfo(packageName, userId);
if (pkg == null) { if (pkg == null) {
Slog.w(TAG, "overlay package " + packageName + " was replaced, but couldn't be found"); Slog.w(TAG, "overlay package " + packageName + " was replaced, but couldn't be found");
return onOverlayPackageRemoved(packageName, userId); onOverlayPackageRemoved(packageName, userId);
return;
} }
try { try {
final OverlayInfo oldOi = mSettings.getOverlayInfo(packageName, userId); final OverlayInfo oldOi = mSettings.getOverlayInfo(packageName, userId);
if (mustReinitializeOverlay(pkg, oldOi)) { 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, mSettings.init(packageName, userId, pkg.overlayTarget, pkg.targetOverlayableName,
pkg.applicationInfo.getBaseCodePath(), pkg.applicationInfo.getBaseCodePath(),
isPackageConfiguredMutable(pkg.packageName), isPackageConfiguredMutable(pkg.packageName),
@@ -464,25 +457,22 @@ final class OverlayManagerServiceImpl {
} }
if (updateState(pkg.overlayTarget, packageName, userId, 0)) { 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) { } 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, void onOverlayPackageRemoved(@NonNull final String packageName, final int userId) {
final int userId) throws OperationFailedException {
try { try {
final OverlayInfo overlayInfo = mSettings.getOverlayInfo(packageName, userId); final OverlayInfo overlayInfo = mSettings.getOverlayInfo(packageName, userId);
if (mSettings.remove(packageName, userId)) { if (mSettings.remove(packageName, userId)) {
removeIdmapIfPossible(overlayInfo); removeIdmapIfPossible(overlayInfo);
return Optional.of(new PackageAndUser(overlayInfo.targetPackageName, userId)); mListener.onOverlaysChanged(overlayInfo.targetPackageName, userId);
} }
return Optional.empty();
} catch (OverlayManagerSettings.BadKeyException e) { } 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); return mSettings.getOverlaysForUser(userId);
} }
Optional<PackageAndUser> setEnabled(@NonNull final String packageName, final boolean enable, boolean setEnabled(@NonNull final String packageName, final boolean enable,
final int userId) throws OperationFailedException { final int userId) {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, String.format("setEnabled packageName=%s enable=%s userId=%d", Slog.d(TAG, String.format("setEnabled packageName=%s enable=%s userId=%d",
packageName, enable, userId)); packageName, enable, userId));
@@ -512,33 +502,30 @@ final class OverlayManagerServiceImpl {
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId); final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
if (overlayPackage == null) { if (overlayPackage == null) {
throw new OperationFailedException( return false;
String.format("failed to find overlay package %s for user %d",
packageName, userId));
} }
try { try {
final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId); final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
if (!oi.isMutable) { if (!oi.isMutable) {
// Ignore immutable overlays. // Ignore immutable overlays.
throw new OperationFailedException( return false;
"cannot enable immutable overlay packages in runtime");
} }
boolean modified = mSettings.setEnabled(packageName, userId, enable); boolean modified = mSettings.setEnabled(packageName, userId, enable);
modified |= updateState(oi.targetPackageName, oi.packageName, userId, 0); modified |= updateState(oi.targetPackageName, oi.packageName, userId, 0);
if (modified) { if (modified) {
return Optional.of(new PackageAndUser(oi.targetPackageName, userId)); mListener.onOverlaysChanged(oi.targetPackageName, userId);
} }
return Optional.empty(); return true;
} catch (OverlayManagerSettings.BadKeyException e) { } catch (OverlayManagerSettings.BadKeyException e) {
throw new OperationFailedException("failed to update settings", e); return false;
} }
} }
Optional<PackageAndUser> setEnabledExclusive(@NonNull final String packageName, boolean setEnabledExclusive(@NonNull final String packageName, boolean withinCategory,
boolean withinCategory, final int userId) throws OperationFailedException { final int userId) {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, String.format("setEnabledExclusive packageName=%s" Slog.d(TAG, String.format("setEnabledExclusive packageName=%s"
+ " withinCategory=%s userId=%d", packageName, withinCategory, userId)); + " withinCategory=%s userId=%d", packageName, withinCategory, userId));
@@ -546,8 +533,7 @@ final class OverlayManagerServiceImpl {
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId); final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
if (overlayPackage == null) { if (overlayPackage == null) {
throw new OperationFailedException(String.format( return false;
"failed to find overlay package %s for user %d", packageName, userId));
} }
try { try {
@@ -590,11 +576,11 @@ final class OverlayManagerServiceImpl {
modified |= updateState(targetPackageName, packageName, userId, 0); modified |= updateState(targetPackageName, packageName, userId, 0);
if (modified) { if (modified) {
return Optional.of(new PackageAndUser(targetPackageName, userId)); mListener.onOverlaysChanged(targetPackageName, userId);
} }
return Optional.empty(); return true;
} catch (OverlayManagerSettings.BadKeyException e) { } 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); return mOverlayConfig.isEnabled(packageName);
} }
Optional<PackageAndUser> setPriority(@NonNull final String packageName, boolean setPriority(@NonNull final String packageName,
@NonNull final String newParentPackageName, final int userId) @NonNull final String newParentPackageName, final int userId) {
throws OperationFailedException {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, "setPriority packageName=" + packageName + " newParentPackageName=" Slog.d(TAG, "setPriority packageName=" + packageName + " newParentPackageName="
+ newParentPackageName + " userId=" + userId); + newParentPackageName + " userId=" + userId);
} }
if (!isPackageConfiguredMutable(packageName)) { if (!isPackageConfiguredMutable(packageName)) {
throw new OperationFailedException(String.format( return false;
"overlay package %s user %d is not updatable", packageName, userId));
} }
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId); final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
if (overlayPackage == null) { if (overlayPackage == null) {
throw new OperationFailedException(String.format( return false;
"failed to find overlay package %s for user %d", packageName, userId));
} }
if (mSettings.setPriority(packageName, newParentPackageName, userId)) { 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, boolean setHighestPriority(@NonNull final String packageName, final int userId) {
final int userId) throws OperationFailedException {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, "setHighestPriority packageName=" + packageName + " userId=" + userId); Slog.d(TAG, "setHighestPriority packageName=" + packageName + " userId=" + userId);
} }
if (!isPackageConfiguredMutable(packageName)) { if (!isPackageConfiguredMutable(packageName)) {
throw new OperationFailedException(String.format( return false;
"overlay package %s user %d is not updatable", packageName, userId));
} }
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId); final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
if (overlayPackage == null) { if (overlayPackage == null) {
throw new OperationFailedException(String.format( return false;
"failed to find overlay package %s for user %d", packageName, userId));
} }
if (mSettings.setHighestPriority(packageName, userId)) { 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) boolean setLowestPriority(@NonNull final String packageName, final int userId) {
throws OperationFailedException {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, "setLowestPriority packageName=" + packageName + " userId=" + userId); Slog.d(TAG, "setLowestPriority packageName=" + packageName + " userId=" + userId);
} }
if (!isPackageConfiguredMutable(packageName)) { if (!isPackageConfiguredMutable(packageName)) {
throw new OperationFailedException(String.format( return false;
"overlay package %s user %d is not updatable", packageName, userId));
} }
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId); final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
if (overlayPackage == null) { if (overlayPackage == null) {
throw new OperationFailedException(String.format( return false;
"failed to find overlay package %s for user %d", packageName, userId));
} }
if (mSettings.setLowestPriority(packageName, userId)) { 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) { void dump(@NonNull final PrintWriter pw, @NonNull DumpState dumpState) {
@@ -820,13 +797,12 @@ final class OverlayManagerServiceImpl {
mIdmapManager.removeIdmap(oi, oi.userId); mIdmapManager.removeIdmap(oi, oi.userId);
} }
static final class OperationFailedException extends Exception { interface OverlayChangeListener {
OperationFailedException(@NonNull final String message) {
super(message);
}
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);
} }
} }

View File

@@ -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);
}
}

View File

@@ -78,7 +78,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
} }
@Test @Test
public void testImmutableEnabledChange() throws Exception { public void testImmutableEnabledChange() {
final OverlayManagerServiceImpl impl = getImpl(); final OverlayManagerServiceImpl impl = getImpl();
installNewPackage(target(TARGET), USER); installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER);
@@ -106,7 +106,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
} }
@Test @Test
public void testMutableEnabledChangeHasNoEffect() throws Exception { public void testMutableEnabledChangeHasNoEffect() {
final OverlayManagerServiceImpl impl = getImpl(); final OverlayManagerServiceImpl impl = getImpl();
installNewPackage(target(TARGET), USER); installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER);
@@ -134,7 +134,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
} }
@Test @Test
public void testMutableEnabledToImmutableEnabled() throws Exception { public void testMutableEnabledToImmutableEnabled() {
final OverlayManagerServiceImpl impl = getImpl(); final OverlayManagerServiceImpl impl = getImpl();
installNewPackage(target(TARGET), USER); installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER);
@@ -178,7 +178,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
} }
@Test @Test
public void testMutablePriorityChange() throws Exception { public void testMutablePriorityChange() {
final OverlayManagerServiceImpl impl = getImpl(); final OverlayManagerServiceImpl impl = getImpl();
installNewPackage(target(TARGET), USER); installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER);
@@ -218,7 +218,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
} }
@Test @Test
public void testImmutablePriorityChange() throws Exception { public void testImmutablePriorityChange() {
final OverlayManagerServiceImpl impl = getImpl(); final OverlayManagerServiceImpl impl = getImpl();
installNewPackage(target(TARGET), USER); installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER);

View File

@@ -22,14 +22,11 @@ import static android.content.om.OverlayInfo.STATE_MISSING_TARGET;
import static android.os.OverlayablePolicy.CONFIG_SIGNATURE; import static android.os.OverlayablePolicy.CONFIG_SIGNATURE;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.testng.Assert.assertThrows;
import android.content.om.OverlayInfo; import android.content.om.OverlayInfo;
import android.util.Pair;
import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4;
@@ -38,7 +35,6 @@ import org.junit.runner.RunWith;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTestsBase { public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTestsBase {
@@ -59,7 +55,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
private static final String CERT_CONFIG_NOK = "config_certificate_nok"; private static final String CERT_CONFIG_NOK = "config_certificate_nok";
@Test @Test
public void testGetOverlayInfo() throws Exception { public void testGetOverlayInfo() {
installNewPackage(overlay(OVERLAY, TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER);
final OverlayManagerServiceImpl impl = getImpl(); final OverlayManagerServiceImpl impl = getImpl();
@@ -71,7 +67,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
} }
@Test @Test
public void testGetOverlayInfosForTarget() throws Exception { public void testGetOverlayInfosForTarget() {
installNewPackage(overlay(OVERLAY, TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER);
installNewPackage(overlay(OVERLAY2, TARGET), USER); installNewPackage(overlay(OVERLAY2, TARGET), USER);
installNewPackage(overlay(OVERLAY3, TARGET), USER2); installNewPackage(overlay(OVERLAY3, TARGET), USER2);
@@ -96,7 +92,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
} }
@Test @Test
public void testGetOverlayInfosForUser() throws Exception { public void testGetOverlayInfosForUser() {
installNewPackage(target(TARGET), USER); installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER);
installNewPackage(overlay(OVERLAY2, TARGET), USER); installNewPackage(overlay(OVERLAY2, TARGET), USER);
@@ -123,7 +119,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
} }
@Test @Test
public void testPriority() throws Exception { public void testPriority() {
installNewPackage(overlay(OVERLAY, TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER);
installNewPackage(overlay(OVERLAY2, TARGET), USER); installNewPackage(overlay(OVERLAY2, TARGET), USER);
installNewPackage(overlay(OVERLAY3, TARGET), USER); installNewPackage(overlay(OVERLAY3, TARGET), USER);
@@ -135,21 +131,18 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
assertOverlayInfoForTarget(TARGET, USER, o1, o2, o3); assertOverlayInfoForTarget(TARGET, USER, o1, o2, o3);
assertEquals(impl.setLowestPriority(OVERLAY3, USER), assertTrue(impl.setLowestPriority(OVERLAY3, USER));
Optional.of(new PackageAndUser(TARGET, USER)));
assertOverlayInfoForTarget(TARGET, USER, o3, o1, o2); assertOverlayInfoForTarget(TARGET, USER, o3, o1, o2);
assertEquals(impl.setHighestPriority(OVERLAY3, USER), assertTrue(impl.setHighestPriority(OVERLAY3, USER));
Optional.of(new PackageAndUser(TARGET, USER)));
assertOverlayInfoForTarget(TARGET, USER, o1, o2, o3); assertOverlayInfoForTarget(TARGET, USER, o1, o2, o3);
assertEquals(impl.setPriority(OVERLAY, OVERLAY2, USER), assertTrue(impl.setPriority(OVERLAY, OVERLAY2, USER));
Optional.of(new PackageAndUser(TARGET, USER)));
assertOverlayInfoForTarget(TARGET, USER, o2, o1, o3); assertOverlayInfoForTarget(TARGET, USER, o2, o1, o3);
} }
@Test @Test
public void testOverlayInfoStateTransitions() throws Exception { public void testOverlayInfoStateTransitions() {
final OverlayManagerServiceImpl impl = getImpl(); final OverlayManagerServiceImpl impl = getImpl();
assertNull(impl.getOverlayInfo(OVERLAY, USER)); assertNull(impl.getOverlayInfo(OVERLAY, USER));
@@ -160,8 +153,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
installNewPackage(target, USER); installNewPackage(target, USER);
assertState(STATE_DISABLED, OVERLAY, USER); assertState(STATE_DISABLED, OVERLAY, USER);
assertEquals(impl.setEnabled(OVERLAY, true, USER), impl.setEnabled(OVERLAY, true, USER);
Optional.of(new PackageAndUser(TARGET, USER)));
assertState(STATE_ENABLED, OVERLAY, USER); assertState(STATE_ENABLED, OVERLAY, USER);
// target upgrades do not change the state of the overlay // target upgrades do not change the state of the overlay
@@ -176,40 +168,50 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
} }
@Test @Test
public void testOnOverlayPackageUpgraded() throws Exception { public void testOnOverlayPackageUpgraded() {
final FakeListener listener = getListener();
final FakeDeviceState.PackageBuilder target = target(TARGET); final FakeDeviceState.PackageBuilder target = target(TARGET);
final FakeDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET); final FakeDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET);
installNewPackage(target, USER); installNewPackage(target, USER);
installNewPackage(overlay, USER); installNewPackage(overlay, USER);
listener.count = 0;
upgradePackage(overlay, USER); upgradePackage(overlay, USER);
assertEquals(2, listener.count);
// upgrade to a version where the overlay has changed its target // 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 FakeDeviceState.PackageBuilder overlay2 = overlay(OVERLAY, "some.other.target");
final Pair<Optional<PackageAndUser>, Optional<PackageAndUser>> pair = upgradePackage(overlay2, USER);
upgradePackage(overlay2, USER); assertEquals(3, listener.count);
assertEquals(pair.first, Optional.of(new PackageAndUser(TARGET, USER)));
assertEquals(pair.second, Optional.of(new PackageAndUser("some.other.target", USER))); listener.count = 0;
upgradePackage(overlay2, USER);
assertEquals(2, listener.count);
} }
@Test @Test
public void testSetEnabledAtVariousConditions() throws Exception { public void testListener() {
final OverlayManagerServiceImpl impl = getImpl(); final OverlayManagerServiceImpl impl = getImpl();
assertThrows(OverlayManagerServiceImpl.OperationFailedException.class, final FakeListener listener = getListener();
() -> 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);
installNewPackage(overlay(OVERLAY, TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET), USER);
assertEquals(impl.setEnabled(OVERLAY, true, USER), assertEquals(1, listener.count);
Optional.of(new PackageAndUser(TARGET, USER))); listener.count = 0;
// request succeeded, but nothing changed installNewPackage(target(TARGET), USER);
assertFalse(impl.setEnabled(OVERLAY, true, USER).isPresent()); assertEquals(1, listener.count);
listener.count = 0;
impl.setEnabled(OVERLAY, true, USER);
assertEquals(1, listener.count);
listener.count = 0;
impl.setEnabled(OVERLAY, true, USER);
assertEquals(0, listener.count);
} }
@Test @Test
public void testConfigSignaturePolicyOk() throws Exception { public void testConfigSignaturePolicyOk() {
setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG); setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG);
reinitializeImpl(); reinitializeImpl();
@@ -227,7 +229,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
} }
@Test @Test
public void testConfigSignaturePolicyCertNok() throws Exception { public void testConfigSignaturePolicyCertNok() {
setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG); setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG);
reinitializeImpl(); reinitializeImpl();
@@ -245,7 +247,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
} }
@Test @Test
public void testConfigSignaturePolicyNoConfig() throws Exception { public void testConfigSignaturePolicyNoConfig() {
addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER); addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
installNewPackage(target(TARGET), USER); installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER); installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
@@ -260,7 +262,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
} }
@Test @Test
public void testConfigSignaturePolicyNoRefPkg() throws Exception { public void testConfigSignaturePolicyNoRefPkg() {
installNewPackage(target(TARGET), USER); installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER); installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
@@ -274,7 +276,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
} }
@Test @Test
public void testConfigSignaturePolicyRefPkgNotSystem() throws Exception { public void testConfigSignaturePolicyRefPkgNotSystem() {
setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG); setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG);
reinitializeImpl(); reinitializeImpl();

View File

@@ -16,8 +16,6 @@
package com.android.server.om; package com.android.server.om;
import static com.android.server.om.OverlayManagerServiceImpl.OperationFailedException;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
@@ -32,7 +30,6 @@ import android.content.pm.PackageInfo;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.ArraySet; import android.util.ArraySet;
import android.util.Pair;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@@ -46,13 +43,13 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** Base class for creating {@link OverlayManagerServiceImplTests} tests. */ /** Base class for creating {@link OverlayManagerServiceImplTests} tests. */
class OverlayManagerServiceImplTestsBase { class OverlayManagerServiceImplTestsBase {
private OverlayManagerServiceImpl mImpl; private OverlayManagerServiceImpl mImpl;
private FakeDeviceState mState; private FakeDeviceState mState;
private FakeListener mListener;
private FakePackageManagerHelper mPackageManager; private FakePackageManagerHelper mPackageManager;
private FakeIdmapDaemon mIdmapDaemon; private FakeIdmapDaemon mIdmapDaemon;
private OverlayConfig mOverlayConfig; private OverlayConfig mOverlayConfig;
@@ -61,6 +58,7 @@ class OverlayManagerServiceImplTestsBase {
@Before @Before
public void setUp() { public void setUp() {
mState = new FakeDeviceState(); mState = new FakeDeviceState();
mListener = new FakeListener();
mPackageManager = new FakePackageManagerHelper(mState); mPackageManager = new FakePackageManagerHelper(mState);
mIdmapDaemon = new FakeIdmapDaemon(mState); mIdmapDaemon = new FakeIdmapDaemon(mState);
mOverlayConfig = mock(OverlayConfig.class); mOverlayConfig = mock(OverlayConfig.class);
@@ -75,13 +73,18 @@ class OverlayManagerServiceImplTestsBase {
new IdmapManager(mIdmapDaemon, mPackageManager), new IdmapManager(mIdmapDaemon, mPackageManager),
new OverlayManagerSettings(), new OverlayManagerSettings(),
mOverlayConfig, mOverlayConfig,
new String[0]); new String[0],
mListener);
} }
OverlayManagerServiceImpl getImpl() { OverlayManagerServiceImpl getImpl() {
return mImpl; return mImpl;
} }
FakeListener getListener() {
return mListener;
}
FakeIdmapDaemon getIdmapd() { FakeIdmapDaemon getIdmapd() {
return mIdmapDaemon; return mIdmapDaemon;
} }
@@ -152,8 +155,7 @@ class OverlayManagerServiceImplTestsBase {
* *
* @throws IllegalStateException if the package is currently installed * @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) { if (mState.select(pkg.packageName, userId) != null) {
throw new IllegalStateException("package " + pkg.packageName + " already installed"); 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#ACTION_PACKAGE_ADDED} broadcast with the
* {@link android.content.Intent#EXTRA_REPLACING} extra. * {@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 * @throws IllegalStateException if the package is not currently installed
*/ */
Pair<Optional<PackageAndUser>, Optional<PackageAndUser>> upgradePackage( void upgradePackage(FakeDeviceState.PackageBuilder pkg, int userId) {
FakeDeviceState.PackageBuilder pkg, int userId) throws OperationFailedException {
final FakeDeviceState.Package replacedPackage = mState.select(pkg.packageName, userId); final FakeDeviceState.Package replacedPackage = mState.select(pkg.packageName, userId);
if (replacedPackage == null) { if (replacedPackage == null) {
throw new IllegalStateException("package " + pkg.packageName + " not installed"); throw new IllegalStateException("package " + pkg.packageName + " not installed");
} }
Optional<PackageAndUser> opt1 = Optional.empty();
if (replacedPackage.targetPackageName != null) { if (replacedPackage.targetPackageName != null) {
opt1 = mImpl.onOverlayPackageReplacing(pkg.packageName, userId); mImpl.onOverlayPackageReplacing(pkg.packageName, userId);
} }
mState.add(pkg, userId); mState.add(pkg, userId);
Optional<PackageAndUser> opt2;
if (pkg.targetPackage == null) { if (pkg.targetPackage == null) {
opt2 = mImpl.onTargetPackageReplaced(pkg.packageName, userId); mImpl.onTargetPackageReplaced(pkg.packageName, userId);
} else { } 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 * @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); final FakeDeviceState.Package pkg = mState.select(packageName, userId);
if (pkg == null) { if (pkg == null) {
throw new IllegalStateException("package " + packageName+ " not installed"); 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++;
}
}
} }