Merge "Whitelist for package broadcasts" into rvc-dev
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 9f51edb..39fc18d 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -403,4 +403,20 @@
* Called by DevicePolicyManagerService to set the uid of the device owner.
*/
public abstract void setDeviceOwnerUid(int uid);
+
+ /**
+ * Sends a broadcast, assuming the caller to be the system and allowing the inclusion of an
+ * approved whitelist of app Ids >= {@link android.os.Process#FIRST_APPLICATION_UID} that the
+ * broadcast my be sent to; any app Ids < {@link android.os.Process#FIRST_APPLICATION_UID} are
+ * automatically whitelisted.
+ *
+ * @see com.android.server.am.ActivityManagerService#broadcastIntentWithFeature(
+ * IApplicationThread, String, Intent, String, IIntentReceiver, int, String, Bundle,
+ * String[], int, Bundle, boolean, boolean, int)
+ */
+ public abstract int broadcastIntent(Intent intent,
+ IIntentReceiver resultTo,
+ String[] requiredPermissions, boolean serialized,
+ int userId, int[] appIdWhitelist);
+
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 73d6fff..bd905da 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15568,7 +15568,7 @@
}
private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,
- int callingUid, int[] users) {
+ int callingUid, int[] users, int[] broadcastWhitelist) {
// TODO: come back and remove this assumption to triage all broadcasts
int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING;
@@ -15644,6 +15644,15 @@
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
}
+ if (receivers != null && broadcastWhitelist != null) {
+ for (int i = receivers.size() - 1; i >= 0; i--) {
+ final int uid = receivers.get(i).activityInfo.applicationInfo.uid;
+ if (uid >= Process.FIRST_APPLICATION_UID
+ && Arrays.binarySearch(broadcastWhitelist, UserHandle.getAppId(uid)) < 0) {
+ receivers.remove(i);
+ }
+ }
+ }
return receivers;
}
@@ -15738,7 +15747,8 @@
return broadcastIntentLocked(callerApp, callerPackage, callerFeatureId, intent,
resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions,
appOp, bOptions, ordered, sticky, callingPid, callingUid, realCallingUid,
- realCallingPid, userId, false /* allowBackgroundActivityStarts */);
+ realCallingPid, userId, false /* allowBackgroundActivityStarts */,
+ null /*broadcastWhitelist*/);
}
@GuardedBy("this")
@@ -15747,7 +15757,8 @@
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid,
- int realCallingPid, int userId, boolean allowBackgroundActivityStarts) {
+ int realCallingPid, int userId, boolean allowBackgroundActivityStarts,
+ @Nullable int[] broadcastWhitelist) {
intent = new Intent(intent);
final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid);
@@ -15756,6 +15767,12 @@
intent.setFlags(intent.getFlags() & ~Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
}
+ if (userId == UserHandle.USER_ALL && broadcastWhitelist != null) {
+ Slog.e(TAG, "broadcastWhitelist only applies when sending to individual users. "
+ + "Assuming restrictive whitelist.");
+ broadcastWhitelist = new int[]{};
+ }
+
// By default broadcasts do not go to stopped apps.
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
@@ -16242,7 +16259,8 @@
// Need to resolve the intent to interested receivers...
if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
== 0) {
- receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
+ receivers = collectReceiverComponents(
+ intent, resolvedType, callingUid, users, broadcastWhitelist);
}
if (intent.getComponent() == null) {
if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
@@ -16272,6 +16290,17 @@
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing broadcast: " + intent.getAction()
+ " replacePending=" + replacePending);
+ if (registeredReceivers != null && broadcastWhitelist != null) {
+ // if a uid whitelist was provided, remove anything in the application space that wasn't
+ // in it.
+ for (int i = registeredReceivers.size() - 1; i >= 0; i--) {
+ final int uid = registeredReceivers.get(i).owningUid;
+ if (uid >= Process.FIRST_APPLICATION_UID
+ && Arrays.binarySearch(broadcastWhitelist, UserHandle.getAppId(uid)) < 0) {
+ registeredReceivers.remove(i);
+ }
+ }
+ }
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
if (!ordered && NR > 0) {
@@ -16555,7 +16584,8 @@
return broadcastIntentLocked(null, packageName, featureId, intent, resolvedType,
resultTo, resultCode, resultData, resultExtras, requiredPermissions,
OP_NONE, bOptions, serialized, sticky, -1, uid, realCallingUid,
- realCallingPid, userId, allowBackgroundActivityStarts);
+ realCallingPid, userId, allowBackgroundActivityStarts,
+ null /*broadcastWhitelist*/);
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -19186,6 +19216,32 @@
}
@Override
+ public int broadcastIntent(Intent intent,
+ IIntentReceiver resultTo,
+ String[] requiredPermissions,
+ boolean serialized, int userId, int[] appIdWhitelist) {
+ synchronized (ActivityManagerService.this) {
+ intent = verifyBroadcastLocked(intent);
+
+ final int callingPid = Binder.getCallingPid();
+ final int callingUid = Binder.getCallingUid();
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ return ActivityManagerService.this.broadcastIntentLocked(null /*callerApp*/,
+ null /*callerPackage*/, null /*callingFeatureId*/, intent,
+ null /*resolvedType*/, resultTo, 0 /*resultCode*/, null /*resultData*/,
+ null /*resultExtras*/, requiredPermissions, AppOpsManager.OP_NONE,
+ null /*options*/, serialized, false /*sticky*/, callingPid, callingUid,
+ callingUid, callingPid, userId, false /*allowBackgroundStarts*/,
+ appIdWhitelist);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
+ }
+
+ @Override
public ComponentName startServiceInPackage(int uid, Intent service, String resolvedType,
boolean fgRequired, String callingPackage, @Nullable String callingFeatureId,
int userId, boolean allowBackgroundActivityStarts)
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 690b9f7..805d918 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -55,6 +55,7 @@
import com.android.server.pm.parsing.pkg.AndroidPackage;
import java.io.PrintWriter;
+import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -507,7 +508,65 @@
private static boolean isSystemSigned(@NonNull PackageParser.SigningDetails sysSigningDetails,
PackageSetting pkgSetting) {
return pkgSetting.isSystem()
- && pkgSetting.signatures.mSigningDetails.signaturesMatchExactly(sysSigningDetails);
+ && pkgSetting.signatures.mSigningDetails.signaturesMatchExactly(sysSigningDetails);
+ }
+
+ private static void sort(int[] uids, int nextUidIndex) {
+ Arrays.sort(uids, 0, nextUidIndex);
+ }
+
+ /**
+ * Fetches all app Ids that a given setting is currently visible to, per provided user. This
+ * only includes UIDs >= {@link Process#FIRST_APPLICATION_UID} as all other UIDs can already see
+ * all applications.
+ *
+ * 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 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 whitelist should be
+ * applied.
+ */
+ @Nullable
+ public SparseArray<int[]> getVisibilityWhitelist(PackageSetting setting, int[] users,
+ ArrayMap<String, PackageSetting> existingSettings) {
+ if (mForceQueryable.contains(setting.appId)) {
+ return null;
+ }
+ // let's reserve max memory to limit the number of allocations
+ SparseArray<int[]> result = new SparseArray<>(users.length);
+ for (int u = 0; u < users.length; u++) {
+ final int userId = users[u];
+ int[] appIds = new int[existingSettings.size()];
+ int[] buffer = null;
+ int whitelistSize = 0;
+ for (int i = existingSettings.size() - 1; i >= 0; i--) {
+ final PackageSetting existingSetting = existingSettings.valueAt(i);
+ final int existingAppId = existingSetting.appId;
+ if (existingAppId < Process.FIRST_APPLICATION_UID) {
+ continue;
+ }
+ final int loc = Arrays.binarySearch(appIds, 0, whitelistSize, existingAppId);
+ if (loc >= 0) {
+ continue;
+ }
+ final int existingUid = UserHandle.getUid(userId, existingAppId);
+ if (!shouldFilterApplication(existingUid, existingSetting, setting, userId)) {
+ if (buffer == null) {
+ buffer = new int[appIds.length];
+ }
+ final int insert = ~loc;
+ System.arraycopy(appIds, insert, buffer, 0, whitelistSize - insert);
+ appIds[insert] = existingUid;
+ System.arraycopy(buffer, 0, appIds, insert + 1, whitelistSize - insert);
+ whitelistSize++;
+ }
+ }
+ result.put(userId, Arrays.copyOf(appIds, whitelistSize));
+ }
+ return result;
}
/**
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 8ef1182..414449d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -136,6 +136,7 @@
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.ApplicationPackageManager;
import android.app.BroadcastOptions;
@@ -882,6 +883,7 @@
private final Singleton<UserManagerService> mUserManagerProducer;
private final Singleton<Settings> mSettingsProducer;
private final Singleton<ActivityTaskManagerInternal> mActivityTaskManagerProducer;
+ private final Singleton<ActivityManagerInternal> mActivityManagerInternalProducer;
private final Singleton<DeviceIdleInternal> mLocalDeviceIdleController;
private final Singleton<StorageManagerInternal> mStorageManagerInternalProducer;
private final Singleton<NetworkPolicyManagerInternal> mNetworkPolicyManagerProducer;
@@ -900,6 +902,7 @@
Producer<UserManagerService> userManagerProducer,
Producer<Settings> settingsProducer,
Producer<ActivityTaskManagerInternal> activityTaskManagerProducer,
+ Producer<ActivityManagerInternal> activityManagerInternalProducer,
Producer<DeviceIdleInternal> deviceIdleControllerProducer,
Producer<StorageManagerInternal> storageManagerInternalProducer,
Producer<NetworkPolicyManagerInternal> networkPolicyManagerProducer,
@@ -920,6 +923,7 @@
mUserManagerProducer = new Singleton<>(userManagerProducer);
mSettingsProducer = new Singleton<>(settingsProducer);
mActivityTaskManagerProducer = new Singleton<>(activityTaskManagerProducer);
+ mActivityManagerInternalProducer = new Singleton<>(activityManagerInternalProducer);
mLocalDeviceIdleController = new Singleton<>(deviceIdleControllerProducer);
mStorageManagerInternalProducer = new Singleton<>(storageManagerInternalProducer);
mNetworkPolicyManagerProducer = new Singleton<>(networkPolicyManagerProducer);
@@ -984,6 +988,10 @@
return mActivityTaskManagerProducer.get(this, mPackageManager);
}
+ public ActivityManagerInternal getActivityManagerInternal() {
+ return mActivityManagerInternalProducer.get(this, mPackageManager);
+ }
+
public DeviceIdleInternal getLocalDeviceIdleController() {
return mLocalDeviceIdleController.get(this, mPackageManager);
}
@@ -2119,16 +2127,23 @@
}
extras.putInt(PackageInstaller.EXTRA_DATA_LOADER_TYPE, dataLoaderType);
// Send to all running apps.
+ final SparseArray<int[]> newBroadcastWhitelist;
+
+ synchronized (mLock) {
+ newBroadcastWhitelist = mAppsFilter.getVisibilityWhitelist(
+ getPackageSettingInternal(res.name, Process.SYSTEM_UID),
+ updateUserIds, mSettings.mPackages);
+ }
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, 0 /*flags*/,
null /*targetPackage*/, null /*finishedReceiver*/,
- updateUserIds, instantUserIds);
+ updateUserIds, instantUserIds, newBroadcastWhitelist);
if (installerPackageName != null) {
// Send to the installer, even if it's not running.
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, 0 /*flags*/,
installerPackageName, null /*finishedReceiver*/,
- updateUserIds, instantUserIds);
+ updateUserIds, instantUserIds, null /* broadcastWhitelist */);
}
// if the required verifier is defined, but, is not the installer of record
// for the package, it gets notified
@@ -2138,7 +2153,7 @@
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, 0 /*flags*/,
mRequiredVerifierPackage, null /*finishedReceiver*/,
- updateUserIds, instantUserIds);
+ updateUserIds, instantUserIds, null /* broadcastWhitelist */);
}
// If package installer is defined, notify package installer about new
// app installed
@@ -2146,7 +2161,7 @@
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND /*flags*/,
mRequiredInstallerPackage, null /*finishedReceiver*/,
- firstUserIds, instantUserIds);
+ firstUserIds, instantUserIds, null /* broadcastWhitelist */);
}
// Send replaced for users that don't see the package for the first time
@@ -2154,23 +2169,24 @@
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
packageName, extras, 0 /*flags*/,
null /*targetPackage*/, null /*finishedReceiver*/,
- updateUserIds, instantUserIds);
+ updateUserIds, instantUserIds, res.removedInfo.broadcastWhitelist);
if (installerPackageName != null) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
extras, 0 /*flags*/,
installerPackageName, null /*finishedReceiver*/,
- updateUserIds, instantUserIds);
+ updateUserIds, instantUserIds, null /*broadcastWhitelist*/);
}
if (notifyVerifier) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
extras, 0 /*flags*/,
mRequiredVerifierPackage, null /*finishedReceiver*/,
- updateUserIds, instantUserIds);
+ updateUserIds, instantUserIds, null /*broadcastWhitelist*/);
}
sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
null /*package*/, null /*extras*/, 0 /*flags*/,
packageName /*targetPackage*/,
- null /*finishedReceiver*/, updateUserIds, instantUserIds);
+ null /*finishedReceiver*/, updateUserIds, instantUserIds,
+ null /*broadcastWhitelist*/);
} else if (launchedForRestore && !res.pkg.isSystem()) {
// First-install and we did a restore, so we're responsible for the
// first-launch broadcast.
@@ -2207,6 +2223,7 @@
sendResourcesChangedBroadcast(true, true, pkgList, uidArray, null);
}
} else if (!ArrayUtils.isEmpty(res.libraryConsumers)) { // if static shared lib
+ int[] allUsers = mInjector.getUserManagerService().getUserIds();
for (int i = 0; i < res.libraryConsumers.size(); i++) {
AndroidPackage pkg = res.libraryConsumers.get(i);
// send broadcast that all consumers of the static shared library have changed
@@ -2512,6 +2529,7 @@
i.getPermissionManagerServiceInternal().getPermissionSettings(),
lock),
new Injector.LocalServicesProducer<>(ActivityTaskManagerInternal.class),
+ new Injector.LocalServicesProducer<>(ActivityManagerInternal.class),
new Injector.LocalServicesProducer<>(DeviceIdleInternal.class),
new Injector.LocalServicesProducer<>(StorageManagerInternal.class),
new Injector.LocalServicesProducer<>(NetworkPolicyManagerInternal.class),
@@ -12213,7 +12231,8 @@
@Override
public void sendPackageBroadcast(final String action, final String pkg, final Bundle extras,
final int flags, final String targetPkg, final IIntentReceiver finishedReceiver,
- final int[] userIds, int[] instantUserIds) {
+ final int[] userIds, int[] instantUserIds,
+ @Nullable SparseArray<int[]> broadcastWhitelist) {
mHandler.post(() -> {
try {
final IActivityManager am = ActivityManager.getService();
@@ -12225,10 +12244,10 @@
resolvedUserIds = userIds;
}
doSendBroadcast(am, action, pkg, extras, flags, targetPkg, finishedReceiver,
- resolvedUserIds, false);
+ resolvedUserIds, false, broadcastWhitelist);
if (instantUserIds != null && instantUserIds != EMPTY_INT_ARRAY) {
doSendBroadcast(am, action, pkg, extras, flags, targetPkg, finishedReceiver,
- instantUserIds, true);
+ instantUserIds, true, null);
}
} catch (RemoteException ex) {
}
@@ -12298,8 +12317,7 @@
*/
private void doSendBroadcast(IActivityManager am, String action, String pkg, Bundle extras,
int flags, String targetPkg, IIntentReceiver finishedReceiver,
- int[] userIds, boolean isInstantApp)
- throws RemoteException {
+ int[] userIds, boolean isInstantApp, @Nullable SparseArray<int[]> broadcastWhitelist) {
for (int id : userIds) {
final Intent intent = new Intent(action,
pkg != null ? Uri.fromParts(PACKAGE_SCHEME, pkg, null) : null);
@@ -12326,9 +12344,10 @@
+ intent.toShortString(false, true, false, false)
+ " " + intent.getExtras(), here);
}
- am.broadcastIntentWithFeature(null, null, intent, null, finishedReceiver,
- 0, null, null, requiredPermissions, android.app.AppOpsManager.OP_NONE,
- null, finishedReceiver != null, false, id);
+ mInjector.getActivityManagerInternal().broadcastIntent(
+ intent, finishedReceiver, requiredPermissions,
+ finishedReceiver != null, id,
+ broadcastWhitelist == null ? null : broadcastWhitelist.get(id));
}
}
@@ -12456,7 +12475,10 @@
extras.putInt(Intent.EXTRA_UID, uid);
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
- packageName, extras, 0, null, null, userIds, instantUserIds);
+ packageName, extras, 0, null, null, userIds, instantUserIds,
+ mAppsFilter.getVisibilityWhitelist(
+ getPackageSettingInternal(packageName, Process.SYSTEM_UID),
+ userIds, mSettings.mPackages));
if (sendBootCompleted && !ArrayUtils.isEmpty(userIds)) {
mHandler.post(() -> {
for (int userId : userIds) {
@@ -12662,7 +12684,7 @@
extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidList);
extras.putInt(Intent.EXTRA_DISTRACTION_RESTRICTIONS, distractionFlags);
sendPackageBroadcast(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED, null, extras,
- Intent.FLAG_RECEIVER_REGISTERED_ONLY, null, null, new int[]{userId}, null);
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY, null, null, new int[]{userId}, null, null);
}
private void sendPackagesSuspendedForUser(String[] pkgList, int[] uidList, int userId,
@@ -12674,7 +12696,7 @@
suspended ? Intent.ACTION_PACKAGES_SUSPENDED
: Intent.ACTION_PACKAGES_UNSUSPENDED,
null, extras, Intent.FLAG_RECEIVER_REGISTERED_ONLY, null, null,
- new int[] {userId}, null);
+ new int[] {userId}, null, null);
}
/**
@@ -13065,31 +13087,27 @@
? Intent.ACTION_MY_PACKAGE_SUSPENDED
: Intent.ACTION_MY_PACKAGE_UNSUSPENDED;
mHandler.post(() -> {
- try {
- final IActivityManager am = ActivityManager.getService();
- if (am == null) {
- Slog.wtf(TAG, "IActivityManager null. Cannot send MY_PACKAGE_ "
- + (suspended ? "" : "UN") + "SUSPENDED broadcasts");
- return;
+ final IActivityManager am = ActivityManager.getService();
+ if (am == null) {
+ Slog.wtf(TAG, "IActivityManager null. Cannot send MY_PACKAGE_ "
+ + (suspended ? "" : "UN") + "SUSPENDED broadcasts");
+ return;
+ }
+ final int[] targetUserIds = new int[] {userId};
+ for (String packageName : affectedPackages) {
+ final Bundle appExtras = suspended
+ ? getSuspendedPackageAppExtrasInternal(packageName, userId)
+ : null;
+ final Bundle intentExtras;
+ if (appExtras != null) {
+ intentExtras = new Bundle(1);
+ intentExtras.putBundle(Intent.EXTRA_SUSPENDED_PACKAGE_EXTRAS, appExtras);
+ } else {
+ intentExtras = null;
}
- final int[] targetUserIds = new int[] {userId};
- for (String packageName : affectedPackages) {
- final Bundle appExtras = suspended
- ? getSuspendedPackageAppExtrasInternal(packageName, userId)
- : null;
- final Bundle intentExtras;
- if (appExtras != null) {
- intentExtras = new Bundle(1);
- intentExtras.putBundle(Intent.EXTRA_SUSPENDED_PACKAGE_EXTRAS, appExtras);
- } else {
- intentExtras = null;
- }
- doSendBroadcast(am, action, null, intentExtras,
- Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, packageName, null,
- targetUserIds, false);
- }
- } catch (RemoteException ex) {
- // Shouldn't happen as AMS is in the same process.
+ doSendBroadcast(am, action, null, intentExtras,
+ Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, packageName, null,
+ targetUserIds, false, null);
}
});
}
@@ -14089,7 +14107,7 @@
private void sendFirstLaunchBroadcast(String pkgName, String installerPkg,
int[] userIds, int[] instantUserIds) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH, pkgName, null, 0,
- installerPkg, null, userIds, instantUserIds);
+ installerPkg, null, userIds, instantUserIds, null /* broadcastWhitelist */);
}
private abstract class HandlerParams {
@@ -16172,6 +16190,8 @@
reconciledPkg.pkgSetting.firstInstallTime = deletedPkgSetting.firstInstallTime;
reconciledPkg.pkgSetting.lastUpdateTime = System.currentTimeMillis();
+ res.removedInfo.broadcastWhitelist = mAppsFilter.getVisibilityWhitelist(
+ reconciledPkg.pkgSetting, request.mAllUsers, mSettings.mPackages);
if (reconciledPkg.prepareResult.system) {
// Remove existing system package
removePackageLI(oldPackage, true);
@@ -17986,6 +18006,9 @@
boolean dataRemoved;
boolean removedForAllUsers;
boolean isStaticSharedLib;
+ // a two dimensional array mapping userId to the set of appIds that can receive notice
+ // of package changes
+ SparseArray<int[]> broadcastWhitelist;
// Clean up resources deleted packages.
InstallArgs args = null;
ArrayMap<String, PackageInstalledInfo> appearedChildPackages;
@@ -18019,19 +18042,19 @@
Bundle extras = new Bundle(2);
extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid);
extras.putBoolean(Intent.EXTRA_REPLACING, true);
- packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
- removedPackage, extras, 0, null /*targetPackage*/, null, null, null);
- packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
- removedPackage, extras, 0, null /*targetPackage*/, null, null, null);
- packageSender.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
- null, null, 0, removedPackage, null, null, null);
+ packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, removedPackage, extras,
+ 0, null /*targetPackage*/, null, null, null, broadcastWhitelist);
+ packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, removedPackage,
+ extras, 0, null /*targetPackage*/, null, null, null, broadcastWhitelist);
+ packageSender.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null, null, 0,
+ removedPackage, null, null, null, null /* broadcastWhitelist */);
if (installerPackageName != null) {
packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
removedPackage, extras, 0 /*flags*/,
- installerPackageName, null, null, null);
+ installerPackageName, null, null, null, null /* broadcastWhitelist */);
packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
removedPackage, extras, 0 /*flags*/,
- installerPackageName, null, null, null);
+ installerPackageName, null, null, null, null /* broadcastWhitelist */);
}
}
@@ -18054,17 +18077,16 @@
if (removedPackage != null) {
packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED,
removedPackage, extras, 0, null /*targetPackage*/, null,
- broadcastUsers, instantUserIds);
+ broadcastUsers, instantUserIds, broadcastWhitelist);
if (installerPackageName != null) {
packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED,
removedPackage, extras, 0 /*flags*/,
- installerPackageName, null, broadcastUsers, instantUserIds);
+ installerPackageName, null, broadcastUsers, instantUserIds, null);
}
if (dataRemoved && !isRemovedPackageSystemUpdate) {
packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED,
- removedPackage, extras,
- Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,
- null, null, broadcastUsers, instantUserIds);
+ removedPackage, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, null,
+ null, broadcastUsers, instantUserIds, broadcastWhitelist);
packageSender.notifyPackageRemoved(removedPackage, removedUid);
}
}
@@ -18077,7 +18099,7 @@
packageSender.sendPackageBroadcast(Intent.ACTION_UID_REMOVED,
null, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,
- null, null, broadcastUsers, instantUserIds);
+ null, null, broadcastUsers, instantUserIds, broadcastWhitelist);
}
}
@@ -20418,8 +20440,7 @@
}
private void sendPackageChangedBroadcast(String packageName,
- boolean dontKillApp, ArrayList<String> componentNames, int packageUid,
- String reason) {
+ boolean dontKillApp, ArrayList<String> componentNames, int packageUid, String reason) {
if (DEBUG_INSTALL)
Log.v(TAG, "Sending package changed: package=" + packageName + " components="
+ componentNames);
@@ -20442,8 +20463,14 @@
final boolean isInstantApp = isInstantApp(packageName, userId);
final int[] userIds = isInstantApp ? EMPTY_INT_ARRAY : new int[] { userId };
final int[] instantUserIds = isInstantApp ? new int[] { userId } : EMPTY_INT_ARRAY;
+ final SparseArray<int[]> broadcastWhitelist;
+ synchronized (mLock) {
+ broadcastWhitelist = isInstantApp ? null : mAppsFilter.getVisibilityWhitelist(
+ getPackageSettingInternal(packageName, Process.SYSTEM_UID),
+ userIds, mSettings.mPackages);
+ }
sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, flags, null, null,
- userIds, instantUserIds);
+ userIds, instantUserIds, broadcastWhitelist);
}
@Override
@@ -21679,7 +21706,7 @@
}
private void sendResourcesChangedBroadcast(boolean mediaStatus, boolean replacing,
- String[] pkgList, int uidArr[], IIntentReceiver finishedReceiver) {
+ String[] pkgList, int[] uidArr, IIntentReceiver finishedReceiver) {
int size = pkgList.length;
if (size > 0) {
// Send broadcasts here
@@ -21693,7 +21720,8 @@
}
String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
: Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
- sendPackageBroadcast(action, null, extras, 0, null, finishedReceiver, null, null);
+ // TODO: not sure how to handle this one.
+ sendPackageBroadcast(action, null, extras, 0, null, finishedReceiver, null, null, null);
}
}
@@ -24867,7 +24895,8 @@
*/
void sendPackageBroadcast(final String action, final String pkg,
final Bundle extras, final int flags, final String targetPkg,
- final IIntentReceiver finishedReceiver, final int[] userIds, int[] instantUserIds);
+ final IIntentReceiver finishedReceiver, final int[] userIds, int[] instantUserIds,
+ @Nullable SparseArray<int[]> broadcastWhitelist);
void sendPackageAddedForNewUsers(String packageName, boolean sendBootCompleted,
boolean includeStopped, int appId, int[] userIds, int[] instantUserIds);
void notifyPackageAdded(String packageName, int uid);
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
index 22591c6..5109de5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
@@ -17,6 +17,7 @@
package com.android.server.pm;
+import static org.hamcrest.Matchers.arrayContaining;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -47,6 +48,7 @@
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import org.hamcrest.Matcher;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -56,7 +58,9 @@
import org.mockito.MockitoAnnotations;
import java.security.cert.CertificateException;
+import java.util.Arrays;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -635,6 +639,57 @@
appsFilter.shouldFilterApplication(DUMMY_TARGET_UID, target, instrumentation, 0));
}
+ @Test
+ public void testWhoCanSee() throws Exception {
+ final AppsFilter appsFilter =
+ new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ appsFilter.onSystemReady();
+
+ final int systemAppId = Process.FIRST_APPLICATION_UID - 1;
+ final int seesNothingAppId = Process.FIRST_APPLICATION_UID;
+ final int hasProviderAppId = Process.FIRST_APPLICATION_UID + 1;
+ final int queriesProviderAppId = Process.FIRST_APPLICATION_UID + 2;
+ PackageSetting system = simulateAddPackage(appsFilter, pkg("some.system.pkg"), systemAppId);
+ PackageSetting seesNothing = simulateAddPackage(appsFilter, pkg("some.system.pkg"),
+ seesNothingAppId);
+ PackageSetting hasProvider = simulateAddPackage(appsFilter,
+ pkgWithProvider("com.some.package", "com.some.authority"), hasProviderAppId);
+ PackageSetting queriesProvider = simulateAddPackage(appsFilter,
+ pkgQueriesProvider("com.some.other.package", "com.some.authority"),
+ queriesProviderAppId);
+
+ final int[] systemFilter =
+ appsFilter.getVisibilityWhitelist(system, new int[]{0}, mExisting).get(0);
+ assertThat(Arrays.asList(systemFilter), arrayContaining(systemAppId));
+
+ final int[] seesNothingFilter =
+ appsFilter.getVisibilityWhitelist(seesNothing, new int[]{0}, mExisting).get(0);
+ assertThat(Arrays.asList(seesNothingFilter),
+ arrayContaining(systemAppId, seesNothingAppId));
+
+ final int[] hasProviderFilter =
+ appsFilter.getVisibilityWhitelist(hasProvider, new int[]{0}, mExisting).get(0);
+ assertThat(Arrays.asList(hasProviderFilter),
+ arrayContaining(systemAppId, hasProviderAppId, queriesProviderAppId));
+
+ int[] queriesProviderFilter =
+ appsFilter.getVisibilityWhitelist(queriesProvider, new int[]{0}, mExisting).get(0);
+ assertThat(Arrays.asList(queriesProviderFilter),
+ arrayContaining(systemAppId, queriesProviderAppId));
+
+ // provider read
+ appsFilter.grantImplicitAccess(hasProviderAppId, queriesProviderAppId);
+
+ // ensure implicit access is included in the filter
+ queriesProviderFilter =
+ appsFilter.getVisibilityWhitelist(queriesProvider, new int[]{0}, mExisting).get(0);
+ assertThat(Arrays.asList(queriesProviderFilter),
+ arrayContaining(systemAppId, hasProviderAppId, queriesProviderAppId));
+ }
+
+ private void assertThat(List<int[]> asList, Matcher<Integer[]> arrayContainingInAnyOrder) {
+ }
+
private interface WithSettingBuilder {
PackageSettingBuilder withBuilder(PackageSettingBuilder builder);
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
index 9cf6702..0a68688 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
@@ -18,6 +18,7 @@
import android.content.IIntentReceiver;
import android.os.Bundle;
+import android.util.SparseArray;
import androidx.test.runner.AndroidJUnit4;
@@ -47,7 +48,7 @@
public void sendPackageBroadcast(final String action, final String pkg,
final Bundle extras, final int flags, final String targetPkg,
final IIntentReceiver finishedReceiver, final int[] userIds,
- int[] instantUserIds) {
+ int[] instantUserIds, SparseArray<int[]> broadcastWhitelist) {
}
public void sendPackageAddedForNewUsers(String packageName,