Merge "Add overlayable configurator resources" into rvc-dev am: 4515014469 am: 0c6c286e44
Change-Id: I13b5441d48424f605dd088c8f211859741b36daa
This commit is contained in:
@@ -4451,4 +4451,11 @@
|
|||||||
<bool name="config_pdp_reject_enable_retry">false</bool>
|
<bool name="config_pdp_reject_enable_retry">false</bool>
|
||||||
<!-- pdp data reject retry delay in ms -->
|
<!-- pdp data reject retry delay in ms -->
|
||||||
<integer name="config_pdp_reject_retry_delay_ms">-1</integer>
|
<integer name="config_pdp_reject_retry_delay_ms">-1</integer>
|
||||||
|
|
||||||
|
<!-- Package name that is recognized as an actor for the packages listed in
|
||||||
|
@array/config_overlayableConfiguratorTargets. If an overlay targeting one of the listed
|
||||||
|
targets is signed with the same signature as the configurator, the overlay will be granted
|
||||||
|
the "actor" policy. -->
|
||||||
|
<string name="config_overlayableConfigurator" translatable="false" />
|
||||||
|
<string-array name="config_overlayableConfiguratorTargets" translatable="false" />
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -4025,4 +4025,6 @@
|
|||||||
<java-symbol type="string" name="config_pdp_reject_service_not_subscribed" />
|
<java-symbol type="string" name="config_pdp_reject_service_not_subscribed" />
|
||||||
<java-symbol type="string" name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" />
|
<java-symbol type="string" name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" />
|
||||||
|
|
||||||
|
<java-symbol type="string" name="config_overlayableConfigurator" />
|
||||||
|
<java-symbol type="array" name="config_overlayableConfiguratorTargets" />
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import android.util.Slog;
|
|||||||
|
|
||||||
import com.android.server.FgThread;
|
import com.android.server.FgThread;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
@@ -124,9 +125,13 @@ class IdmapDaemon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String getIdmapPath(String overlayPath, int userId) throws TimeoutException, RemoteException {
|
boolean idmapExists(String overlayPath, int userId) {
|
||||||
try (Connection c = connect()) {
|
try (Connection c = connect()) {
|
||||||
return mService.getIdmapPath(overlayPath, userId);
|
return new File(mService.getIdmapPath(overlayPath, userId)).isFile();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Slog.wtf(TAG, "failed to check if idmap exists for " + overlayPath + ": "
|
||||||
|
+ e.getMessage());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,10 +27,10 @@ import android.content.pm.PackageInfo;
|
|||||||
import android.os.Build.VERSION_CODES;
|
import android.os.Build.VERSION_CODES;
|
||||||
import android.os.OverlayablePolicy;
|
import android.os.OverlayablePolicy;
|
||||||
import android.os.SystemProperties;
|
import android.os.SystemProperties;
|
||||||
import android.os.UserHandle;
|
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
import java.io.File;
|
import com.android.internal.util.ArrayUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,12 +55,16 @@ class IdmapManager {
|
|||||||
VENDOR_IS_Q_OR_LATER = isQOrLater;
|
VENDOR_IS_Q_OR_LATER = isQOrLater;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final OverlayableInfoCallback mOverlayableCallback;
|
|
||||||
private final IdmapDaemon mIdmapDaemon;
|
private final IdmapDaemon mIdmapDaemon;
|
||||||
|
private final OverlayableInfoCallback mOverlayableCallback;
|
||||||
|
private final String mOverlayableConfigurator;
|
||||||
|
private final String[] mOverlayableConfiguratorTargets;
|
||||||
|
|
||||||
IdmapManager(final OverlayableInfoCallback verifyCallback) {
|
IdmapManager(final IdmapDaemon idmapDaemon, final OverlayableInfoCallback verifyCallback) {
|
||||||
mOverlayableCallback = verifyCallback;
|
mOverlayableCallback = verifyCallback;
|
||||||
mIdmapDaemon = IdmapDaemon.getInstance();
|
mIdmapDaemon = idmapDaemon;
|
||||||
|
mOverlayableConfigurator = verifyCallback.getOverlayableConfigurator();
|
||||||
|
mOverlayableConfiguratorTargets = verifyCallback.getOverlayableConfiguratorTargets() ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,23 +107,11 @@ class IdmapManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean idmapExists(@NonNull final OverlayInfo oi) {
|
boolean idmapExists(@NonNull final OverlayInfo oi) {
|
||||||
return new File(getIdmapPath(oi.baseCodePath, oi.userId)).isFile();
|
return mIdmapDaemon.idmapExists(oi.baseCodePath, oi.userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean idmapExists(@NonNull final PackageInfo overlayPackage, final int userId) {
|
boolean idmapExists(@NonNull final PackageInfo overlayPackage, final int userId) {
|
||||||
return new File(getIdmapPath(overlayPackage.applicationInfo.getBaseCodePath(), userId))
|
return mIdmapDaemon.idmapExists(overlayPackage.applicationInfo.getBaseCodePath(), userId);
|
||||||
.isFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
private @NonNull String getIdmapPath(@NonNull final String overlayPackagePath,
|
|
||||||
final int userId) {
|
|
||||||
try {
|
|
||||||
return mIdmapDaemon.getIdmapPath(overlayPackagePath, userId);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Slog.w(TAG, "failed to get idmap path for " + overlayPackagePath + ": "
|
|
||||||
+ e.getMessage());
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -198,9 +190,17 @@ class IdmapManager {
|
|||||||
String targetOverlayableName = overlayPackage.targetOverlayableName;
|
String targetOverlayableName = overlayPackage.targetOverlayableName;
|
||||||
if (targetOverlayableName != null) {
|
if (targetOverlayableName != null) {
|
||||||
try {
|
try {
|
||||||
|
if (!mOverlayableConfigurator.isEmpty()
|
||||||
|
&& ArrayUtils.contains(mOverlayableConfiguratorTargets,
|
||||||
|
targetPackage.packageName)
|
||||||
|
&& mOverlayableCallback.signaturesMatching(mOverlayableConfigurator,
|
||||||
|
overlayPackage.packageName, userId)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
OverlayableInfo overlayableInfo = mOverlayableCallback.getOverlayableForTarget(
|
OverlayableInfo overlayableInfo = mOverlayableCallback.getOverlayableForTarget(
|
||||||
targetPackage.packageName, targetOverlayableName, userId);
|
targetPackage.packageName, targetOverlayableName, userId);
|
||||||
if (overlayableInfo != null) {
|
if (overlayableInfo != null && overlayableInfo.actor != null) {
|
||||||
String actorPackageName = OverlayActorEnforcer.getPackageNameForActor(
|
String actorPackageName = OverlayActorEnforcer.getPackageNameForActor(
|
||||||
overlayableInfo.actor, mOverlayableCallback.getNamedActors()).first;
|
overlayableInfo.actor, mOverlayableCallback.getNamedActors()).first;
|
||||||
if (mOverlayableCallback.signaturesMatching(actorPackageName,
|
if (mOverlayableCallback.signaturesMatching(actorPackageName,
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ public class OverlayActorEnforcer {
|
|||||||
/**
|
/**
|
||||||
* @return nullable actor result with {@link ActorState} failure status
|
* @return nullable actor result with {@link ActorState} failure status
|
||||||
*/
|
*/
|
||||||
static Pair<String, ActorState> getPackageNameForActor(String actorUriString,
|
static Pair<String, ActorState> getPackageNameForActor(@NonNull String actorUriString,
|
||||||
Map<String, Map<String, String>> namedActors) {
|
@NonNull Map<String, Map<String, String>> namedActors) {
|
||||||
Uri actorUri = Uri.parse(actorUriString);
|
Uri actorUri = Uri.parse(actorUriString);
|
||||||
|
|
||||||
String actorScheme = actorUri.getScheme();
|
String actorScheme = actorUri.getScheme();
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import android.content.pm.PackageInfo;
|
|||||||
import android.content.pm.PackageManagerInternal;
|
import android.content.pm.PackageManagerInternal;
|
||||||
import android.content.pm.UserInfo;
|
import android.content.pm.UserInfo;
|
||||||
import android.content.res.ApkAssets;
|
import android.content.res.ApkAssets;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
@@ -62,6 +63,7 @@ import android.util.AtomicFile;
|
|||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
|
||||||
|
import com.android.internal.R;
|
||||||
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.IoThread;
|
||||||
@@ -246,7 +248,7 @@ public final class OverlayManagerService extends SystemService {
|
|||||||
new File(Environment.getDataSystemDirectory(), "overlays.xml"), "overlays");
|
new File(Environment.getDataSystemDirectory(), "overlays.xml"), "overlays");
|
||||||
mPackageManager = new PackageManagerHelperImpl(context);
|
mPackageManager = new PackageManagerHelperImpl(context);
|
||||||
mUserManager = UserManagerService.getInstance();
|
mUserManager = UserManagerService.getInstance();
|
||||||
IdmapManager im = new IdmapManager(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(),
|
||||||
@@ -1118,6 +1120,17 @@ public final class OverlayManagerService extends SystemService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getOverlayableConfigurator() {
|
||||||
|
return Resources.getSystem().getString(R.string.config_overlayableConfigurator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getOverlayableConfiguratorTargets() {
|
||||||
|
return Resources.getSystem().getStringArray(
|
||||||
|
R.array.config_overlayableConfiguratorTargets);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<PackageInfo> getOverlayPackages(final int userId) {
|
public List<PackageInfo> getOverlayPackages(final int userId) {
|
||||||
final List<PackageInfo> overlays = mPackageManagerInternal.getOverlayPackages(userId);
|
final List<PackageInfo> overlays = mPackageManagerInternal.getOverlayPackages(userId);
|
||||||
|
|||||||
@@ -80,4 +80,24 @@ public interface OverlayableInfoCallback {
|
|||||||
* in the system returns {@link PackageManager#SIGNATURE_MATCH}
|
* in the system returns {@link PackageManager#SIGNATURE_MATCH}
|
||||||
*/
|
*/
|
||||||
boolean signaturesMatching(@NonNull String pkgName1, @NonNull String pkgName2, int userId);
|
boolean signaturesMatching(@NonNull String pkgName1, @NonNull String pkgName2, int userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the package name that is recognized as an actor for the packages specified by
|
||||||
|
* {@link #getOverlayableConfiguratorTargets()}.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
default String getOverlayableConfigurator() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the target packages that recognize the {@link #getOverlayableConfigurator} as an
|
||||||
|
* actor for its overlayable declarations. Overlays targeting one of the specified targets that
|
||||||
|
* are signed with the same signature as the overlayable configurator will be granted the
|
||||||
|
* "actor" policy.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
default String[] getOverlayableConfiguratorTargets() {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,9 +44,9 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
|
|||||||
@Test
|
@Test
|
||||||
public void testUpdateOverlaysForUser() {
|
public void testUpdateOverlaysForUser() {
|
||||||
final OverlayManagerServiceImpl impl = getImpl();
|
final OverlayManagerServiceImpl impl = getImpl();
|
||||||
installTargetPackage(TARGET, USER);
|
addSystemPackage(target(TARGET), USER);
|
||||||
installTargetPackage("some.other.target", USER);
|
addSystemPackage(target("some.other.target"), USER);;
|
||||||
installOverlayPackage(OVERLAY, TARGET, USER);
|
addSystemPackage(overlay(OVERLAY, TARGET), USER);
|
||||||
|
|
||||||
// do nothing, expect no change
|
// do nothing, expect no change
|
||||||
final List<String> a = impl.updateOverlaysForUser(USER);
|
final List<String> a = impl.updateOverlaysForUser(USER);
|
||||||
@@ -54,8 +54,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
|
|||||||
assertTrue(a.contains(TARGET));
|
assertTrue(a.contains(TARGET));
|
||||||
|
|
||||||
// upgrade overlay, keep target
|
// upgrade overlay, keep target
|
||||||
beginUpgradeOverlayPackage(OVERLAY, USER);
|
addSystemPackage(overlay(OVERLAY, TARGET), USER);
|
||||||
endUpgradeOverlayPackage(OVERLAY, TARGET, USER);
|
|
||||||
|
|
||||||
final List<String> b = impl.updateOverlaysForUser(USER);
|
final List<String> b = impl.updateOverlaysForUser(USER);
|
||||||
assertEquals(1, b.size());
|
assertEquals(1, b.size());
|
||||||
@@ -67,7 +66,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
|
|||||||
assertTrue(c.contains(TARGET));
|
assertTrue(c.contains(TARGET));
|
||||||
|
|
||||||
// upgrade overlay, switch to new target
|
// upgrade overlay, switch to new target
|
||||||
addOverlayPackage(OVERLAY, "some.other.target", USER, true, false, 0);
|
addSystemPackage(overlay(OVERLAY, "some.other.target"), USER);
|
||||||
final List<String> d = impl.updateOverlaysForUser(USER);
|
final List<String> d = impl.updateOverlaysForUser(USER);
|
||||||
assertEquals(2, d.size());
|
assertEquals(2, d.size());
|
||||||
assertTrue(d.containsAll(Arrays.asList(TARGET, "some.other.target")));
|
assertTrue(d.containsAll(Arrays.asList(TARGET, "some.other.target")));
|
||||||
@@ -81,23 +80,24 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
|
|||||||
@Test
|
@Test
|
||||||
public void testImmutableEnabledChange() {
|
public void testImmutableEnabledChange() {
|
||||||
final OverlayManagerServiceImpl impl = getImpl();
|
final OverlayManagerServiceImpl impl = getImpl();
|
||||||
installTargetPackage(TARGET, USER);
|
installNewPackage(target(TARGET), USER);
|
||||||
|
installNewPackage(overlay(OVERLAY, TARGET), USER);
|
||||||
|
|
||||||
addOverlayPackage(OVERLAY, TARGET, USER, false, false, 0);
|
configureSystemOverlay(OVERLAY, false /* mutable */, false /* enabled */, 0 /* priority */);
|
||||||
impl.updateOverlaysForUser(USER);
|
impl.updateOverlaysForUser(USER);
|
||||||
final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
|
final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
|
||||||
assertNotNull(o1);
|
assertNotNull(o1);
|
||||||
assertFalse(o1.isEnabled());
|
assertFalse(o1.isEnabled());
|
||||||
assertFalse(o1.isMutable);
|
assertFalse(o1.isMutable);
|
||||||
|
|
||||||
addOverlayPackage(OVERLAY, TARGET, USER, false, true, 0);
|
configureSystemOverlay(OVERLAY, false /* mutable */, true /* enabled */, 0 /* priority */);
|
||||||
impl.updateOverlaysForUser(USER);
|
impl.updateOverlaysForUser(USER);
|
||||||
final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY, USER);
|
final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY, USER);
|
||||||
assertNotNull(o2);
|
assertNotNull(o2);
|
||||||
assertTrue(o2.isEnabled());
|
assertTrue(o2.isEnabled());
|
||||||
assertFalse(o2.isMutable);
|
assertFalse(o2.isMutable);
|
||||||
|
|
||||||
addOverlayPackage(OVERLAY, TARGET, USER, false, false, 0);
|
configureSystemOverlay(OVERLAY, false /* mutable */, false /* enabled */, 0 /* priority */);
|
||||||
impl.updateOverlaysForUser(USER);
|
impl.updateOverlaysForUser(USER);
|
||||||
final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY, USER);
|
final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY, USER);
|
||||||
assertNotNull(o3);
|
assertNotNull(o3);
|
||||||
@@ -108,23 +108,24 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
|
|||||||
@Test
|
@Test
|
||||||
public void testMutableEnabledChangeHasNoEffect() {
|
public void testMutableEnabledChangeHasNoEffect() {
|
||||||
final OverlayManagerServiceImpl impl = getImpl();
|
final OverlayManagerServiceImpl impl = getImpl();
|
||||||
installTargetPackage(TARGET, USER);
|
installNewPackage(target(TARGET), USER);
|
||||||
|
installNewPackage(overlay(OVERLAY, TARGET), USER);
|
||||||
|
configureSystemOverlay(OVERLAY, true /* mutable */, false /* enabled */, 0 /* priority */);
|
||||||
|
|
||||||
addOverlayPackage(OVERLAY, TARGET, USER, true, false, 0);
|
|
||||||
impl.updateOverlaysForUser(USER);
|
impl.updateOverlaysForUser(USER);
|
||||||
final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
|
final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
|
||||||
assertNotNull(o1);
|
assertNotNull(o1);
|
||||||
assertFalse(o1.isEnabled());
|
assertFalse(o1.isEnabled());
|
||||||
assertTrue(o1.isMutable);
|
assertTrue(o1.isMutable);
|
||||||
|
|
||||||
addOverlayPackage(OVERLAY, TARGET, USER, true, true, 0);
|
configureSystemOverlay(OVERLAY, true /* mutable */, true /* enabled */, 0 /* priority */);
|
||||||
impl.updateOverlaysForUser(USER);
|
impl.updateOverlaysForUser(USER);
|
||||||
final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY, USER);
|
final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY, USER);
|
||||||
assertNotNull(o2);
|
assertNotNull(o2);
|
||||||
assertFalse(o2.isEnabled());
|
assertFalse(o2.isEnabled());
|
||||||
assertTrue(o2.isMutable);
|
assertTrue(o2.isMutable);
|
||||||
|
|
||||||
addOverlayPackage(OVERLAY, TARGET, USER, true, false, 0);
|
configureSystemOverlay(OVERLAY, true /* mutable */, false /* enabled */, 0 /* priority */);
|
||||||
impl.updateOverlaysForUser(USER);
|
impl.updateOverlaysForUser(USER);
|
||||||
final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY, USER);
|
final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY, USER);
|
||||||
assertNotNull(o3);
|
assertNotNull(o3);
|
||||||
@@ -135,15 +136,16 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
|
|||||||
@Test
|
@Test
|
||||||
public void testMutableEnabledToImmutableEnabled() {
|
public void testMutableEnabledToImmutableEnabled() {
|
||||||
final OverlayManagerServiceImpl impl = getImpl();
|
final OverlayManagerServiceImpl impl = getImpl();
|
||||||
installTargetPackage(TARGET, USER);
|
installNewPackage(target(TARGET), USER);
|
||||||
|
installNewPackage(overlay(OVERLAY, TARGET), USER);
|
||||||
|
|
||||||
final BiConsumer<Boolean, Boolean> setOverlay = (mutable, enabled) -> {
|
final BiConsumer<Boolean, Boolean> setOverlay = (mutable, enabled) -> {
|
||||||
addOverlayPackage(OVERLAY, TARGET, USER, mutable, enabled, 0);
|
configureSystemOverlay(OVERLAY, mutable, enabled, 0 /* priority */);
|
||||||
impl.updateOverlaysForUser(USER);
|
impl.updateOverlaysForUser(USER);
|
||||||
final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
|
final OverlayInfo o = impl.getOverlayInfo(OVERLAY, USER);
|
||||||
assertNotNull(o1);
|
assertNotNull(o);
|
||||||
assertEquals(enabled, o1.isEnabled());
|
assertEquals(enabled, o.isEnabled());
|
||||||
assertEquals(mutable, o1.isMutable);
|
assertEquals(mutable, o.isMutable);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Immutable/enabled -> mutable/enabled
|
// Immutable/enabled -> mutable/enabled
|
||||||
@@ -178,70 +180,76 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
|
|||||||
@Test
|
@Test
|
||||||
public void testMutablePriorityChange() {
|
public void testMutablePriorityChange() {
|
||||||
final OverlayManagerServiceImpl impl = getImpl();
|
final OverlayManagerServiceImpl impl = getImpl();
|
||||||
installTargetPackage(TARGET, USER);
|
installNewPackage(target(TARGET), USER);
|
||||||
addOverlayPackage(OVERLAY, TARGET, USER, true, true, 0);
|
installNewPackage(overlay(OVERLAY, TARGET), USER);
|
||||||
addOverlayPackage(OVERLAY2, TARGET, USER, true, true, 1);
|
installNewPackage(overlay(OVERLAY2, TARGET), USER);
|
||||||
|
configureSystemOverlay(OVERLAY, true /* mutable */, false /* enabled */, 0 /* priority */);
|
||||||
|
configureSystemOverlay(OVERLAY2, true /* mutable */, false /* enabled */, 1 /* priority */);
|
||||||
impl.updateOverlaysForUser(USER);
|
impl.updateOverlaysForUser(USER);
|
||||||
|
|
||||||
final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
|
final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
|
||||||
assertNotNull(o1);
|
assertNotNull(o1);
|
||||||
assertEquals(0, o1.priority);
|
assertEquals(0, o1.priority);
|
||||||
|
assertFalse(o1.isEnabled());
|
||||||
|
|
||||||
final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY2, USER);
|
final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY2, USER);
|
||||||
assertNotNull(o2);
|
assertNotNull(o2);
|
||||||
assertEquals(1, o2.priority);
|
assertEquals(1, o2.priority);
|
||||||
|
assertFalse(o2.isEnabled());
|
||||||
|
|
||||||
// Overlay priority changing between reboots should not affect enable state of mutable
|
// Overlay priority changing between reboots should not affect enable state of mutable
|
||||||
// overlays
|
// overlays.
|
||||||
impl.setEnabled(OVERLAY, true, USER);
|
impl.setEnabled(OVERLAY, true, USER);
|
||||||
|
|
||||||
// Reorder the overlays
|
// Reorder the overlays
|
||||||
addOverlayPackage(OVERLAY, TARGET, USER, true, true, 1);
|
configureSystemOverlay(OVERLAY, true /* mutable */, false /* enabled */, 1 /* priority */);
|
||||||
addOverlayPackage(OVERLAY2, TARGET, USER, true, true, 0);
|
configureSystemOverlay(OVERLAY2, true /* mutable */, false /* enabled */, 0 /* priority */);
|
||||||
impl.updateOverlaysForUser(USER);
|
impl.updateOverlaysForUser(USER);
|
||||||
|
|
||||||
final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY, USER);
|
final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY, USER);
|
||||||
assertNotNull(o3);
|
assertNotNull(o3);
|
||||||
assertEquals(1, o3.priority);
|
assertEquals(1, o3.priority);
|
||||||
|
assertTrue(o3.isEnabled());
|
||||||
|
|
||||||
final OverlayInfo o4 = impl.getOverlayInfo(OVERLAY2, USER);
|
final OverlayInfo o4 = impl.getOverlayInfo(OVERLAY2, USER);
|
||||||
assertNotNull(o4);
|
assertNotNull(o4);
|
||||||
assertEquals(0, o4.priority);
|
assertEquals(0, o4.priority);
|
||||||
assertTrue(o1.isEnabled());
|
assertFalse(o4.isEnabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testImmutablePriorityChange() {
|
public void testImmutablePriorityChange() {
|
||||||
final OverlayManagerServiceImpl impl = getImpl();
|
final OverlayManagerServiceImpl impl = getImpl();
|
||||||
installTargetPackage(TARGET, USER);
|
installNewPackage(target(TARGET), USER);
|
||||||
addOverlayPackage(OVERLAY, TARGET, USER, false, true, 0);
|
installNewPackage(overlay(OVERLAY, TARGET), USER);
|
||||||
addOverlayPackage(OVERLAY2, TARGET, USER, false, true, 1);
|
installNewPackage(overlay(OVERLAY2, TARGET), USER);
|
||||||
|
configureSystemOverlay(OVERLAY, false /* mutable */, true /* enabled */, 0 /* priority */);
|
||||||
|
configureSystemOverlay(OVERLAY2, false /* mutable */, true /* enabled */, 1 /* priority */);
|
||||||
impl.updateOverlaysForUser(USER);
|
impl.updateOverlaysForUser(USER);
|
||||||
|
|
||||||
final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
|
final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
|
||||||
assertNotNull(o1);
|
assertNotNull(o1);
|
||||||
assertEquals(0, o1.priority);
|
assertEquals(0, o1.priority);
|
||||||
|
assertTrue(o1.isEnabled());
|
||||||
|
|
||||||
final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY2, USER);
|
final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY2, USER);
|
||||||
assertNotNull(o2);
|
assertNotNull(o2);
|
||||||
assertEquals(1, o2.priority);
|
assertEquals(1, o2.priority);
|
||||||
|
assertTrue(o2.isEnabled());
|
||||||
// Overlay priority changing between reboots should not affect enable state of mutable
|
|
||||||
// overlays
|
|
||||||
impl.setEnabled(OVERLAY, true, USER);
|
|
||||||
|
|
||||||
// Reorder the overlays
|
// Reorder the overlays
|
||||||
addOverlayPackage(OVERLAY, TARGET, USER, false, true, 1);
|
configureSystemOverlay(OVERLAY, false /* mutable */, true /* enabled */, 1 /* priority */);
|
||||||
addOverlayPackage(OVERLAY2, TARGET, USER, false, true, 0);
|
configureSystemOverlay(OVERLAY2, false /* mutable */, true /* enabled */, 0 /* priority */);
|
||||||
impl.updateOverlaysForUser(USER);
|
impl.updateOverlaysForUser(USER);
|
||||||
|
|
||||||
final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY, USER);
|
final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY, USER);
|
||||||
assertNotNull(o3);
|
assertNotNull(o3);
|
||||||
assertEquals(1, o3.priority);
|
assertEquals(1, o3.priority);
|
||||||
|
assertTrue(o3.isEnabled());
|
||||||
|
|
||||||
final OverlayInfo o4 = impl.getOverlayInfo(OVERLAY2, USER);
|
final OverlayInfo o4 = impl.getOverlayInfo(OVERLAY2, USER);
|
||||||
assertNotNull(o4);
|
assertNotNull(o4);
|
||||||
assertEquals(0, o4.priority);
|
assertEquals(0, o4.priority);
|
||||||
assertTrue(o1.isEnabled());
|
assertTrue(o4.isEnabled());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import static org.junit.Assert.assertNull;
|
|||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import android.content.om.OverlayInfo;
|
import android.content.om.OverlayInfo;
|
||||||
|
import android.os.OverlayablePolicy;
|
||||||
|
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
@@ -49,11 +50,9 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
|
|||||||
private static final String OVERLAY3 = OVERLAY + "3";
|
private static final String OVERLAY3 = OVERLAY + "3";
|
||||||
private static final int USER3 = USER2 + 1;
|
private static final int USER3 = USER2 + 1;
|
||||||
|
|
||||||
// tests: basics
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetOverlayInfo() throws Exception {
|
public void testGetOverlayInfo() {
|
||||||
installOverlayPackage(OVERLAY, TARGET, USER);
|
installNewPackage(overlay(OVERLAY, TARGET), USER);
|
||||||
|
|
||||||
final OverlayManagerServiceImpl impl = getImpl();
|
final OverlayManagerServiceImpl impl = getImpl();
|
||||||
final OverlayInfo oi = impl.getOverlayInfo(OVERLAY, USER);
|
final OverlayInfo oi = impl.getOverlayInfo(OVERLAY, USER);
|
||||||
@@ -64,10 +63,10 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetOverlayInfosForTarget() throws Exception {
|
public void testGetOverlayInfosForTarget() {
|
||||||
installOverlayPackage(OVERLAY, TARGET, USER);
|
installNewPackage(overlay(OVERLAY, TARGET), USER);
|
||||||
installOverlayPackage(OVERLAY2, TARGET, USER);
|
installNewPackage(overlay(OVERLAY2, TARGET), USER);
|
||||||
installOverlayPackage(OVERLAY3, TARGET, USER2);
|
installNewPackage(overlay(OVERLAY3, TARGET), USER2);
|
||||||
|
|
||||||
final OverlayManagerServiceImpl impl = getImpl();
|
final OverlayManagerServiceImpl impl = getImpl();
|
||||||
final List<OverlayInfo> ois = impl.getOverlayInfosForTarget(TARGET, USER);
|
final List<OverlayInfo> ois = impl.getOverlayInfosForTarget(TARGET, USER);
|
||||||
@@ -89,11 +88,11 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetOverlayInfosForUser() throws Exception {
|
public void testGetOverlayInfosForUser() {
|
||||||
installTargetPackage(TARGET, USER);
|
installNewPackage(target(TARGET), USER);
|
||||||
installOverlayPackage(OVERLAY, TARGET, USER);
|
installNewPackage(overlay(OVERLAY, TARGET), USER);
|
||||||
installOverlayPackage(OVERLAY2, TARGET, USER);
|
installNewPackage(overlay(OVERLAY2, TARGET), USER);
|
||||||
installOverlayPackage(OVERLAY3, TARGET2, USER);
|
installNewPackage(overlay(OVERLAY3, TARGET2), USER);
|
||||||
|
|
||||||
final OverlayManagerServiceImpl impl = getImpl();
|
final OverlayManagerServiceImpl impl = getImpl();
|
||||||
final Map<String, List<OverlayInfo>> everything = impl.getOverlaysForUser(USER);
|
final Map<String, List<OverlayInfo>> everything = impl.getOverlaysForUser(USER);
|
||||||
@@ -116,91 +115,86 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPriority() throws Exception {
|
public void testPriority() {
|
||||||
installOverlayPackage(OVERLAY, TARGET, USER);
|
installNewPackage(overlay(OVERLAY, TARGET), USER);
|
||||||
installOverlayPackage(OVERLAY2, TARGET, USER);
|
installNewPackage(overlay(OVERLAY2, TARGET), USER);
|
||||||
installOverlayPackage(OVERLAY3, TARGET, USER);
|
installNewPackage(overlay(OVERLAY3, TARGET), USER);
|
||||||
|
|
||||||
final OverlayManagerServiceImpl impl = getImpl();
|
final OverlayManagerServiceImpl impl = getImpl();
|
||||||
final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
|
final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
|
||||||
final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY2, USER);
|
final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY2, USER);
|
||||||
final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY3, USER);
|
final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY3, USER);
|
||||||
|
|
||||||
assertOverlayInfoList(TARGET, USER, o1, o2, o3);
|
assertOverlayInfoForTarget(TARGET, USER, o1, o2, o3);
|
||||||
|
|
||||||
assertTrue(impl.setLowestPriority(OVERLAY3, USER));
|
assertTrue(impl.setLowestPriority(OVERLAY3, USER));
|
||||||
assertOverlayInfoList(TARGET, USER, o3, o1, o2);
|
assertOverlayInfoForTarget(TARGET, USER, o3, o1, o2);
|
||||||
|
|
||||||
assertTrue(impl.setHighestPriority(OVERLAY3, USER));
|
assertTrue(impl.setHighestPriority(OVERLAY3, USER));
|
||||||
assertOverlayInfoList(TARGET, USER, o1, o2, o3);
|
assertOverlayInfoForTarget(TARGET, USER, o1, o2, o3);
|
||||||
|
|
||||||
assertTrue(impl.setPriority(OVERLAY, OVERLAY2, USER));
|
assertTrue(impl.setPriority(OVERLAY, OVERLAY2, USER));
|
||||||
assertOverlayInfoList(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));
|
||||||
|
|
||||||
installOverlayPackage(OVERLAY, TARGET, USER);
|
installNewPackage(overlay(OVERLAY, TARGET), USER);
|
||||||
assertState(STATE_MISSING_TARGET, OVERLAY, USER);
|
assertState(STATE_MISSING_TARGET, OVERLAY, USER);
|
||||||
|
|
||||||
installTargetPackage(TARGET, USER);
|
final DummyDeviceState.PackageBuilder target = target(TARGET);
|
||||||
|
installNewPackage(target, USER);
|
||||||
assertState(STATE_DISABLED, OVERLAY, USER);
|
assertState(STATE_DISABLED, OVERLAY, USER);
|
||||||
|
|
||||||
impl.setEnabled(OVERLAY, true, USER);
|
impl.setEnabled(OVERLAY, true, 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
|
||||||
beginUpgradeTargetPackage(TARGET, USER);
|
upgradePackage(target, USER);
|
||||||
assertState(STATE_ENABLED, OVERLAY, USER);
|
assertState(STATE_ENABLED, OVERLAY, USER);
|
||||||
|
|
||||||
endUpgradeTargetPackage(TARGET, USER);
|
uninstallPackage(TARGET, USER);
|
||||||
assertState(STATE_ENABLED, OVERLAY, USER);
|
|
||||||
|
|
||||||
uninstallTargetPackage(TARGET, USER);
|
|
||||||
assertState(STATE_MISSING_TARGET, OVERLAY, USER);
|
assertState(STATE_MISSING_TARGET, OVERLAY, USER);
|
||||||
|
|
||||||
installTargetPackage(TARGET, USER);
|
installNewPackage(target, USER);
|
||||||
assertState(STATE_ENABLED, OVERLAY, USER);
|
assertState(STATE_ENABLED, OVERLAY, USER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOnOverlayPackageUpgraded() throws Exception {
|
public void testOnOverlayPackageUpgraded() {
|
||||||
final OverlayManagerServiceImpl impl = getImpl();
|
|
||||||
final DummyListener listener = getListener();
|
final DummyListener listener = getListener();
|
||||||
installTargetPackage(TARGET, USER);
|
final DummyDeviceState.PackageBuilder target = target(TARGET);
|
||||||
installOverlayPackage(OVERLAY, TARGET, USER);
|
final DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET);
|
||||||
impl.onOverlayPackageReplacing(OVERLAY, USER);
|
installNewPackage(target, USER);
|
||||||
|
installNewPackage(overlay, USER);
|
||||||
listener.count = 0;
|
listener.count = 0;
|
||||||
impl.onOverlayPackageReplaced(OVERLAY, USER);
|
upgradePackage(overlay, USER);
|
||||||
assertEquals(1, listener.count);
|
|
||||||
|
|
||||||
// upgrade to a version where the overlay has changed its target
|
|
||||||
beginUpgradeOverlayPackage(OVERLAY, USER);
|
|
||||||
listener.count = 0;
|
|
||||||
endUpgradeOverlayPackage(OVERLAY, "some.other.target", USER);
|
|
||||||
// expect once for the old target package, once for the new target package
|
|
||||||
assertEquals(2, listener.count);
|
assertEquals(2, listener.count);
|
||||||
|
|
||||||
beginUpgradeOverlayPackage(OVERLAY, USER);
|
// 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;
|
listener.count = 0;
|
||||||
endUpgradeOverlayPackage(OVERLAY, "some.other.target", USER);
|
final DummyDeviceState.PackageBuilder overlay2 = overlay(OVERLAY, "some.other.target");
|
||||||
assertEquals(1, listener.count);
|
upgradePackage(overlay2, USER);
|
||||||
|
assertEquals(3, listener.count);
|
||||||
|
|
||||||
|
listener.count = 0;
|
||||||
|
upgradePackage(overlay2, USER);
|
||||||
|
assertEquals(2, listener.count);
|
||||||
}
|
}
|
||||||
|
|
||||||
// tests: listener interface
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testListener() throws Exception {
|
public void testListener() {
|
||||||
final OverlayManagerServiceImpl impl = getImpl();
|
final OverlayManagerServiceImpl impl = getImpl();
|
||||||
final DummyListener listener = getListener();
|
final DummyListener listener = getListener();
|
||||||
installOverlayPackage(OVERLAY, TARGET, USER);
|
installNewPackage(overlay(OVERLAY, TARGET), USER);
|
||||||
assertEquals(1, listener.count);
|
assertEquals(1, listener.count);
|
||||||
listener.count = 0;
|
listener.count = 0;
|
||||||
|
|
||||||
installTargetPackage(TARGET, USER);
|
installNewPackage(target(TARGET), USER);
|
||||||
assertEquals(1, listener.count);
|
assertEquals(1, listener.count);
|
||||||
listener.count = 0;
|
listener.count = 0;
|
||||||
|
|
||||||
@@ -211,4 +205,49 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
|
|||||||
impl.setEnabled(OVERLAY, true, USER);
|
impl.setEnabled(OVERLAY, true, USER);
|
||||||
assertEquals(0, listener.count);
|
assertEquals(0, listener.count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConfigurator() {
|
||||||
|
final DummyPackageManagerHelper packageManager = getPackageManager();
|
||||||
|
packageManager.overlayableConfigurator = "actor";
|
||||||
|
packageManager.overlayableConfiguratorTargets = new String[]{TARGET};
|
||||||
|
reinitializeImpl();
|
||||||
|
|
||||||
|
installNewPackage(target("actor").setCertificate("one"), USER);
|
||||||
|
installNewPackage(target(TARGET)
|
||||||
|
.addOverlayable("TestResources")
|
||||||
|
.setCertificate("two"), USER);
|
||||||
|
|
||||||
|
final DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET, "TestResources")
|
||||||
|
.setCertificate("one");
|
||||||
|
installNewPackage(overlay, USER);
|
||||||
|
|
||||||
|
final DummyIdmapDaemon idmapDaemon = getIdmapDaemon();
|
||||||
|
final DummyIdmapDaemon.IdmapHeader idmap = idmapDaemon.getIdmap(overlay.build().apkPath);
|
||||||
|
assertNotNull(idmap);
|
||||||
|
assertEquals(OverlayablePolicy.ACTOR_SIGNATURE,
|
||||||
|
idmap.policies & OverlayablePolicy.ACTOR_SIGNATURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConfiguratorDifferentSignatures() {
|
||||||
|
final DummyPackageManagerHelper packageManager = getPackageManager();
|
||||||
|
packageManager.overlayableConfigurator = "actor";
|
||||||
|
packageManager.overlayableConfiguratorTargets = new String[]{TARGET};
|
||||||
|
reinitializeImpl();
|
||||||
|
|
||||||
|
installNewPackage(target("actor").setCertificate("one"), USER);
|
||||||
|
installNewPackage(target(TARGET)
|
||||||
|
.addOverlayable("TestResources")
|
||||||
|
.setCertificate("two"), USER);
|
||||||
|
|
||||||
|
final DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET, "TestResources")
|
||||||
|
.setCertificate("two");
|
||||||
|
installNewPackage(overlay, USER);
|
||||||
|
|
||||||
|
final DummyIdmapDaemon idmapDaemon = getIdmapDaemon();
|
||||||
|
final DummyIdmapDaemon.IdmapHeader idmap = idmapDaemon.getIdmap(overlay.build().apkPath);
|
||||||
|
assertNotNull(idmap);
|
||||||
|
assertEquals(0, idmap.policies & OverlayablePolicy.ACTOR_SIGNATURE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package com.android.server.om;
|
package com.android.server.om;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@@ -26,17 +27,19 @@ import android.content.om.OverlayInfo.State;
|
|||||||
import android.content.om.OverlayableInfo;
|
import android.content.om.OverlayableInfo;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.util.ArrayMap;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.android.internal.content.om.OverlayConfig;
|
import com.android.internal.content.om.OverlayConfig;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Iterator;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -47,29 +50,48 @@ class OverlayManagerServiceImplTestsBase {
|
|||||||
private OverlayManagerServiceImpl mImpl;
|
private OverlayManagerServiceImpl mImpl;
|
||||||
private DummyDeviceState mState;
|
private DummyDeviceState mState;
|
||||||
private DummyListener mListener;
|
private DummyListener mListener;
|
||||||
|
private DummyPackageManagerHelper mPackageManager;
|
||||||
|
private DummyIdmapDaemon mIdmapDaemon;
|
||||||
|
private OverlayConfig mOverlayConfig;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
mState = new DummyDeviceState();
|
mState = new DummyDeviceState();
|
||||||
mListener = new DummyListener();
|
mListener = new DummyListener();
|
||||||
final DummyPackageManagerHelper pmh = new DummyPackageManagerHelper(mState);
|
mPackageManager = new DummyPackageManagerHelper(mState);
|
||||||
|
mIdmapDaemon = new DummyIdmapDaemon(mState);
|
||||||
|
mOverlayConfig = mock(OverlayConfig.class);
|
||||||
|
when(mOverlayConfig.getPriority(any())).thenReturn(OverlayConfig.DEFAULT_PRIORITY);
|
||||||
|
when(mOverlayConfig.isEnabled(any())).thenReturn(false);
|
||||||
|
when(mOverlayConfig.isMutable(any())).thenReturn(true);
|
||||||
|
reinitializeImpl();
|
||||||
|
}
|
||||||
|
|
||||||
mImpl = new OverlayManagerServiceImpl(pmh,
|
void reinitializeImpl() {
|
||||||
new DummyIdmapManager(mState, pmh),
|
mImpl = new OverlayManagerServiceImpl(mPackageManager,
|
||||||
|
new IdmapManager(mIdmapDaemon, mPackageManager),
|
||||||
new OverlayManagerSettings(),
|
new OverlayManagerSettings(),
|
||||||
mState.mOverlayConfig,
|
mOverlayConfig,
|
||||||
new String[0],
|
new String[0],
|
||||||
mListener);
|
mListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public OverlayManagerServiceImpl getImpl() {
|
OverlayManagerServiceImpl getImpl() {
|
||||||
return mImpl;
|
return mImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DummyListener getListener() {
|
DummyListener getListener() {
|
||||||
return mListener;
|
return mListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DummyPackageManagerHelper getPackageManager() {
|
||||||
|
return mPackageManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
DummyIdmapDaemon getIdmapDaemon() {
|
||||||
|
return mIdmapDaemon;
|
||||||
|
}
|
||||||
|
|
||||||
void assertState(@State int expected, final String overlayPackageName, int userId) {
|
void assertState(@State int expected, final String overlayPackageName, int userId) {
|
||||||
final OverlayInfo info = mImpl.getOverlayInfo(overlayPackageName, userId);
|
final OverlayInfo info = mImpl.getOverlayInfo(overlayPackageName, userId);
|
||||||
if (info == null) {
|
if (info == null) {
|
||||||
@@ -81,7 +103,7 @@ class OverlayManagerServiceImplTestsBase {
|
|||||||
assertEquals(msg, expected, info.state);
|
assertEquals(msg, expected, info.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void assertOverlayInfoList(final String targetPackageName, int userId,
|
void assertOverlayInfoForTarget(final String targetPackageName, int userId,
|
||||||
OverlayInfo... overlayInfos) {
|
OverlayInfo... overlayInfos) {
|
||||||
final List<OverlayInfo> expected =
|
final List<OverlayInfo> expected =
|
||||||
mImpl.getOverlayInfosForTarget(targetPackageName, userId);
|
mImpl.getOverlayInfosForTarget(targetPackageName, userId);
|
||||||
@@ -89,198 +111,202 @@ class OverlayManagerServiceImplTestsBase {
|
|||||||
assertEquals(expected, actual);
|
assertEquals(expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
DummyDeviceState.PackageBuilder target(String packageName) {
|
||||||
* Creates an overlay configured through {@link OverlayConfig}.
|
return new DummyDeviceState.PackageBuilder(packageName, null /* targetPackageName */,
|
||||||
*
|
null /* targetOverlayableName */);
|
||||||
* @throws IllegalStateException if the package is already installed
|
}
|
||||||
*/
|
|
||||||
void addOverlayPackage(String packageName, String targetPackageName, int userId,
|
DummyDeviceState.PackageBuilder overlay(String packageName, String targetPackageName) {
|
||||||
boolean mutable, boolean enabled, int priority) {
|
return overlay(packageName, targetPackageName, null /* targetOverlayableName */);
|
||||||
mState.addOverlay(packageName, targetPackageName, userId, mutable, enabled, priority);
|
}
|
||||||
|
|
||||||
|
DummyDeviceState.PackageBuilder overlay(String packageName, String targetPackageName,
|
||||||
|
String targetOverlayableName) {
|
||||||
|
return new DummyDeviceState.PackageBuilder(packageName, targetPackageName,
|
||||||
|
targetOverlayableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addSystemPackage(DummyDeviceState.PackageBuilder pkg, int userId) {
|
||||||
|
mState.add(pkg, userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void configureSystemOverlay(String packageName, boolean mutable, boolean enabled,
|
||||||
|
int priority) {
|
||||||
|
when(mOverlayConfig.getPriority(packageName)).thenReturn(priority);
|
||||||
|
when(mOverlayConfig.isEnabled(packageName)).thenReturn(enabled);
|
||||||
|
when(mOverlayConfig.isMutable(packageName)).thenReturn(mutable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the target package to the device.
|
* Adds the package to the device.
|
||||||
*
|
*
|
||||||
* This corresponds to when the OMS receives the
|
* This corresponds to when the OMS receives the
|
||||||
* {@link android.content.Intent#ACTION_PACKAGE_ADDED} broadcast.
|
* {@link android.content.Intent#ACTION_PACKAGE_ADDED} broadcast.
|
||||||
*
|
*
|
||||||
* @throws IllegalStateException if the package is not currently installed
|
* @throws IllegalStateException if the package is currently installed
|
||||||
*/
|
*/
|
||||||
void installTargetPackage(String packageName, int userId) {
|
void installNewPackage(DummyDeviceState.PackageBuilder pkg, int userId) {
|
||||||
if (mState.select(packageName, userId) != null) {
|
if (mState.select(pkg.packageName, userId) != null) {
|
||||||
throw new IllegalStateException("package already installed");
|
throw new IllegalStateException("package " + pkg.packageName + " already installed");
|
||||||
|
}
|
||||||
|
mState.add(pkg, userId);
|
||||||
|
if (pkg.targetPackage == null) {
|
||||||
|
mImpl.onTargetPackageAdded(pkg.packageName, userId);
|
||||||
|
} else {
|
||||||
|
mImpl.onOverlayPackageAdded(pkg.packageName, userId);
|
||||||
}
|
}
|
||||||
mState.addTarget(packageName, userId);
|
|
||||||
mImpl.onTargetPackageAdded(packageName, userId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begins upgrading the target package.
|
* Begins upgrading the package.
|
||||||
*
|
*
|
||||||
* This corresponds to when the OMS receives the
|
* This corresponds to when the OMS receives the
|
||||||
* {@link android.content.Intent#ACTION_PACKAGE_REMOVED} broadcast with the
|
* {@link android.content.Intent#ACTION_PACKAGE_REMOVED} broadcast with the
|
||||||
* {@link android.content.Intent#EXTRA_REPLACING} extra.
|
* {@link android.content.Intent#EXTRA_REPLACING} extra and then receives the
|
||||||
*
|
|
||||||
* @throws IllegalStateException if the package is not currently installed
|
|
||||||
*/
|
|
||||||
void beginUpgradeTargetPackage(String packageName, int userId) {
|
|
||||||
if (mState.select(packageName, userId) == null) {
|
|
||||||
throw new IllegalStateException("package not installed");
|
|
||||||
}
|
|
||||||
mImpl.onTargetPackageReplacing(packageName, userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ends upgrading the target package.
|
|
||||||
*
|
|
||||||
* This corresponds to when the OMS receives the
|
|
||||||
* {@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.
|
||||||
*
|
*
|
||||||
* @throws IllegalStateException if the package is not currently installed
|
* @throws IllegalStateException if the package is not currently installed
|
||||||
*/
|
*/
|
||||||
void endUpgradeTargetPackage(String packageName, int userId) {
|
void upgradePackage(DummyDeviceState.PackageBuilder pkg, int userId) {
|
||||||
if (mState.select(packageName, userId) == null) {
|
final DummyDeviceState.Package replacedPackage = mState.select(pkg.packageName, userId);
|
||||||
throw new IllegalStateException("package not installed");
|
if (replacedPackage == null) {
|
||||||
|
throw new IllegalStateException("package " + pkg.packageName + " not installed");
|
||||||
|
}
|
||||||
|
if (replacedPackage.targetPackageName != null) {
|
||||||
|
mImpl.onOverlayPackageReplacing(pkg.packageName, userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
mState.add(pkg, userId);
|
||||||
|
if (pkg.targetPackage == null) {
|
||||||
|
mImpl.onTargetPackageReplaced(pkg.packageName, userId);
|
||||||
|
} else {
|
||||||
|
mImpl.onOverlayPackageReplaced(pkg.packageName, userId);
|
||||||
}
|
}
|
||||||
mState.addTarget(packageName, userId);
|
|
||||||
mImpl.onTargetPackageReplaced(packageName, userId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the target package from the device.
|
* Removes the package from the device.
|
||||||
*
|
*
|
||||||
* This corresponds to when the OMS receives the
|
* This corresponds to when the OMS receives the
|
||||||
* {@link android.content.Intent#ACTION_PACKAGE_REMOVED} broadcast.
|
* {@link android.content.Intent#ACTION_PACKAGE_REMOVED} broadcast.
|
||||||
*
|
*
|
||||||
* @throws IllegalStateException if the package is not currently installed
|
* @throws IllegalStateException if the package is not currently installed
|
||||||
*/
|
*/
|
||||||
void uninstallTargetPackage(String packageName, int userId) {
|
void uninstallPackage(String packageName, int userId) {
|
||||||
if (mState.select(packageName, userId) == null) {
|
final DummyDeviceState.Package pkg = mState.select(packageName, userId);
|
||||||
throw new IllegalStateException("package not installed");
|
if (pkg == null) {
|
||||||
}
|
throw new IllegalStateException("package " + packageName+ " not installed");
|
||||||
mState.remove(packageName, userId);
|
|
||||||
mImpl.onTargetPackageRemoved(packageName, userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the overlay package to the device.
|
|
||||||
*
|
|
||||||
* This corresponds to when the OMS receives the
|
|
||||||
* {@link android.content.Intent#ACTION_PACKAGE_ADDED} broadcast.
|
|
||||||
*
|
|
||||||
* @throws IllegalStateException if the package is already installed
|
|
||||||
*/
|
|
||||||
void installOverlayPackage(String packageName, String targetPackageName, int userId) {
|
|
||||||
if (mState.select(packageName, userId) != null) {
|
|
||||||
throw new IllegalStateException("package already installed");
|
|
||||||
}
|
|
||||||
mState.addOverlay(packageName, targetPackageName, userId);
|
|
||||||
mImpl.onOverlayPackageAdded(packageName, userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Begins upgrading the overlay package.
|
|
||||||
*
|
|
||||||
* This corresponds to when the OMS receives the
|
|
||||||
* {@link android.content.Intent#ACTION_PACKAGE_REMOVED} broadcast with the
|
|
||||||
* {@link android.content.Intent#EXTRA_REPLACING} extra.
|
|
||||||
*
|
|
||||||
* @throws IllegalStateException if the package is not currently installed
|
|
||||||
*/
|
|
||||||
void beginUpgradeOverlayPackage(String packageName, int userId) {
|
|
||||||
if (mState.select(packageName, userId) == null) {
|
|
||||||
throw new IllegalStateException("package not installed, cannot upgrade");
|
|
||||||
}
|
|
||||||
|
|
||||||
mImpl.onOverlayPackageReplacing(packageName, userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ends upgrading the overlay package, potentially changing its target package.
|
|
||||||
*
|
|
||||||
* This corresponds to when the OMS receives the
|
|
||||||
* {@link android.content.Intent#ACTION_PACKAGE_ADDED} broadcast with the
|
|
||||||
* {@link android.content.Intent#EXTRA_REPLACING} extra.
|
|
||||||
*
|
|
||||||
* @throws IllegalStateException if the package is not currently installed
|
|
||||||
*/
|
|
||||||
void endUpgradeOverlayPackage(String packageName, String targetPackageName, int userId) {
|
|
||||||
if (mState.select(packageName, userId) == null) {
|
|
||||||
throw new IllegalStateException("package not installed, cannot upgrade");
|
|
||||||
}
|
|
||||||
|
|
||||||
mState.addOverlay(packageName, targetPackageName, userId);
|
|
||||||
mImpl.onOverlayPackageReplaced(packageName, userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class DummyDeviceState {
|
|
||||||
private List<Package> mPackages = new ArrayList<>();
|
|
||||||
private OverlayConfig mOverlayConfig = mock(OverlayConfig.class);
|
|
||||||
|
|
||||||
/** Adds a non-overlay to the device. */
|
|
||||||
public void addTarget(String packageName, int userId) {
|
|
||||||
remove(packageName, userId);
|
|
||||||
mPackages.add(new Package(packageName, userId, null, false, false, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Adds an overlay to the device. */
|
|
||||||
public void addOverlay(String packageName, String targetPackageName, int userId) {
|
|
||||||
addOverlay(packageName, targetPackageName, userId, true, false, OverlayConfig.DEFAULT_PRIORITY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Adds a configured overlay to the device. */
|
|
||||||
public void addOverlay(String packageName, String targetPackageName, int userId,
|
|
||||||
boolean mutable, boolean enabled, int priority) {
|
|
||||||
remove(packageName, userId);
|
|
||||||
mPackages.add(new Package(packageName, userId, targetPackageName, mutable, enabled,
|
|
||||||
priority));
|
|
||||||
when(mOverlayConfig.getPriority(packageName)).thenReturn(priority);
|
|
||||||
when(mOverlayConfig.isEnabled(packageName)).thenReturn(enabled);
|
|
||||||
when(mOverlayConfig.isMutable(packageName)).thenReturn(mutable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Remove a package from the device. */
|
|
||||||
public void remove(String packageName, int userId) {
|
|
||||||
final Iterator<Package> iter = mPackages.iterator();
|
|
||||||
while (iter.hasNext()) {
|
|
||||||
final Package pkg = iter.next();
|
|
||||||
if (pkg.packageName.equals(packageName) && pkg.userId == userId) {
|
|
||||||
iter.remove();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
mState.remove(pkg.packageName);
|
||||||
|
if (pkg.targetPackageName == null) {
|
||||||
|
mImpl.onTargetPackageRemoved(pkg.packageName, userId);
|
||||||
|
} else {
|
||||||
|
mImpl.onOverlayPackageRemoved(pkg.packageName, userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Retrieves all packages on device for a particular user. */
|
/** Represents the state of packages installed on a fake device. */
|
||||||
public List<Package> select(int userId) {
|
static class DummyDeviceState {
|
||||||
return mPackages.stream().filter(p -> p.userId == userId).collect(Collectors.toList());
|
private ArrayMap<String, Package> mPackages = new ArrayMap<>();
|
||||||
|
|
||||||
|
void add(PackageBuilder pkgBuilder, int userId) {
|
||||||
|
final Package pkg = pkgBuilder.build();
|
||||||
|
final Package previousPkg = select(pkg.packageName, userId);
|
||||||
|
mPackages.put(pkg.packageName, pkg);
|
||||||
|
|
||||||
|
pkg.installedUserIds.add(userId);
|
||||||
|
if (previousPkg != null) {
|
||||||
|
pkg.installedUserIds.addAll(previousPkg.installedUserIds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Retrieves the package with the specified package name for a particular user. */
|
void remove(String packageName) {
|
||||||
public Package select(String packageName, int userId) {
|
mPackages.remove(packageName);
|
||||||
return mPackages.stream().filter(
|
|
||||||
p -> p.packageName.equals(packageName) && p.userId == userId)
|
|
||||||
.findFirst().orElse(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class Package {
|
void uninstall(String packageName, int userId) {
|
||||||
public final String packageName;
|
final Package pkg = mPackages.get(packageName);
|
||||||
public final int userId;
|
if (pkg != null) {
|
||||||
public final String targetPackageName;
|
pkg.installedUserIds.remove(userId);
|
||||||
public final boolean mutable;
|
}
|
||||||
public final boolean enabled;
|
}
|
||||||
public final int priority;
|
|
||||||
|
|
||||||
private Package(String packageName, int userId, String targetPackageName,
|
List<Package> select(int userId) {
|
||||||
boolean mutable, boolean enabled, int priority) {
|
return mPackages.values().stream().filter(p -> p.installedUserIds.contains(userId))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
Package select(String packageName, int userId) {
|
||||||
|
final Package pkg = mPackages.get(packageName);
|
||||||
|
return pkg != null && pkg.installedUserIds.contains(userId) ? pkg : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Package selectFromPath(String path) {
|
||||||
|
return mPackages.values().stream()
|
||||||
|
.filter(p -> p.apkPath.equals(path)).findFirst().orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class PackageBuilder {
|
||||||
|
private String packageName;
|
||||||
|
private String targetPackage;
|
||||||
|
private String certificate = "[default]";
|
||||||
|
private int version = 0;
|
||||||
|
private ArrayList<String> overlayableNames = new ArrayList<>();
|
||||||
|
private String targetOverlayableName;
|
||||||
|
|
||||||
|
private PackageBuilder(String packageName, String targetPackage,
|
||||||
|
String targetOverlayableName) {
|
||||||
|
this.packageName = packageName;
|
||||||
|
this.targetPackage = targetPackage;
|
||||||
|
this.targetOverlayableName = targetOverlayableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
PackageBuilder setCertificate(String certificate) {
|
||||||
|
this.certificate = certificate;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
PackageBuilder addOverlayable(String overlayableName) {
|
||||||
|
overlayableNames.add(overlayableName);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
PackageBuilder setVersion(int version) {
|
||||||
|
this.version = version;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Package build() {
|
||||||
|
final String apkPath = String.format("%s/%s/base.apk",
|
||||||
|
targetPackage == null ? "/system/app/:" : "/vendor/overlay/:",
|
||||||
|
packageName);
|
||||||
|
final Package newPackage = new Package(packageName, targetPackage,
|
||||||
|
targetOverlayableName, version, apkPath, certificate);
|
||||||
|
newPackage.overlayableNames.addAll(overlayableNames);
|
||||||
|
return newPackage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class Package {
|
||||||
|
final String packageName;
|
||||||
|
final String targetPackageName;
|
||||||
|
final String targetOverlayableName;
|
||||||
|
final int versionCode;
|
||||||
|
final String apkPath;
|
||||||
|
final String certificate;
|
||||||
|
final ArrayList<String> overlayableNames = new ArrayList<>();
|
||||||
|
private final ArraySet<Integer> installedUserIds = new ArraySet<>();
|
||||||
|
|
||||||
|
private Package(String packageName, String targetPackageName,
|
||||||
|
String targetOverlayableName, int versionCode, String apkPath,
|
||||||
|
String certificate) {
|
||||||
this.packageName = packageName;
|
this.packageName = packageName;
|
||||||
this.userId = userId;
|
|
||||||
this.targetPackageName = targetPackageName;
|
this.targetPackageName = targetPackageName;
|
||||||
this.mutable = mutable;
|
this.targetOverlayableName = targetOverlayableName;
|
||||||
this.enabled = enabled;
|
this.versionCode = versionCode;
|
||||||
this.priority = priority;
|
this.apkPath = apkPath;
|
||||||
|
this.certificate = certificate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -288,6 +314,8 @@ class OverlayManagerServiceImplTestsBase {
|
|||||||
static final class DummyPackageManagerHelper implements PackageManagerHelper,
|
static final class DummyPackageManagerHelper implements PackageManagerHelper,
|
||||||
OverlayableInfoCallback {
|
OverlayableInfoCallback {
|
||||||
private final DummyDeviceState mState;
|
private final DummyDeviceState mState;
|
||||||
|
String[] overlayableConfiguratorTargets = new String[0];
|
||||||
|
String overlayableConfigurator = "";
|
||||||
|
|
||||||
private DummyPackageManagerHelper(DummyDeviceState state) {
|
private DummyPackageManagerHelper(DummyDeviceState state) {
|
||||||
mState = state;
|
mState = state;
|
||||||
@@ -300,13 +328,12 @@ class OverlayManagerServiceImplTestsBase {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final ApplicationInfo ai = new ApplicationInfo();
|
final ApplicationInfo ai = new ApplicationInfo();
|
||||||
ai.sourceDir = String.format("%s/%s/base.apk",
|
ai.sourceDir = pkg.apkPath;
|
||||||
pkg.targetPackageName == null ? "/system/app/" : "/vendor/overlay/",
|
|
||||||
pkg.packageName);
|
|
||||||
PackageInfo pi = new PackageInfo();
|
PackageInfo pi = new PackageInfo();
|
||||||
pi.applicationInfo = ai;
|
pi.applicationInfo = ai;
|
||||||
pi.packageName = pkg.packageName;
|
pi.packageName = pkg.packageName;
|
||||||
pi.overlayTarget = pkg.targetPackageName;
|
pi.overlayTarget = pkg.targetPackageName;
|
||||||
|
pi.targetOverlayableName = pkg.targetOverlayableName;
|
||||||
pi.overlayCategory = "dummy-category-" + pkg.targetPackageName;
|
pi.overlayCategory = "dummy-category-" + pkg.targetPackageName;
|
||||||
return pi;
|
return pi;
|
||||||
}
|
}
|
||||||
@@ -314,14 +341,16 @@ class OverlayManagerServiceImplTestsBase {
|
|||||||
@Override
|
@Override
|
||||||
public boolean signaturesMatching(@NonNull String packageName1,
|
public boolean signaturesMatching(@NonNull String packageName1,
|
||||||
@NonNull String packageName2, int userId) {
|
@NonNull String packageName2, int userId) {
|
||||||
return false;
|
final DummyDeviceState.Package pkg1 = mState.select(packageName1, userId);
|
||||||
|
final DummyDeviceState.Package pkg2 = mState.select(packageName2, userId);
|
||||||
|
return pkg1 != null && pkg2 != null && pkg1.certificate.equals(pkg2.certificate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<PackageInfo> getOverlayPackages(int userId) {
|
public List<PackageInfo> getOverlayPackages(int userId) {
|
||||||
return mState.select(userId).stream()
|
return mState.select(userId).stream()
|
||||||
.filter(p -> p.targetPackageName != null)
|
.filter(p -> p.targetPackageName != null)
|
||||||
.map(p -> getPackageInfo(p.packageName, p.userId))
|
.map(p -> getPackageInfo(p.packageName, userId))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,7 +358,11 @@ class OverlayManagerServiceImplTestsBase {
|
|||||||
@Override
|
@Override
|
||||||
public OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
|
public OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
|
||||||
@NonNull String targetOverlayableName, int userId) {
|
@NonNull String targetOverlayableName, int userId) {
|
||||||
throw new UnsupportedOperationException();
|
final DummyDeviceState.Package pkg = mState.select(packageName, userId);
|
||||||
|
if (pkg == null || !pkg.overlayableNames.contains(targetOverlayableName)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new OverlayableInfo(targetOverlayableName, null /* actor */);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -341,69 +374,98 @@ class OverlayManagerServiceImplTestsBase {
|
|||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Map<String, String>> getNamedActors() {
|
public Map<String, Map<String, String>> getNamedActors() {
|
||||||
throw new UnsupportedOperationException();
|
return Collections.emptyMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean doesTargetDefineOverlayable(String targetPackageName, int userId) {
|
public boolean doesTargetDefineOverlayable(String targetPackageName, int userId) {
|
||||||
throw new UnsupportedOperationException();
|
final DummyDeviceState.Package pkg = mState.select(targetPackageName, userId);
|
||||||
|
return pkg != null && pkg.overlayableNames.contains(targetPackageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void enforcePermission(String permission, String message) throws SecurityException {
|
public void enforcePermission(String permission, String message) throws SecurityException {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getOverlayableConfiguratorTargets() {
|
||||||
|
return overlayableConfiguratorTargets;
|
||||||
}
|
}
|
||||||
|
|
||||||
static class DummyIdmapManager extends IdmapManager {
|
@Override
|
||||||
|
public String getOverlayableConfigurator() {
|
||||||
|
return overlayableConfigurator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class DummyIdmapDaemon extends IdmapDaemon {
|
||||||
private final DummyDeviceState mState;
|
private final DummyDeviceState mState;
|
||||||
private Set<String> mIdmapFiles = new ArraySet<>();
|
private final ArrayMap<String, IdmapHeader> mIdmapFiles = new ArrayMap<>();
|
||||||
|
|
||||||
private DummyIdmapManager(DummyDeviceState state,
|
DummyIdmapDaemon(DummyDeviceState state) {
|
||||||
DummyPackageManagerHelper packageManagerHelper) {
|
this.mState = state;
|
||||||
super(packageManagerHelper);
|
}
|
||||||
mState = state;
|
|
||||||
|
private int getCrc(@NonNull final String path) {
|
||||||
|
final DummyDeviceState.Package pkg = mState.selectFromPath(path);
|
||||||
|
Assert.assertNotNull(pkg);
|
||||||
|
return pkg.versionCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
boolean createIdmap(@NonNull final PackageInfo targetPackage,
|
String createIdmap(String targetPath, String overlayPath, int policies, boolean enforce,
|
||||||
@NonNull final PackageInfo overlayPackage, int userId) {
|
int userId) {
|
||||||
final DummyDeviceState.Package t = mState.select(targetPackage.packageName, userId);
|
mIdmapFiles.put(overlayPath, new IdmapHeader(getCrc(targetPath),
|
||||||
if (t == null) {
|
getCrc(overlayPath), targetPath, policies, enforce));
|
||||||
|
return overlayPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean removeIdmap(String overlayPath, int userId) {
|
||||||
|
return mIdmapFiles.remove(overlayPath) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean verifyIdmap(String targetPath, String overlayPath, int policies, boolean enforce,
|
||||||
|
int userId) {
|
||||||
|
final IdmapHeader idmap = mIdmapFiles.get(overlayPath);
|
||||||
|
if (idmap == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final DummyDeviceState.Package o = mState.select(overlayPackage.packageName, userId);
|
return idmap.isUpToDate(getCrc(targetPath), getCrc(overlayPath), targetPath);
|
||||||
if (o == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final String key = createKey(overlayPackage.packageName, userId);
|
|
||||||
return mIdmapFiles.add(key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
boolean removeIdmap(@NonNull final OverlayInfo oi, final int userId) {
|
boolean idmapExists(String overlayPath, int userId) {
|
||||||
final String key = createKey(oi.packageName, oi.userId);
|
return mIdmapFiles.containsKey(overlayPath);
|
||||||
if (!mIdmapFiles.contains(key)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
mIdmapFiles.remove(key);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
IdmapHeader getIdmap(String overlayPath) {
|
||||||
boolean idmapExists(@NonNull final OverlayInfo oi) {
|
return mIdmapFiles.get(overlayPath);
|
||||||
final String key = createKey(oi.packageName, oi.userId);
|
|
||||||
return mIdmapFiles.contains(key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
static class IdmapHeader {
|
||||||
boolean idmapExists(@NonNull final PackageInfo overlayPackage, final int userId) {
|
private final int targetCrc;
|
||||||
final String key = createKey(overlayPackage.packageName, userId);
|
private final int overlayCrc;
|
||||||
return mIdmapFiles.contains(key);
|
final String targetPath;
|
||||||
|
final int policies;
|
||||||
|
final boolean enforceOverlayable;
|
||||||
|
|
||||||
|
private IdmapHeader(int targetCrc, int overlayCrc, String targetPath, int policies,
|
||||||
|
boolean enforceOverlayable) {
|
||||||
|
this.targetCrc = targetCrc;
|
||||||
|
this.overlayCrc = overlayCrc;
|
||||||
|
this.targetPath = targetPath;
|
||||||
|
this.policies = policies;
|
||||||
|
this.enforceOverlayable = enforceOverlayable;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createKey(@NonNull final String packageName, final int userId) {
|
private boolean isUpToDate(int expectedTargetCrc, int expectedOverlayCrc,
|
||||||
return String.format("%s:%d", packageName, userId);
|
String expectedTargetPath) {
|
||||||
|
return expectedTargetCrc == targetCrc && expectedOverlayCrc == overlayCrc
|
||||||
|
&& expectedTargetPath.equals(targetPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user