Loading services/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ package com.android.server.pm { method public void close(); method public void forAllPackageStates(@NonNull java.util.function.Consumer<com.android.server.pm.pkg.PackageState>); method @Nullable public com.android.server.pm.pkg.PackageState getPackageState(@NonNull String); method @NonNull public java.util.Map<java.lang.String,com.android.server.pm.pkg.PackageState> getPackageStates(); } public static interface PackageManagerLocal.UnfilteredSnapshot extends java.lang.AutoCloseable { Loading services/core/java/com/android/server/pm/PackageManagerLocal.java +7 −5 Original line number Diff line number Diff line Loading @@ -167,14 +167,16 @@ public interface PackageManagerLocal { PackageState getPackageState(@NonNull String packageName); /** * Iterates on all states. This should only be used when either the target package name * is not known or the large majority of the states are expected to be used. * * Returns a map of all {@link PackageState PackageStates} on the device. * <p> * This will cause app visibility filtering to be invoked on each state on the device, * which can be expensive. * which can be expensive. Prefer {@link #getPackageState(String)} if possible. * * @param consumer Block to accept each state as it becomes available post-filtering. * @return Mapping of package name to {@link PackageState}. */ @NonNull Map<String, PackageState> getPackageStates(); void forAllPackageStates(@NonNull Consumer<PackageState> consumer); @Override Loading services/core/java/com/android/server/pm/local/PackageManagerLocalImpl.java +20 −9 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.annotation.Nullable; import android.annotation.UserIdInt; import android.os.Binder; import android.os.UserHandle; import android.util.ArrayMap; import com.android.server.pm.Computer; import com.android.server.pm.PackageManagerLocal; Loading @@ -30,7 +31,6 @@ import com.android.server.pm.pkg.PackageState; import com.android.server.pm.snapshot.PackageDataSnapshot; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; Loading Loading @@ -143,7 +143,7 @@ public class PackageManagerLocalImpl implements PackageManagerLocal { private final int mUserId; @Nullable private ArrayList<PackageState> mFilteredPackageStates; private Map<String, PackageState> mFilteredPackageStates; @Nullable private final UnfilteredSnapshotImpl mParentSnapshot; Loading Loading @@ -179,26 +179,37 @@ public class PackageManagerLocalImpl implements PackageManagerLocal { return mSnapshot.getPackageStateFiltered(packageName, mCallingUid, mUserId); } @NonNull @Override public void forAllPackageStates(@NonNull Consumer<PackageState> consumer) { public Map<String, PackageState> getPackageStates() { checkClosed(); if (mFilteredPackageStates == null) { var packageStates = mSnapshot.getPackageStates(); var filteredPackageStates = new ArrayList<PackageState>(); var filteredPackageStates = new ArrayMap<String, PackageState>(); for (int index = 0, size = packageStates.size(); index < size; index++) { var packageState = packageStates.valueAt(index); if (!mSnapshot.shouldFilterApplication(packageState, mCallingUid, mUserId)) { filteredPackageStates.add(packageState); filteredPackageStates.put(packageStates.keyAt(index), packageState); } } mFilteredPackageStates = filteredPackageStates; mFilteredPackageStates = Collections.unmodifiableMap(filteredPackageStates); } for (int index = 0, size = mFilteredPackageStates.size(); index < size; index++) { var packageState = mFilteredPackageStates.get(index); return mFilteredPackageStates; } @Override public void forAllPackageStates(@NonNull Consumer<PackageState> consumer) { checkClosed(); var packageStates = mSnapshot.getPackageStates(); for (int index = 0, size = packageStates.size(); index < size; index++) { var packageState = packageStates.valueAt(index); if (!mSnapshot.shouldFilterApplication(packageState, mCallingUid, mUserId)) { consumer.accept(packageState); } } } } } services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/PackageManagerLocalSnapshotTest.kt +23 −7 Original line number Diff line number Diff line Loading @@ -53,6 +53,11 @@ class PackageManagerLocalSnapshotTest { snapshot.use { val packageStates = it.packageStates // Check for unmodifiable assertFailsWith(UnsupportedOperationException::class) { it.packageStates.clear() } // Check contents assertThat(packageStates).containsExactly( packageStateAll.packageName, packageStateAll, Loading @@ -78,9 +83,14 @@ class PackageManagerLocalSnapshotTest { assertThat(filteredOne.getPackageState(packageStateUser10.packageName)).isNull() filteredThree.use { val statesList = mutableListOf<PackageState>() assertThat(it.forAllPackageStates { statesList += it }) assertThat(statesList).containsExactly(packageStateAll, packageStateUser10) // Check for unmodifiable assertFailsWith(UnsupportedOperationException::class) { it.packageStates.clear() } assertThat(it.packageStates).containsExactly( packageStateAll.packageName, packageStateAll, packageStateUser10.packageName, packageStateUser10, ) } // Call after child close, parent open fails Loading @@ -96,7 +106,7 @@ class PackageManagerLocalSnapshotTest { // Call after close fails assertClosedFailure { snapshot.packageStates } assertClosedFailure { filteredOne.forAllPackageStates {} } assertClosedFailure { filteredOne.packageStates } assertClosedFailure { filteredTwo.getPackageState(packageStateAll.packageName) } Loading @@ -116,9 +126,15 @@ class PackageManagerLocalSnapshotTest { .isEqualTo(packageStateUser0) assertThat(it.getPackageState(packageStateUser10.packageName)).isNull() val statesList = mutableListOf<PackageState>() assertThat(it.forAllPackageStates { statesList += it }) assertThat(statesList).containsExactly(packageStateAll, packageStateUser0) // Check for unmodifiable assertFailsWith(UnsupportedOperationException::class) { it.packageStates.clear() } assertThat(it.packageStates).containsExactly( packageStateAll.packageName, packageStateAll, packageStateUser0.packageName, packageStateUser0, ) } // Call after close fails Loading Loading
services/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ package com.android.server.pm { method public void close(); method public void forAllPackageStates(@NonNull java.util.function.Consumer<com.android.server.pm.pkg.PackageState>); method @Nullable public com.android.server.pm.pkg.PackageState getPackageState(@NonNull String); method @NonNull public java.util.Map<java.lang.String,com.android.server.pm.pkg.PackageState> getPackageStates(); } public static interface PackageManagerLocal.UnfilteredSnapshot extends java.lang.AutoCloseable { Loading
services/core/java/com/android/server/pm/PackageManagerLocal.java +7 −5 Original line number Diff line number Diff line Loading @@ -167,14 +167,16 @@ public interface PackageManagerLocal { PackageState getPackageState(@NonNull String packageName); /** * Iterates on all states. This should only be used when either the target package name * is not known or the large majority of the states are expected to be used. * * Returns a map of all {@link PackageState PackageStates} on the device. * <p> * This will cause app visibility filtering to be invoked on each state on the device, * which can be expensive. * which can be expensive. Prefer {@link #getPackageState(String)} if possible. * * @param consumer Block to accept each state as it becomes available post-filtering. * @return Mapping of package name to {@link PackageState}. */ @NonNull Map<String, PackageState> getPackageStates(); void forAllPackageStates(@NonNull Consumer<PackageState> consumer); @Override Loading
services/core/java/com/android/server/pm/local/PackageManagerLocalImpl.java +20 −9 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.annotation.Nullable; import android.annotation.UserIdInt; import android.os.Binder; import android.os.UserHandle; import android.util.ArrayMap; import com.android.server.pm.Computer; import com.android.server.pm.PackageManagerLocal; Loading @@ -30,7 +31,6 @@ import com.android.server.pm.pkg.PackageState; import com.android.server.pm.snapshot.PackageDataSnapshot; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; Loading Loading @@ -143,7 +143,7 @@ public class PackageManagerLocalImpl implements PackageManagerLocal { private final int mUserId; @Nullable private ArrayList<PackageState> mFilteredPackageStates; private Map<String, PackageState> mFilteredPackageStates; @Nullable private final UnfilteredSnapshotImpl mParentSnapshot; Loading Loading @@ -179,26 +179,37 @@ public class PackageManagerLocalImpl implements PackageManagerLocal { return mSnapshot.getPackageStateFiltered(packageName, mCallingUid, mUserId); } @NonNull @Override public void forAllPackageStates(@NonNull Consumer<PackageState> consumer) { public Map<String, PackageState> getPackageStates() { checkClosed(); if (mFilteredPackageStates == null) { var packageStates = mSnapshot.getPackageStates(); var filteredPackageStates = new ArrayList<PackageState>(); var filteredPackageStates = new ArrayMap<String, PackageState>(); for (int index = 0, size = packageStates.size(); index < size; index++) { var packageState = packageStates.valueAt(index); if (!mSnapshot.shouldFilterApplication(packageState, mCallingUid, mUserId)) { filteredPackageStates.add(packageState); filteredPackageStates.put(packageStates.keyAt(index), packageState); } } mFilteredPackageStates = filteredPackageStates; mFilteredPackageStates = Collections.unmodifiableMap(filteredPackageStates); } for (int index = 0, size = mFilteredPackageStates.size(); index < size; index++) { var packageState = mFilteredPackageStates.get(index); return mFilteredPackageStates; } @Override public void forAllPackageStates(@NonNull Consumer<PackageState> consumer) { checkClosed(); var packageStates = mSnapshot.getPackageStates(); for (int index = 0, size = packageStates.size(); index < size; index++) { var packageState = packageStates.valueAt(index); if (!mSnapshot.shouldFilterApplication(packageState, mCallingUid, mUserId)) { consumer.accept(packageState); } } } } }
services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/PackageManagerLocalSnapshotTest.kt +23 −7 Original line number Diff line number Diff line Loading @@ -53,6 +53,11 @@ class PackageManagerLocalSnapshotTest { snapshot.use { val packageStates = it.packageStates // Check for unmodifiable assertFailsWith(UnsupportedOperationException::class) { it.packageStates.clear() } // Check contents assertThat(packageStates).containsExactly( packageStateAll.packageName, packageStateAll, Loading @@ -78,9 +83,14 @@ class PackageManagerLocalSnapshotTest { assertThat(filteredOne.getPackageState(packageStateUser10.packageName)).isNull() filteredThree.use { val statesList = mutableListOf<PackageState>() assertThat(it.forAllPackageStates { statesList += it }) assertThat(statesList).containsExactly(packageStateAll, packageStateUser10) // Check for unmodifiable assertFailsWith(UnsupportedOperationException::class) { it.packageStates.clear() } assertThat(it.packageStates).containsExactly( packageStateAll.packageName, packageStateAll, packageStateUser10.packageName, packageStateUser10, ) } // Call after child close, parent open fails Loading @@ -96,7 +106,7 @@ class PackageManagerLocalSnapshotTest { // Call after close fails assertClosedFailure { snapshot.packageStates } assertClosedFailure { filteredOne.forAllPackageStates {} } assertClosedFailure { filteredOne.packageStates } assertClosedFailure { filteredTwo.getPackageState(packageStateAll.packageName) } Loading @@ -116,9 +126,15 @@ class PackageManagerLocalSnapshotTest { .isEqualTo(packageStateUser0) assertThat(it.getPackageState(packageStateUser10.packageName)).isNull() val statesList = mutableListOf<PackageState>() assertThat(it.forAllPackageStates { statesList += it }) assertThat(statesList).containsExactly(packageStateAll, packageStateUser0) // Check for unmodifiable assertFailsWith(UnsupportedOperationException::class) { it.packageStates.clear() } assertThat(it.packageStates).containsExactly( packageStateAll.packageName, packageStateAll, packageStateUser0.packageName, packageStateUser0, ) } // Call after close fails Loading