diff options
3 files changed, 95 insertions, 43 deletions
diff --git a/services/core/java/com/android/server/om/OverlayReferenceMapper.java b/services/core/java/com/android/server/om/OverlayReferenceMapper.java index f8ae99aa2e3e..fdceabe74dd8 100644 --- a/services/core/java/com/android/server/om/OverlayReferenceMapper.java +++ b/services/core/java/com/android/server/om/OverlayReferenceMapper.java @@ -26,10 +26,13 @@ import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.CollectionUtils; import com.android.server.SystemConfig; import com.android.server.pm.pkg.AndroidPackage; import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -118,16 +121,20 @@ public class OverlayReferenceMapper { return actorPair.first; } - @Nullable + @NonNull @Override - public Pair<String, String> getTargetToOverlayables(@NonNull AndroidPackage pkg) { + public Map<String, Set<String>> getTargetToOverlayables(@NonNull AndroidPackage pkg) { String target = pkg.getOverlayTarget(); if (TextUtils.isEmpty(target)) { - return null; + return Collections.emptyMap(); } String overlayable = pkg.getOverlayTargetOverlayableName(); - return Pair.create(target, overlayable); + Map<String, Set<String>> targetToOverlayables = new HashMap<>(); + Set<String> overlayables = new HashSet<>(); + overlayables.add(overlayable); + targetToOverlayables.put(target, overlayables); + return targetToOverlayables; } }; } @@ -167,7 +174,7 @@ public class OverlayReferenceMapper { } // TODO(b/135203078): Replace with isOverlay boolean flag check; fix test mocks - if (mProvider.getTargetToOverlayables(pkg) != null) { + if (!mProvider.getTargetToOverlayables(pkg).isEmpty()) { addOverlay(pkg, otherPkgs, changed); } @@ -238,17 +245,20 @@ public class OverlayReferenceMapper { String target = targetPkg.getPackageName(); removeTarget(target, changedPackages); - final Map<String, String> overlayablesToActors = targetPkg.getOverlayables(); - for (final var entry : overlayablesToActors.entrySet()) { - final String overlayable = entry.getKey(); - final String actor = entry.getValue(); + Map<String, String> overlayablesToActors = targetPkg.getOverlayables(); + for (String overlayable : overlayablesToActors.keySet()) { + String actor = overlayablesToActors.get(overlayable); addTargetToMap(actor, target, changedPackages); for (AndroidPackage overlayPkg : otherPkgs.values()) { - var targetToOverlayables = + Map<String, Set<String>> targetToOverlayables = mProvider.getTargetToOverlayables(overlayPkg); - if (targetToOverlayables != null && targetToOverlayables.first.equals(target) - && targetToOverlayables.second.equals(overlayable)) { + Set<String> overlayables = targetToOverlayables.get(target); + if (CollectionUtils.isEmpty(overlayables)) { + continue; + } + + if (overlayables.contains(overlayable)) { String overlay = overlayPkg.getPackageName(); addOverlayToMap(actor, target, overlay, changedPackages); } @@ -300,22 +310,25 @@ public class OverlayReferenceMapper { String overlay = overlayPkg.getPackageName(); removeOverlay(overlay, changedPackages); - Pair<String, String> targetToOverlayables = + Map<String, Set<String>> targetToOverlayables = mProvider.getTargetToOverlayables(overlayPkg); - if (targetToOverlayables != null) { - String target = targetToOverlayables.first; + for (Map.Entry<String, Set<String>> entry : targetToOverlayables.entrySet()) { + String target = entry.getKey(); + Set<String> overlayables = entry.getValue(); AndroidPackage targetPkg = otherPkgs.get(target); if (targetPkg == null) { - return; + continue; } + String targetPkgName = targetPkg.getPackageName(); Map<String, String> overlayableToActor = targetPkg.getOverlayables(); - String overlayable = targetToOverlayables.second; - String actor = overlayableToActor.get(overlayable); - if (TextUtils.isEmpty(actor)) { - return; + for (String overlayable : overlayables) { + String actor = overlayableToActor.get(overlayable); + if (TextUtils.isEmpty(actor)) { + continue; + } + addOverlayToMap(actor, targetPkgName, overlay, changedPackages); } - addOverlayToMap(actor, targetPkgName, overlay, changedPackages); } } } @@ -417,11 +430,11 @@ public class OverlayReferenceMapper { String getActorPkg(@NonNull String actor); /** - * Mock response of overlay tags. + * Mock response of multiple overlay tags. * * TODO(b/119899133): Replace with actual implementation; fix OverlayReferenceMapperTests */ - @Nullable - Pair<String, String> getTargetToOverlayables(@NonNull AndroidPackage pkg); + @NonNull + Map<String, Set<String>> getTargetToOverlayables(@NonNull AndroidPackage pkg); } } diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java index 66aaa562b873..7277fd79fdd5 100644 --- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java +++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java @@ -45,7 +45,6 @@ import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import android.util.ArrayMap; import android.util.ArraySet; -import android.util.Pair; import android.util.SparseArray; import androidx.annotation.NonNull; @@ -79,7 +78,10 @@ import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.Set; @Presubmit @RunWith(JUnit4.class) @@ -883,15 +885,18 @@ public class AppsFilterImplTest { return null; } - @Nullable + @NonNull @Override - public Pair<String, String> getTargetToOverlayables( + public Map<String, Set<String>> getTargetToOverlayables( @NonNull AndroidPackage pkg) { if (overlay.getPackageName().equals(pkg.getPackageName())) { - return Pair.create(overlay.getOverlayTarget(), - overlay.getOverlayTargetOverlayableName()); + Map<String, Set<String>> map = new ArrayMap<>(); + Set<String> set = new ArraySet<>(); + set.add(overlay.getOverlayTargetOverlayableName()); + map.put(overlay.getOverlayTarget(), set); + return map; } - return null; + return Collections.emptyMap(); } }, mMockHandler); @@ -972,15 +977,18 @@ public class AppsFilterImplTest { return null; } - @Nullable + @NonNull @Override - public Pair<String, String> getTargetToOverlayables( + public Map<String, Set<String>> getTargetToOverlayables( @NonNull AndroidPackage pkg) { if (overlay.getPackageName().equals(pkg.getPackageName())) { - return Pair.create(overlay.getOverlayTarget(), - overlay.getOverlayTargetOverlayableName()); + Map<String, Set<String>> map = new ArrayMap<>(); + Set<String> set = new ArraySet<>(); + set.add(overlay.getOverlayTargetOverlayableName()); + map.put(overlay.getOverlayTarget(), set); + return map; } - return null; + return Collections.emptyMap(); } }, mMockHandler); diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt b/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt index bc10cd6bf1c9..1352adef783f 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt +++ b/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt @@ -76,10 +76,12 @@ class OverlayReferenceMapperTests { val overlay1 = mockOverlay(1) mapper = mapper( overlayToTargetToOverlayables = mapOf( - overlay0.packageName to android.util.Pair(target.packageName, - target.overlayables.keys.first()), - overlay1.packageName to android.util.Pair(target.packageName, - target.overlayables.keys.first()) + overlay0.packageName to mapOf( + target.packageName to target.overlayables.keys + ), + overlay1.packageName to mapOf( + target.packageName to target.overlayables.keys + ) ) ) val existing = mapper.addInOrder(overlay0, overlay1) { @@ -132,6 +134,33 @@ class OverlayReferenceMapperTests { } @Test + fun overlayWithMultipleTargets() { + val target0 = mockTarget(0) + val target1 = mockTarget(1) + val overlay = mockOverlay() + mapper = mapper( + overlayToTargetToOverlayables = mapOf( + overlay.packageName to mapOf( + target0.packageName to target0.overlayables.keys, + target1.packageName to target1.overlayables.keys + ) + ) + ) + mapper.addInOrder(target0, target1, overlay) { + assertThat(it).containsExactly(ACTOR_PACKAGE_NAME) + } + assertMapping(ACTOR_PACKAGE_NAME to setOf(target0, target1, overlay)) + mapper.remove(target0) { + assertThat(it).containsExactly(ACTOR_PACKAGE_NAME) + } + assertMapping(ACTOR_PACKAGE_NAME to setOf(target1, overlay)) + mapper.remove(target1) { + assertThat(it).containsExactly(ACTOR_PACKAGE_NAME) + } + assertEmpty() + } + + @Test fun overlayWithoutTarget() { val overlay = mockOverlay() mapper.addInOrder(overlay) { @@ -190,15 +219,17 @@ class OverlayReferenceMapperTests { namedActors: Map<String, Map<String, String>> = Uri.parse(ACTOR_NAME).run { mapOf(authority!! to mapOf(pathSegments.first() to ACTOR_PACKAGE_NAME)) }, - overlayToTargetToOverlayables: Map<String, android.util.Pair<String, String>> = mapOf( - mockOverlay().packageName to mockTarget().run { android.util.Pair(packageName!!, - overlayables.keys.first()) }) + overlayToTargetToOverlayables: Map<String, Map<String, Set<String>>> = mapOf( + mockOverlay().packageName to mapOf( + mockTarget().run { packageName to overlayables.keys } + ) + ) ) = OverlayReferenceMapper(deferRebuild, object : OverlayReferenceMapper.Provider { override fun getActorPkg(actor: String) = OverlayActorEnforcer.getPackageNameForActor(actor, namedActors).first override fun getTargetToOverlayables(pkg: AndroidPackage) = - overlayToTargetToOverlayables[pkg.packageName] + overlayToTargetToOverlayables[pkg.packageName] ?: emptyMap() }) private fun mockTarget(increment: Int = 0) = mockThrowOnUnmocked<AndroidPackage> { |