Merge "[AppsFilter] use snapshots instead of live data" into tm-dev

This commit is contained in:
Songchun Fan
2022-04-22 19:32:49 +00:00
committed by Android (Google) Code Review
14 changed files with 509 additions and 478 deletions

View File

@@ -61,6 +61,7 @@ import com.android.server.pm.pkg.component.ParsedInstrumentation;
import com.android.server.pm.pkg.component.ParsedIntentInfo;
import com.android.server.pm.pkg.component.ParsedMainComponent;
import com.android.server.pm.pkg.component.ParsedProvider;
import com.android.server.pm.snapshot.PackageDataSnapshot;
import com.android.server.utils.Snappable;
import com.android.server.utils.SnapshotCache;
import com.android.server.utils.Watchable;
@@ -179,7 +180,6 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
private final boolean mSystemAppsQueryable;
private final FeatureConfig mFeatureConfig;
private final OverlayReferenceMapper mOverlayReferenceMapper;
private final StateProvider mStateProvider;
private SigningDetails mSystemSigningDetails;
@GuardedBy("mLock")
@@ -192,7 +192,8 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
/**
* This structure maps uid -> uid and indicates whether access from the first should be
* filtered to the second. It's essentially a cache of the
* {@link #shouldFilterApplicationInternal(int, Object, PackageStateInternal, int)} call.
* {@link #shouldFilterApplicationInternal(PackageDataSnapshot, int, Object,
* PackageStateInternal, int)} call.
* NOTE: It can only be relied upon after the system is ready to avoid unnecessary update on
* initial scam and is empty until {@link #mSystemReady} is true.
*/
@@ -282,8 +283,7 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
}
@VisibleForTesting(visibility = PRIVATE)
AppsFilterImpl(StateProvider stateProvider,
FeatureConfig featureConfig,
AppsFilterImpl(FeatureConfig featureConfig,
String[] forceQueryableList,
boolean systemAppsQueryable,
@Nullable OverlayReferenceMapper.Provider overlayProvider,
@@ -293,7 +293,6 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
mSystemAppsQueryable = systemAppsQueryable;
mOverlayReferenceMapper = new OverlayReferenceMapper(true /*deferRebuild*/,
overlayProvider);
mStateProvider = stateProvider;
mBackgroundExecutor = backgroundExecutor;
mShouldFilterCache = new WatchedSparseBooleanMatrix();
mShouldFilterCacheSnapshot = new SnapshotCache.Auto<>(
@@ -352,7 +351,6 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
mSystemAppsQueryable = orig.mSystemAppsQueryable;
mFeatureConfig = orig.mFeatureConfig;
mOverlayReferenceMapper = orig.mOverlayReferenceMapper;
mStateProvider = orig.mStateProvider;
mSystemSigningDetails = orig.mSystemSigningDetails;
synchronized (orig.mCacheLock) {
mShouldFilterCache = orig.mShouldFilterCacheSnapshot.snapshot();
@@ -361,7 +359,7 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
mBackgroundExecutor = null;
mSnapshot = new SnapshotCache.Sealed<>();
mSystemReady = true;
mSystemReady = orig.mSystemReady;
}
/**
@@ -373,23 +371,6 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
return mSnapshot.snapshot();
}
/**
* Provides system state to AppsFilter via {@link CurrentStateCallback} after properly guarding
* the data with the package lock.
*
* Don't call {@link #runWithState} with {@link #mCacheLock} held.
*/
@VisibleForTesting(visibility = PRIVATE)
public interface StateProvider {
void runWithState(CurrentStateCallback callback);
interface CurrentStateCallback {
void currentState(ArrayMap<String, ? extends PackageStateInternal> settings,
Collection<SharedUserSetting> sharedUserSettings,
UserInfo[] users);
}
}
@VisibleForTesting(visibility = PRIVATE)
public interface FeatureConfig {
@@ -517,12 +498,13 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
@Override
public void onCompatChange(String packageName) {
AndroidPackage pkg = mPmInternal.getPackage(packageName);
PackageDataSnapshot snapshot = mPmInternal.snapshot();
AndroidPackage pkg = snapshot.getPackage(packageName);
if (pkg == null) {
return;
}
updateEnabledState(pkg);
mAppsFilter.updateShouldFilterCacheForPackage(packageName);
mAppsFilter.updateShouldFilterCacheForPackage(snapshot, packageName);
}
private void updateEnabledState(@NonNull AndroidPackage pkg) {
@@ -574,14 +556,7 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
forcedQueryablePackageNames[i] = forcedQueryablePackageNames[i].intern();
}
}
final StateProvider stateProvider = command -> {
synchronized (injector.getLock()) {
command.currentState(injector.getSettings().getPackagesLocked().untrackedStorage(),
injector.getSettings().getAllSharedUsersLPw(),
injector.getUserManagerInternal().getUserInfos());
}
};
AppsFilterImpl appsFilter = new AppsFilterImpl(stateProvider, featureConfig,
AppsFilterImpl appsFilter = new AppsFilterImpl(featureConfig,
forcedQueryablePackageNames, forceSystemAppsQueryable, null,
injector.getBackgroundExecutor());
featureConfig.setAppsFilter(appsFilter);
@@ -754,12 +729,11 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
return changed;
}
public void onSystemReady() {
public void onSystemReady(PackageManagerInternal pmInternal) {
mOverlayReferenceMapper.rebuildIfDeferred();
mFeatureConfig.onSystemReady();
updateEntireShouldFilterCacheAsync();
onChanged();
updateEntireShouldFilterCacheAsync(pmInternal);
mSystemReady = true;
}
@@ -769,39 +743,41 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
* @param newPkgSetting the new setting being added
* @param isReplace if the package is being replaced and may need extra cleanup.
*/
public void addPackage(PackageStateInternal newPkgSetting, boolean isReplace) {
public void addPackage(PackageDataSnapshot snapshot, PackageStateInternal newPkgSetting,
boolean isReplace) {
if (DEBUG_TRACING) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage");
}
try {
if (isReplace) {
// let's first remove any prior rules for this package
removePackage(newPkgSetting, true /*isReplace*/);
removePackage(snapshot, newPkgSetting, true /*isReplace*/);
}
mStateProvider.runWithState((settings, sharedUserSettings, users) -> {
ArraySet<String> additionalChangedPackages =
addPackageInternal(newPkgSetting, settings);
if (mSystemReady) {
updateShouldFilterCacheForPackage(null, newPkgSetting,
final ArrayMap<String, ? extends PackageStateInternal> settings =
snapshot.getPackageStates();
final UserInfo[] users = snapshot.getUserInfos();
final ArraySet<String> additionalChangedPackages =
addPackageInternal(newPkgSetting, settings);
if (mSystemReady) {
synchronized (mCacheLock) {
updateShouldFilterCacheForPackage(snapshot, null, newPkgSetting,
settings, users, USER_ALL, settings.size());
if (additionalChangedPackages != null) {
for (int index = 0; index < additionalChangedPackages.size(); index++) {
String changedPackage = additionalChangedPackages.valueAt(index);
PackageStateInternal changedPkgSetting =
settings.get(changedPackage);
PackageStateInternal changedPkgSetting = settings.get(changedPackage);
if (changedPkgSetting == null) {
// It's possible for the overlay mapper to know that an actor
// package changed via an explicit reference, even if the actor
// isn't installed, so skip if that's the case.
continue;
}
updateShouldFilterCacheForPackage(null, changedPkgSetting,
updateShouldFilterCacheForPackage(snapshot, null, changedPkgSetting,
settings, users, USER_ALL, settings.size());
}
}
} // else, rebuild entire cache when system is ready
});
}
} // else, rebuild entire cache when system is ready
} finally {
onChanged();
if (DEBUG_TRACING) {
@@ -941,30 +917,32 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
}
}
private void updateEntireShouldFilterCache() {
updateEntireShouldFilterCache(USER_ALL);
private void updateEntireShouldFilterCache(PackageDataSnapshot snapshot) {
updateEntireShouldFilterCache(snapshot, USER_ALL);
}
private void updateEntireShouldFilterCache(int subjectUserId) {
mStateProvider.runWithState((settings, sharedUserSettings, users) -> {
int userId = USER_NULL;
for (int u = 0; u < users.length; u++) {
if (subjectUserId == users[u].id) {
userId = subjectUserId;
break;
}
private void updateEntireShouldFilterCache(PackageDataSnapshot snapshot, int subjectUserId) {
final ArrayMap<String, ? extends PackageStateInternal> settings =
snapshot.getPackageStates();
final UserInfo[] users = snapshot.getUserInfos();
int userId = USER_NULL;
for (int u = 0; u < users.length; u++) {
if (subjectUserId == users[u].id) {
userId = subjectUserId;
break;
}
if (userId == USER_NULL) {
Slog.e(TAG, "We encountered a new user that isn't a member of known users, "
+ "updating the whole cache");
userId = USER_ALL;
}
updateEntireShouldFilterCacheInner(settings, users, userId);
});
}
if (userId == USER_NULL) {
Slog.e(TAG, "We encountered a new user that isn't a member of known users, "
+ "updating the whole cache");
userId = USER_ALL;
}
updateEntireShouldFilterCacheInner(snapshot, settings, users, userId);
onChanged();
}
private void updateEntireShouldFilterCacheInner(
private void updateEntireShouldFilterCacheInner(PackageDataSnapshot snapshot,
ArrayMap<String, ? extends PackageStateInternal> settings,
UserInfo[] users,
int subjectUserId) {
@@ -973,67 +951,42 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
mShouldFilterCache.clear();
}
mShouldFilterCache.setCapacity(users.length * settings.size());
}
for (int i = settings.size() - 1; i >= 0; i--) {
updateShouldFilterCacheForPackage(
null /*skipPackage*/, settings.valueAt(i), settings, users,
subjectUserId, i);
for (int i = settings.size() - 1; i >= 0; i--) {
updateShouldFilterCacheForPackage(snapshot,
null /*skipPackage*/, settings.valueAt(i), settings, users,
subjectUserId, i);
}
}
}
private void updateEntireShouldFilterCacheAsync() {
private void updateEntireShouldFilterCacheAsync(PackageManagerInternal pmInternal) {
mBackgroundExecutor.execute(() -> {
final ArrayMap<String, PackageStateInternal> settingsCopy = new ArrayMap<>();
final Collection<SharedUserSetting> sharedUserSettingsCopy = new ArraySet<>();
final ArrayMap<String, AndroidPackage> packagesCache = new ArrayMap<>();
final UserInfo[][] usersRef = new UserInfo[1][];
mStateProvider.runWithState((settings, sharedUserSettings, users) -> {
packagesCache.ensureCapacity(settings.size());
settingsCopy.putAll(settings);
usersRef[0] = users;
// store away the references to the immutable packages, since settings are retained
// during updates.
for (int i = 0, max = settings.size(); i < max; i++) {
final AndroidPackage pkg = settings.valueAt(i).getPkg();
packagesCache.put(settings.keyAt(i), pkg);
}
sharedUserSettingsCopy.addAll(sharedUserSettings);
});
final PackageDataSnapshot snapshot = pmInternal.snapshot();
final ArrayMap<String, ? extends PackageStateInternal> settings =
snapshot.getPackageStates();
final UserInfo[] users = snapshot.getUserInfos();
boolean[] changed = new boolean[1];
// We have a cache, let's make sure the world hasn't changed out from under us.
mStateProvider.runWithState((settings, sharedUserSettings, users) -> {
if (settings.size() != settingsCopy.size()) {
changed[0] = true;
return;
}
for (int i = 0, max = settings.size(); i < max; i++) {
final AndroidPackage pkg = settings.valueAt(i).getPkg();
if (!Objects.equals(pkg, packagesCache.get(settings.keyAt(i)))) {
changed[0] = true;
return;
}
}
});
if (changed[0]) {
// Something has changed, just update the cache inline with the lock held
updateEntireShouldFilterCache();
if (DEBUG_LOGGING) {
Slog.i(TAG, "Rebuilding cache with lock due to package change.");
}
} else {
updateEntireShouldFilterCacheInner(settingsCopy,
usersRef[0], USER_ALL);
onChanged();
packagesCache.ensureCapacity(settings.size());
usersRef[0] = users;
// store away the references to the immutable packages, since settings are retained
// during updates.
for (int i = 0, max = settings.size(); i < max; i++) {
final AndroidPackage pkg = settings.valueAt(i).getPkg();
packagesCache.put(settings.keyAt(i), pkg);
}
updateEntireShouldFilterCacheInner(snapshot, settings, usersRef[0], USER_ALL);
onChanged();
});
}
public void onUserCreated(int newUserId) {
public void onUserCreated(PackageDataSnapshot snapshot, int newUserId) {
if (!mSystemReady) {
return;
}
updateEntireShouldFilterCache(newUserId);
updateEntireShouldFilterCache(snapshot, newUserId);
}
public void onUserDeleted(@UserIdInt int userId) {
@@ -1044,19 +997,24 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
onChanged();
}
private void updateShouldFilterCacheForPackage(String packageName) {
mStateProvider.runWithState((settings, sharedUserSettings, users) -> {
if (!mSystemReady) {
return;
}
updateShouldFilterCacheForPackage(null /* skipPackage */,
private void updateShouldFilterCacheForPackage(PackageDataSnapshot snapshot,
String packageName) {
if (!mSystemReady) {
return;
}
final ArrayMap<String, ? extends PackageStateInternal> settings =
snapshot.getPackageStates();
final UserInfo[] users = snapshot.getUserInfos();
synchronized (mCacheLock) {
updateShouldFilterCacheForPackage(snapshot, null /* skipPackage */,
settings.get(packageName), settings, users, USER_ALL,
settings.size() /*maxIndex*/);
});
}
onChanged();
}
private void updateShouldFilterCacheForPackage(
@GuardedBy("mCacheLock")
private void updateShouldFilterCacheForPackage(PackageDataSnapshot snapshot,
@Nullable String skipPackageName, PackageStateInternal subjectSetting, ArrayMap<String,
? extends PackageStateInternal> allSettings, UserInfo[] allUsers, int subjectUserId,
int maxIndex) {
@@ -1072,31 +1030,30 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
}
if (subjectUserId == USER_ALL) {
for (int su = 0; su < allUsers.length; su++) {
updateShouldFilterCacheForUser(subjectSetting, allUsers, otherSetting,
updateShouldFilterCacheForUser(snapshot, subjectSetting, allUsers, otherSetting,
allUsers[su].id);
}
} else {
updateShouldFilterCacheForUser(subjectSetting, allUsers, otherSetting,
updateShouldFilterCacheForUser(snapshot, subjectSetting, allUsers, otherSetting,
subjectUserId);
}
}
}
private void updateShouldFilterCacheForUser(
@GuardedBy("mCacheLock")
private void updateShouldFilterCacheForUser(PackageDataSnapshot snapshot,
PackageStateInternal subjectSetting, UserInfo[] allUsers,
PackageStateInternal otherSetting, int subjectUserId) {
for (int ou = 0; ou < allUsers.length; ou++) {
int otherUser = allUsers[ou].id;
int subjectUid = UserHandle.getUid(subjectUserId, subjectSetting.getAppId());
int otherUid = UserHandle.getUid(otherUser, otherSetting.getAppId());
final boolean shouldFilterSubjectToOther = shouldFilterApplicationInternal(
final boolean shouldFilterSubjectToOther = shouldFilterApplicationInternal(snapshot,
subjectUid, subjectSetting, otherSetting, otherUser);
final boolean shouldFilterOtherToSubject = shouldFilterApplicationInternal(
final boolean shouldFilterOtherToSubject = shouldFilterApplicationInternal(snapshot,
otherUid, otherSetting, subjectSetting, subjectUserId);
synchronized (mCacheLock) {
mShouldFilterCache.put(subjectUid, otherUid, shouldFilterSubjectToOther);
mShouldFilterCache.put(otherUid, subjectUid, shouldFilterOtherToSubject);
}
mShouldFilterCache.put(subjectUid, otherUid, shouldFilterSubjectToOther);
mShouldFilterCache.put(otherUid, subjectUid, shouldFilterOtherToSubject);
}
}
@@ -1182,11 +1139,13 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
}
/**
* See {@link AppsFilterSnapshot#getVisibilityAllowList(PackageStateInternal, int[], ArrayMap)}
* See {@link AppsFilterSnapshot#getVisibilityAllowList(PackageDataSnapshot,
* PackageStateInternal, int[], ArrayMap)}
*/
@Override
@Nullable
public SparseArray<int[]> getVisibilityAllowList(PackageStateInternal setting, int[] users,
public SparseArray<int[]> getVisibilityAllowList(PackageDataSnapshot snapshot,
PackageStateInternal setting, int[] users,
ArrayMap<String, ? extends PackageStateInternal> existingSettings) {
synchronized (mLock) {
if (mForceQueryable.contains(setting.getAppId())) {
@@ -1211,7 +1170,8 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
continue;
}
final int existingUid = UserHandle.getUid(userId, existingAppId);
if (!shouldFilterApplication(existingUid, existingSetting, setting, userId)) {
if (!shouldFilterApplication(snapshot, existingUid, existingSetting, setting,
userId)) {
if (buffer == null) {
buffer = new int[appIds.length];
}
@@ -1232,19 +1192,21 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
*/
@VisibleForTesting(visibility = PRIVATE)
@Nullable
SparseArray<int[]> getVisibilityAllowList(PackageStateInternal setting, int[] users,
SparseArray<int[]> getVisibilityAllowList(PackageDataSnapshot snapshot,
PackageStateInternal setting, int[] users,
WatchedArrayMap<String, ? extends PackageStateInternal> existingSettings) {
return getVisibilityAllowList(setting, users, existingSettings.untrackedStorage());
return getVisibilityAllowList(snapshot, setting, users,
existingSettings.untrackedStorage());
}
/**
* Equivalent to calling {@link #addPackage(PackageStateInternal, boolean)} with
* {@code isReplace} equal to {@code false}.
* Equivalent to calling {@link #addPackage(PackageDataSnapshot, PackageStateInternal, boolean)}
* with {@code isReplace} equal to {@code false}.
*
* @see AppsFilterImpl#addPackage(PackageStateInternal, boolean)
* @see AppsFilterImpl#addPackage(PackageDataSnapshot, PackageStateInternal, boolean)
*/
public void addPackage(PackageStateInternal newPkgSetting) {
addPackage(newPkgSetting, false /* isReplace */);
public void addPackage(PackageDataSnapshot snapshot, PackageStateInternal newPkgSetting) {
addPackage(snapshot, newPkgSetting, false /* isReplace */);
}
/**
@@ -1253,119 +1215,122 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
* @param setting the setting of the package being removed.
* @param isReplace if the package is being replaced.
*/
public void removePackage(PackageStateInternal setting, boolean isReplace) {
mStateProvider.runWithState((settings, sharedUserSettings, users) -> {
final ArraySet<String> additionalChangedPackages;
final int userCount = users.length;
synchronized (mLock) {
for (int u = 0; u < userCount; u++) {
final int userId = users[u].id;
final int removingUid = UserHandle.getUid(userId, setting.getAppId());
mImplicitlyQueryable.remove(removingUid);
for (int i = mImplicitlyQueryable.size() - 1; i >= 0; i--) {
mImplicitlyQueryable.remove(mImplicitlyQueryable.keyAt(i),
removingUid);
}
if (isReplace) {
continue;
}
mRetainedImplicitlyQueryable.remove(removingUid);
for (int i = mRetainedImplicitlyQueryable.size() - 1; i >= 0; i--) {
mRetainedImplicitlyQueryable.remove(
mRetainedImplicitlyQueryable.keyAt(i), removingUid);
}
public void removePackage(PackageDataSnapshot snapshot, PackageStateInternal setting,
boolean isReplace) {
final ArraySet<String> additionalChangedPackages;
final ArrayMap<String, ? extends PackageStateInternal> settings =
snapshot.getPackageStates();
final UserInfo[] users = snapshot.getUserInfos();
final Collection<SharedUserSetting> sharedUserSettings = snapshot.getAllSharedUsers();
final int userCount = users.length;
synchronized (mLock) {
for (int u = 0; u < userCount; u++) {
final int userId = users[u].id;
final int removingUid = UserHandle.getUid(userId, setting.getAppId());
mImplicitlyQueryable.remove(removingUid);
for (int i = mImplicitlyQueryable.size() - 1; i >= 0; i--) {
mImplicitlyQueryable.remove(mImplicitlyQueryable.keyAt(i),
removingUid);
}
if (!mQueriesViaComponentRequireRecompute) {
mQueriesViaComponent.remove(setting.getAppId());
for (int i = mQueriesViaComponent.size() - 1; i >= 0; i--) {
mQueriesViaComponent.remove(mQueriesViaComponent.keyAt(i),
setting.getAppId());
}
}
mQueriesViaPackage.remove(setting.getAppId());
for (int i = mQueriesViaPackage.size() - 1; i >= 0; i--) {
mQueriesViaPackage.remove(mQueriesViaPackage.keyAt(i),
setting.getAppId());
}
mQueryableViaUsesLibrary.remove(setting.getAppId());
for (int i = mQueryableViaUsesLibrary.size() - 1; i >= 0; i--) {
mQueryableViaUsesLibrary.remove(mQueryableViaUsesLibrary.keyAt(i),
setting.getAppId());
if (isReplace) {
continue;
}
mForceQueryable.remove(setting.getAppId());
if (setting.getPkg() != null
&& !setting.getPkg().getProtectedBroadcasts().isEmpty()) {
final String removingPackageName = setting.getPkg().getPackageName();
final ArrayList<String> protectedBroadcasts = new ArrayList<>();
protectedBroadcasts.addAll(mProtectedBroadcasts.untrackedStorage());
collectProtectedBroadcasts(settings, removingPackageName);
if (!mProtectedBroadcasts.containsAll(protectedBroadcasts)) {
mQueriesViaComponentRequireRecompute = true;
}
mRetainedImplicitlyQueryable.remove(removingUid);
for (int i = mRetainedImplicitlyQueryable.size() - 1; i >= 0; i--) {
mRetainedImplicitlyQueryable.remove(
mRetainedImplicitlyQueryable.keyAt(i), removingUid);
}
}
additionalChangedPackages = mOverlayReferenceMapper.removePkg(setting.getPackageName());
mFeatureConfig.updatePackageState(setting, true /*removed*/);
// After removing all traces of the package, if it's part of a shared user,
// re-add other
// shared user members to re-establish visibility between them and other
// packages.
// NOTE: this must come after all removals from data structures but before we
// update the
// cache
if (setting.hasSharedUser()) {
final ArraySet<? extends PackageStateInternal> sharedUserPackages =
getSharedUserPackages(setting.getSharedUserAppId(), sharedUserSettings);
for (int i = sharedUserPackages.size() - 1; i >= 0; i--) {
if (sharedUserPackages.valueAt(i) == setting) {
continue;
}
addPackageInternal(
sharedUserPackages.valueAt(i), settings);
if (!mQueriesViaComponentRequireRecompute) {
mQueriesViaComponent.remove(setting.getAppId());
for (int i = mQueriesViaComponent.size() - 1; i >= 0; i--) {
mQueriesViaComponent.remove(mQueriesViaComponent.keyAt(i),
setting.getAppId());
}
}
mQueriesViaPackage.remove(setting.getAppId());
for (int i = mQueriesViaPackage.size() - 1; i >= 0; i--) {
mQueriesViaPackage.remove(mQueriesViaPackage.keyAt(i),
setting.getAppId());
}
mQueryableViaUsesLibrary.remove(setting.getAppId());
for (int i = mQueryableViaUsesLibrary.size() - 1; i >= 0; i--) {
mQueryableViaUsesLibrary.remove(mQueryableViaUsesLibrary.keyAt(i),
setting.getAppId());
}
removeAppIdFromVisibilityCache(setting.getAppId());
if (mSystemReady && setting.hasSharedUser()) {
final ArraySet<? extends PackageStateInternal> sharedUserPackages =
getSharedUserPackages(setting.getSharedUserAppId(), sharedUserSettings);
for (int i = sharedUserPackages.size() - 1; i >= 0; i--) {
PackageStateInternal siblingSetting =
sharedUserPackages.valueAt(i);
if (siblingSetting == setting) {
continue;
}
updateShouldFilterCacheForPackage(
mForceQueryable.remove(setting.getAppId());
if (setting.getPkg() != null
&& !setting.getPkg().getProtectedBroadcasts().isEmpty()) {
final String removingPackageName = setting.getPkg().getPackageName();
final ArrayList<String> protectedBroadcasts = new ArrayList<>();
protectedBroadcasts.addAll(mProtectedBroadcasts.untrackedStorage());
collectProtectedBroadcasts(settings, removingPackageName);
if (!mProtectedBroadcasts.containsAll(protectedBroadcasts)) {
mQueriesViaComponentRequireRecompute = true;
}
}
}
additionalChangedPackages = mOverlayReferenceMapper.removePkg(setting.getPackageName());
mFeatureConfig.updatePackageState(setting, true /*removed*/);
// After removing all traces of the package, if it's part of a shared user, re-add other
// shared user members to re-establish visibility between them and other packages.
// NOTE: this must come after all removals from data structures but before we update the
// cache
if (setting.hasSharedUser()) {
final ArraySet<? extends PackageStateInternal> sharedUserPackages =
getSharedUserPackages(setting.getSharedUserAppId(), sharedUserSettings);
for (int i = sharedUserPackages.size() - 1; i >= 0; i--) {
if (sharedUserPackages.valueAt(i) == setting) {
continue;
}
addPackageInternal(
sharedUserPackages.valueAt(i), settings);
}
}
removeAppIdFromVisibilityCache(setting.getAppId());
if (mSystemReady && setting.hasSharedUser()) {
final ArraySet<? extends PackageStateInternal> sharedUserPackages =
getSharedUserPackages(setting.getSharedUserAppId(), sharedUserSettings);
for (int i = sharedUserPackages.size() - 1; i >= 0; i--) {
PackageStateInternal siblingSetting =
sharedUserPackages.valueAt(i);
if (siblingSetting == setting) {
continue;
}
synchronized (mCacheLock) {
updateShouldFilterCacheForPackage(snapshot,
setting.getPackageName(), siblingSetting, settings,
users, USER_ALL, settings.size());
}
}
}
if (mSystemReady) {
if (additionalChangedPackages != null) {
for (int index = 0; index < additionalChangedPackages.size(); index++) {
String changedPackage = additionalChangedPackages.valueAt(index);
PackageStateInternal changedPkgSetting = settings.get(changedPackage);
if (changedPkgSetting == null) {
// It's possible for the overlay mapper to know that an actor
// package changed via an explicit reference, even if the actor
// isn't installed, so skip if that's the case.
continue;
}
updateShouldFilterCacheForPackage(null, changedPkgSetting,
if (mSystemReady) {
if (additionalChangedPackages != null) {
for (int index = 0; index < additionalChangedPackages.size(); index++) {
String changedPackage = additionalChangedPackages.valueAt(index);
PackageStateInternal changedPkgSetting = settings.get(changedPackage);
if (changedPkgSetting == null) {
// It's possible for the overlay mapper to know that an actor
// package changed via an explicit reference, even if the actor
// isn't installed, so skip if that's the case.
continue;
}
synchronized (mCacheLock) {
updateShouldFilterCacheForPackage(snapshot, null, changedPkgSetting,
settings, users, USER_ALL, settings.size());
}
}
}
});
}
onChanged();
}
@@ -1382,12 +1347,12 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
/**
* See
* {@link AppsFilterSnapshot#shouldFilterApplication(int, Object, PackageStateInternal,
* int)}
* {@link AppsFilterSnapshot#shouldFilterApplication(PackageDataSnapshot, int, Object,
* PackageStateInternal, int)}
*/
@Override
public boolean shouldFilterApplication(int callingUid, @Nullable Object callingSetting,
PackageStateInternal targetPkgSetting, int userId) {
public boolean shouldFilterApplication(PackageDataSnapshot snapshot, int callingUid,
@Nullable Object callingSetting, PackageStateInternal targetPkgSetting, int userId) {
if (DEBUG_TRACING) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplication");
}
@@ -1405,7 +1370,7 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
return false;
}
} else {
if (!shouldFilterApplicationInternal(
if (!shouldFilterApplicationInternal(snapshot,
callingUid, callingSetting, targetPkgSetting, userId)) {
return false;
}
@@ -1440,8 +1405,8 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
}
}
private boolean shouldFilterApplicationInternal(int callingUid, Object callingSetting,
PackageStateInternal targetPkgSetting, int targetUserId) {
private boolean shouldFilterApplicationInternal(PackageDataSnapshot snapshot, int callingUid,
Object callingSetting, PackageStateInternal targetPkgSetting, int targetUserId) {
if (DEBUG_TRACING) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplicationInternal");
}
@@ -1467,9 +1432,8 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
final PackageStateInternal packageState = (PackageStateInternal) callingSetting;
if (packageState.hasSharedUser()) {
callingPkgSetting = null;
mStateProvider.runWithState((settings, sharedUserSettings, users) ->
callingSharedPkgSettings.addAll(getSharedUserPackages(
packageState.getSharedUserAppId(), sharedUserSettings)));
callingSharedPkgSettings.addAll(getSharedUserPackages(
packageState.getSharedUserAppId(), snapshot.getAllSharedUsers()));
} else {
callingPkgSetting = packageState;
@@ -1600,11 +1564,7 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mQueriesViaComponent");
}
if (mQueriesViaComponentRequireRecompute) {
final ArrayMap<String, PackageStateInternal> settingsCopy = new ArrayMap<>();
mStateProvider.runWithState((settings, sharedUserSettings, users) -> {
settingsCopy.putAll(settings);
});
recomputeComponentVisibility(settingsCopy);
recomputeComponentVisibility(snapshot.getPackageStates());
onChanged();
}
synchronized (mLock) {

View File

@@ -25,6 +25,7 @@ import android.util.SparseArray;
import com.android.internal.util.function.QuadFunction;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.snapshot.PackageDataSnapshot;
import java.io.PrintWriter;
@@ -40,27 +41,30 @@ public interface AppsFilterSnapshot {
* If the setting is visible to all UIDs, null is returned. If an app is not visible to any
* applications, the int array will be empty.
*
* @param snapshot the snapshot of the computer that contains all package information
* @param users the set of users that should be evaluated for this calculation
* @param existingSettings the set of all package settings that currently exist on device
* @return a SparseArray mapping userIds to a sorted int array of appIds that may view the
* provided setting or null if the app is visible to all and no allow list should be
* applied.
*/
SparseArray<int[]> getVisibilityAllowList(PackageStateInternal setting, int[] users,
SparseArray<int[]> getVisibilityAllowList(PackageDataSnapshot snapshot,
PackageStateInternal setting, int[] users,
ArrayMap<String, ? extends PackageStateInternal> existingSettings);
/**
* Returns true if the calling package should not be able to see the target package, false if no
* filtering should be done.
*
* @param snapshot the snapshot of the computer that contains all package information
* @param callingUid the uid of the caller attempting to access a package
* @param callingSetting the setting attempting to access a package or null if it could not be
* found
* @param targetPkgSetting the package being accessed
* @param userId the user in which this access is being attempted
*/
boolean shouldFilterApplication(int callingUid, @Nullable Object callingSetting,
PackageStateInternal targetPkgSetting, int userId);
boolean shouldFilterApplication(PackageDataSnapshot snapshot, int callingUid,
@Nullable Object callingSetting, PackageStateInternal targetPkgSetting, int userId);
/**
* Returns whether the querying package is allowed to see the target package.

View File

@@ -59,6 +59,7 @@ import com.android.server.utils.WatchedLongSparseArray;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.List;
import java.util.Set;
@@ -128,6 +129,7 @@ public interface Computer extends PackageDataSnapshot {
*/
ActivityInfo getActivityInfoInternal(ComponentName component, long flags,
int filterCallingUid, int userId);
@Override
AndroidPackage getPackage(String packageName);
AndroidPackage getPackage(int uid);
ApplicationInfo generateApplicationInfoFromSettings(String packageName, long flags,
@@ -289,6 +291,7 @@ public interface Computer extends PackageDataSnapshot {
PreferredIntentResolver getPreferredActivities(@UserIdInt int userId);
@NonNull
@Override
ArrayMap<String, ? extends PackageStateInternal> getPackageStates();
@Nullable
@@ -602,4 +605,12 @@ public interface Computer extends PackageDataSnapshot {
@NonNull
List<? extends PackageStateInternal> getVolumePackages(@NonNull String volumeUuid);
@Override
@NonNull
UserInfo[] getUserInfos();
@Override
@NonNull
Collection<SharedUserSetting> getAllSharedUsers();
}

View File

@@ -1348,7 +1348,7 @@ public class ComputerEngine implements Computer {
PackageStateInternal resolvedSetting =
getPackageStateInternal(info.activityInfo.packageName, 0);
if (resolveForStart
|| !mAppsFilter.shouldFilterApplication(
|| !mAppsFilter.shouldFilterApplication(this,
filterCallingUid, callingSetting, resolvedSetting, userId)) {
continue;
}
@@ -1382,7 +1382,7 @@ public class ComputerEngine implements Computer {
mSettings.getSettingBase(UserHandle.getAppId(filterCallingUid));
PackageStateInternal resolvedSetting =
getPackageStateInternal(info.serviceInfo.packageName, 0);
if (!mAppsFilter.shouldFilterApplication(
if (!mAppsFilter.shouldFilterApplication(this,
filterCallingUid, callingSetting, resolvedSetting, userId)) {
continue;
}
@@ -2730,7 +2730,7 @@ public class ComputerEngine implements Computer {
}
int appId = UserHandle.getAppId(callingUid);
final SettingBase callingPs = mSettings.getSettingBase(appId);
return mAppsFilter.shouldFilterApplication(callingUid, callingPs, ps, userId);
return mAppsFilter.shouldFilterApplication(this, callingUid, callingPs, ps, userId);
}
/**
@@ -5036,7 +5036,7 @@ public class ComputerEngine implements Computer {
if (setting == null) {
return null;
}
return mAppsFilter.getVisibilityAllowList(setting, userIds, getPackageStates());
return mAppsFilter.getVisibilityAllowList(this, setting, userIds, getPackageStates());
}
@Nullable
@@ -5323,7 +5323,7 @@ public class ComputerEngine implements Computer {
if (ps == null) {
return null;
}
final SparseArray<int[]> visibilityAllowList = mAppsFilter.getVisibilityAllowList(ps,
final SparseArray<int[]> visibilityAllowList = mAppsFilter.getVisibilityAllowList(this, ps,
new int[]{userId}, getPackageStates());
return visibilityAllowList != null ? visibilityAllowList.get(userId) : null;
}
@@ -5823,4 +5823,16 @@ public class ComputerEngine implements Computer {
public List<? extends PackageStateInternal> getVolumePackages(@NonNull String volumeUuid) {
return mSettings.getVolumePackages(volumeUuid);
}
@Override
@NonNull
public Collection<SharedUserSetting> getAllSharedUsers() {
return mSettings.getAllSharedUsers();
}
@Override
@NonNull
public UserInfo[] getUserInfos() {
return mInjector.getUserManagerInternal().getUserInfos();
}
}

View File

@@ -543,8 +543,9 @@ final class DeletePackageHelper {
synchronized (mPm.mLock) {
if (outInfo != null) {
outInfo.mUid = ps.getAppId();
outInfo.mBroadcastAllowList = mPm.mAppsFilter.getVisibilityAllowList(ps,
allUserHandles, mPm.mSettings.getPackagesLocked());
outInfo.mBroadcastAllowList = mPm.mAppsFilter.getVisibilityAllowList(
mPm.snapshotComputer(), ps, allUserHandles,
mPm.mSettings.getPackagesLocked());
}
}

View File

@@ -464,9 +464,9 @@ final class InstallPackageHelper {
KeySetManagerService ksms = mPm.mSettings.getKeySetManagerService();
ksms.addScannedPackageLPw(pkg);
mPm.mComponentResolver.addAllComponents(pkg, chatty, mPm.mSetupWizardPackage,
mPm.snapshotComputer());
mPm.mAppsFilter.addPackage(pkgSetting, isReplace);
final Computer snapshot = mPm.snapshotComputer();
mPm.mComponentResolver.addAllComponents(pkg, chatty, mPm.mSetupWizardPackage, snapshot);
mPm.mAppsFilter.addPackage(snapshot, pkgSetting, isReplace);
mPm.addAllPackageProperties(pkg);
if (oldPkgSetting == null || oldPkgSetting.getPkg() == null) {
@@ -1916,7 +1916,7 @@ final class InstallPackageHelper {
.setLastUpdateTime(System.currentTimeMillis());
res.mRemovedInfo.mBroadcastAllowList = mPm.mAppsFilter.getVisibilityAllowList(
reconciledPkg.mPkgSetting, request.mAllUsers,
mPm.snapshotComputer(), reconciledPkg.mPkgSetting, request.mAllUsers,
mPm.mSettings.getPackagesLocked());
if (reconciledPkg.mPrepareResult.mSystem) {
// Remove existing system package
@@ -2712,9 +2712,9 @@ final class InstallPackageHelper {
// Send to all running apps.
final SparseArray<int[]> newBroadcastAllowList;
synchronized (mPm.mLock) {
newBroadcastAllowList = mPm.mAppsFilter.getVisibilityAllowList(
mPm.snapshotComputer()
.getPackageStateInternal(packageName, Process.SYSTEM_UID),
final Computer snapshot = mPm.snapshotComputer();
newBroadcastAllowList = mPm.mAppsFilter.getVisibilityAllowList(snapshot,
snapshot.getPackageStateInternal(packageName, Process.SYSTEM_UID),
updateUserIds, mPm.mSettings.getPackagesLocked());
}
mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,

View File

@@ -2992,7 +2992,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
if (ArrayUtils.isEmpty(userIds) && ArrayUtils.isEmpty(instantUserIds)) {
return;
}
SparseArray<int[]> broadcastAllowList = mAppsFilter.getVisibilityAllowList(
SparseArray<int[]> broadcastAllowList = mAppsFilter.getVisibilityAllowList(snapshot,
snapshot.getPackageStateInternal(packageName, Process.SYSTEM_UID),
userIds, snapshot.getPackageStates());
mHandler.post(() -> mBroadcastHelper.sendPackageAddedForNewUsers(
@@ -4013,7 +4013,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
.getUriFor(Secure.INSTANT_APPS_ENABLED), false, co, UserHandle.USER_ALL);
co.onChange(true);
mAppsFilter.onSystemReady();
mAppsFilter.onSystemReady(LocalServices.getService(PackageManagerInternal.class));
// Disable any carrier apps. We do this very early in boot to prevent the apps from being
// disabled after already being started.
@@ -4226,7 +4226,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
synchronized (mLock) {
scheduleWritePackageRestrictions(userId);
scheduleWritePackageListLocked(userId);
mAppsFilter.onUserCreated(userId);
mAppsFilter.onUserCreated(snapshotComputer(), userId);
}
}
@@ -5751,7 +5751,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
targetPackageState = snapshotComputer().getPackageStateInternal(targetPackage);
mSettings.addInstallerPackageNames(targetPackageState.getInstallSource());
}
mAppsFilter.addPackage(targetPackageState);
mAppsFilter.addPackage(snapshotComputer(), targetPackageState);
scheduleWriteSettings();
}
}

View File

@@ -274,8 +274,9 @@ final class RemovePackageHelper {
synchronized (mPm.mLock) {
mPm.mDomainVerificationManager.clearPackage(deletedPs.getPackageName());
mPm.mSettings.getKeySetManagerService().removeAppKeySetDataLPw(packageName);
mPm.mAppsFilter.removePackage(mPm.snapshotComputer()
.getPackageStateInternal(packageName), false /* isReplace */);
final Computer snapshot = mPm.snapshotComputer();
mPm.mAppsFilter.removePackage(snapshot,
snapshot.getPackageStateInternal(packageName), false /* isReplace */);
removedAppId = mPm.mSettings.removePackageLPw(packageName);
if (outInfo != null) {
outInfo.mRemovedAppId = removedAppId;

View File

@@ -598,7 +598,7 @@ public final class SuspendPackageHelper {
final String pkgName = pkgList[i];
final int uid = uidList[i];
SparseArray<int[]> allowList = mInjector.getAppsFilter().getVisibilityAllowList(
snapshot.getPackageStateInternal(pkgName, SYSTEM_UID),
snapshot, snapshot.getPackageStateInternal(pkgName, SYSTEM_UID),
userIds, snapshot.getPackageStates());
if (allowList == null) {
allowList = new SparseArray<>(0);

View File

@@ -16,5 +16,22 @@
package com.android.server.pm.snapshot;
import android.annotation.NonNull;
import android.content.pm.UserInfo;
import android.util.ArrayMap;
import com.android.server.pm.SharedUserSetting;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import java.util.Collection;
public interface PackageDataSnapshot {
@NonNull
ArrayMap<String, ? extends PackageStateInternal> getPackageStates();
@NonNull
UserInfo[] getUserInfos();
@NonNull
Collection<SharedUserSetting> getAllSharedUsers();
AndroidPackage getPackage(String packageName);
}

View File

@@ -30,6 +30,7 @@ import com.android.server.pm.parsing.pkg.AndroidPackage
import com.android.server.pm.parsing.pkg.PackageImpl
import com.android.server.pm.parsing.pkg.ParsedPackage
import com.android.server.pm.resolution.ComponentResolver
import com.android.server.pm.snapshot.PackageDataSnapshot
import com.android.server.pm.test.override.PackageManagerComponentLabelIconOverrideTest.Companion.Params.AppType
import com.android.server.testutils.TestHandler
import com.android.server.testutils.mock
@@ -361,8 +362,8 @@ class PackageManagerComponentLabelIconOverrideTest {
whenever(this.isCallerRecents(anyInt())) { false }
}
val mockAppsFilter: AppsFilterImpl = mockThrowOnUnmocked {
whenever(this.shouldFilterApplication(anyInt(), any<PackageSetting>(),
any<PackageSetting>(), anyInt())) { false }
whenever(this.shouldFilterApplication(any<PackageDataSnapshot>(), anyInt(),
any<PackageSetting>(), any<PackageSetting>(), anyInt())) { false }
whenever(this.snapshot()) { this@mockThrowOnUnmocked }
whenever(registerObserver(any())).thenCallRealMethod()
}

View File

@@ -69,6 +69,7 @@ import com.android.server.pm.permission.PermissionManagerServiceInternal
import com.android.server.pm.pkg.parsing.ParsingPackage
import com.android.server.pm.pkg.parsing.ParsingPackageUtils
import com.android.server.pm.resolution.ComponentResolver
import com.android.server.pm.snapshot.PackageDataSnapshot
import com.android.server.pm.verify.domain.DomainVerificationManagerInternal
import com.android.server.sdksandbox.SdkSandboxManagerLocal
import com.android.server.testutils.TestHandler
@@ -329,7 +330,7 @@ class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) {
}
whenever(mocks.injector.sharedLibrariesImpl) { mSharedLibraries }
// everything visible by default
whenever(mocks.appsFilter.shouldFilterApplication(
whenever(mocks.appsFilter.shouldFilterApplication(any(PackageDataSnapshot::class.java),
anyInt(), nullable(), nullable(), anyInt())) { false }
val displayManager: DisplayManager = mock()

View File

@@ -23,6 +23,7 @@ import android.os.PersistableBundle
import android.util.ArrayMap
import android.util.SparseArray
import com.android.server.pm.pkg.PackageStateInternal
import com.android.server.pm.snapshot.PackageDataSnapshot
import com.android.server.testutils.any
import com.android.server.testutils.eq
import com.android.server.testutils.nullable
@@ -389,6 +390,7 @@ class SuspendPackageHelperTest : PackageHelperTestBase() {
private fun mockAllowList(pkgSetting: PackageStateInternal, list: SparseArray<IntArray>?) {
whenever(rule.mocks().appsFilter.getVisibilityAllowList(
any(PackageDataSnapshot::class.java),
argThat { it?.packageName == pkgSetting.packageName }, any(IntArray::class.java),
any() as ArrayMap<String, out PackageStateInternal>
))