Loading core/java/android/app/ActivityManagerInternal.java +16 −0 Original line number Original line Diff line number Diff line Loading @@ -403,4 +403,20 @@ public abstract class ActivityManagerInternal { * Called by DevicePolicyManagerService to set the uid of the device owner. * Called by DevicePolicyManagerService to set the uid of the device owner. */ */ public abstract void setDeviceOwnerUid(int uid); 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); } } services/core/java/com/android/server/am/ActivityManagerService.java +61 −5 Original line number Original line Diff line number Diff line Loading @@ -15568,7 +15568,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType, 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 // TODO: come back and remove this assumption to triage all broadcasts int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING; int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING; Loading Loading @@ -15644,6 +15644,15 @@ public class ActivityManagerService extends IActivityManager.Stub } catch (RemoteException ex) { } catch (RemoteException ex) { // pm is in same process, this will never happen. // 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; return receivers; } } Loading Loading @@ -15738,7 +15747,8 @@ public class ActivityManagerService extends IActivityManager.Stub return broadcastIntentLocked(callerApp, callerPackage, callerFeatureId, intent, return broadcastIntentLocked(callerApp, callerPackage, callerFeatureId, intent, resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions, resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions, appOp, bOptions, ordered, sticky, callingPid, callingUid, realCallingUid, appOp, bOptions, ordered, sticky, callingPid, callingUid, realCallingUid, realCallingPid, userId, false /* allowBackgroundActivityStarts */); realCallingPid, userId, false /* allowBackgroundActivityStarts */, null /*broadcastWhitelist*/); } } @GuardedBy("this") @GuardedBy("this") Loading @@ -15747,7 +15757,8 @@ public class ActivityManagerService extends IActivityManager.Stub IIntentReceiver resultTo, int resultCode, String resultData, IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions, Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions, boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid, 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); intent = new Intent(intent); final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid); final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid); Loading @@ -15756,6 +15767,12 @@ public class ActivityManagerService extends IActivityManager.Stub intent.setFlags(intent.getFlags() & ~Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS); 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. // By default broadcasts do not go to stopped apps. intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES); intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES); Loading Loading @@ -16242,7 +16259,8 @@ public class ActivityManagerService extends IActivityManager.Stub // Need to resolve the intent to interested receivers... // Need to resolve the intent to interested receivers... if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) { == 0) { receivers = collectReceiverComponents(intent, resolvedType, callingUid, users); receivers = collectReceiverComponents( intent, resolvedType, callingUid, users, broadcastWhitelist); } } if (intent.getComponent() == null) { if (intent.getComponent() == null) { if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) { if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) { Loading Loading @@ -16272,6 +16290,17 @@ public class ActivityManagerService extends IActivityManager.Stub if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing broadcast: " + intent.getAction() if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing broadcast: " + intent.getAction() + " replacePending=" + replacePending); + " 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; int NR = registeredReceivers != null ? registeredReceivers.size() : 0; if (!ordered && NR > 0) { if (!ordered && NR > 0) { Loading Loading @@ -16555,7 +16584,8 @@ public class ActivityManagerService extends IActivityManager.Stub return broadcastIntentLocked(null, packageName, featureId, intent, resolvedType, return broadcastIntentLocked(null, packageName, featureId, intent, resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions, resultTo, resultCode, resultData, resultExtras, requiredPermissions, OP_NONE, bOptions, serialized, sticky, -1, uid, realCallingUid, OP_NONE, bOptions, serialized, sticky, -1, uid, realCallingUid, realCallingPid, userId, allowBackgroundActivityStarts); realCallingPid, userId, allowBackgroundActivityStarts, null /*broadcastWhitelist*/); } finally { } finally { Binder.restoreCallingIdentity(origId); Binder.restoreCallingIdentity(origId); } } Loading Loading @@ -19185,6 +19215,32 @@ public class ActivityManagerService extends IActivityManager.Stub } } } } @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 @Override public ComponentName startServiceInPackage(int uid, Intent service, String resolvedType, public ComponentName startServiceInPackage(int uid, Intent service, String resolvedType, boolean fgRequired, String callingPackage, @Nullable String callingFeatureId, boolean fgRequired, String callingPackage, @Nullable String callingFeatureId, services/core/java/com/android/server/pm/AppsFilter.java +60 −1 Original line number Original line Diff line number Diff line Loading @@ -55,6 +55,7 @@ import com.android.server.om.OverlayReferenceMapper; import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.pm.parsing.pkg.AndroidPackage; import java.io.PrintWriter; import java.io.PrintWriter; import java.util.Arrays; import java.util.List; import java.util.List; import java.util.Objects; import java.util.Objects; import java.util.Set; import java.util.Set; Loading Loading @@ -510,6 +511,64 @@ public class AppsFilter { && 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; } /** /** * Removes a package for consideration when filtering visibility between apps. * Removes a package for consideration when filtering visibility between apps. * * Loading services/core/java/com/android/server/pm/PackageManagerService.java +93 −64 File changed.Preview size limit exceeded, changes collapsed. Show changes services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java +55 −0 Original line number Original line Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.pm; package com.android.server.pm; import static org.hamcrest.Matchers.arrayContaining; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any; Loading Loading @@ -47,6 +48,7 @@ import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.pm.parsing.pkg.PackageImpl; import com.android.server.pm.parsing.pkg.PackageImpl; import com.android.server.pm.parsing.pkg.ParsedPackage; import com.android.server.pm.parsing.pkg.ParsedPackage; import org.hamcrest.Matcher; import org.junit.Before; import org.junit.Before; import org.junit.Test; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runner.RunWith; Loading @@ -56,7 +58,9 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations; import java.security.cert.CertificateException; import java.security.cert.CertificateException; import java.util.Arrays; import java.util.Collections; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Map; import java.util.Set; import java.util.Set; Loading Loading @@ -635,6 +639,57 @@ public class AppsFilterTest { appsFilter.shouldFilterApplication(DUMMY_TARGET_UID, target, instrumentation, 0)); 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 { private interface WithSettingBuilder { PackageSettingBuilder withBuilder(PackageSettingBuilder builder); PackageSettingBuilder withBuilder(PackageSettingBuilder builder); } } Loading Loading
core/java/android/app/ActivityManagerInternal.java +16 −0 Original line number Original line Diff line number Diff line Loading @@ -403,4 +403,20 @@ public abstract class ActivityManagerInternal { * Called by DevicePolicyManagerService to set the uid of the device owner. * Called by DevicePolicyManagerService to set the uid of the device owner. */ */ public abstract void setDeviceOwnerUid(int uid); 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); } }
services/core/java/com/android/server/am/ActivityManagerService.java +61 −5 Original line number Original line Diff line number Diff line Loading @@ -15568,7 +15568,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType, 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 // TODO: come back and remove this assumption to triage all broadcasts int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING; int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING; Loading Loading @@ -15644,6 +15644,15 @@ public class ActivityManagerService extends IActivityManager.Stub } catch (RemoteException ex) { } catch (RemoteException ex) { // pm is in same process, this will never happen. // 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; return receivers; } } Loading Loading @@ -15738,7 +15747,8 @@ public class ActivityManagerService extends IActivityManager.Stub return broadcastIntentLocked(callerApp, callerPackage, callerFeatureId, intent, return broadcastIntentLocked(callerApp, callerPackage, callerFeatureId, intent, resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions, resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions, appOp, bOptions, ordered, sticky, callingPid, callingUid, realCallingUid, appOp, bOptions, ordered, sticky, callingPid, callingUid, realCallingUid, realCallingPid, userId, false /* allowBackgroundActivityStarts */); realCallingPid, userId, false /* allowBackgroundActivityStarts */, null /*broadcastWhitelist*/); } } @GuardedBy("this") @GuardedBy("this") Loading @@ -15747,7 +15757,8 @@ public class ActivityManagerService extends IActivityManager.Stub IIntentReceiver resultTo, int resultCode, String resultData, IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions, Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions, boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid, 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); intent = new Intent(intent); final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid); final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid); Loading @@ -15756,6 +15767,12 @@ public class ActivityManagerService extends IActivityManager.Stub intent.setFlags(intent.getFlags() & ~Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS); 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. // By default broadcasts do not go to stopped apps. intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES); intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES); Loading Loading @@ -16242,7 +16259,8 @@ public class ActivityManagerService extends IActivityManager.Stub // Need to resolve the intent to interested receivers... // Need to resolve the intent to interested receivers... if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) { == 0) { receivers = collectReceiverComponents(intent, resolvedType, callingUid, users); receivers = collectReceiverComponents( intent, resolvedType, callingUid, users, broadcastWhitelist); } } if (intent.getComponent() == null) { if (intent.getComponent() == null) { if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) { if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) { Loading Loading @@ -16272,6 +16290,17 @@ public class ActivityManagerService extends IActivityManager.Stub if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing broadcast: " + intent.getAction() if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing broadcast: " + intent.getAction() + " replacePending=" + replacePending); + " 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; int NR = registeredReceivers != null ? registeredReceivers.size() : 0; if (!ordered && NR > 0) { if (!ordered && NR > 0) { Loading Loading @@ -16555,7 +16584,8 @@ public class ActivityManagerService extends IActivityManager.Stub return broadcastIntentLocked(null, packageName, featureId, intent, resolvedType, return broadcastIntentLocked(null, packageName, featureId, intent, resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions, resultTo, resultCode, resultData, resultExtras, requiredPermissions, OP_NONE, bOptions, serialized, sticky, -1, uid, realCallingUid, OP_NONE, bOptions, serialized, sticky, -1, uid, realCallingUid, realCallingPid, userId, allowBackgroundActivityStarts); realCallingPid, userId, allowBackgroundActivityStarts, null /*broadcastWhitelist*/); } finally { } finally { Binder.restoreCallingIdentity(origId); Binder.restoreCallingIdentity(origId); } } Loading Loading @@ -19185,6 +19215,32 @@ public class ActivityManagerService extends IActivityManager.Stub } } } } @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 @Override public ComponentName startServiceInPackage(int uid, Intent service, String resolvedType, public ComponentName startServiceInPackage(int uid, Intent service, String resolvedType, boolean fgRequired, String callingPackage, @Nullable String callingFeatureId, boolean fgRequired, String callingPackage, @Nullable String callingFeatureId,
services/core/java/com/android/server/pm/AppsFilter.java +60 −1 Original line number Original line Diff line number Diff line Loading @@ -55,6 +55,7 @@ import com.android.server.om.OverlayReferenceMapper; import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.pm.parsing.pkg.AndroidPackage; import java.io.PrintWriter; import java.io.PrintWriter; import java.util.Arrays; import java.util.List; import java.util.List; import java.util.Objects; import java.util.Objects; import java.util.Set; import java.util.Set; Loading Loading @@ -510,6 +511,64 @@ public class AppsFilter { && 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; } /** /** * Removes a package for consideration when filtering visibility between apps. * Removes a package for consideration when filtering visibility between apps. * * Loading
services/core/java/com/android/server/pm/PackageManagerService.java +93 −64 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java +55 −0 Original line number Original line Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.pm; package com.android.server.pm; import static org.hamcrest.Matchers.arrayContaining; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any; Loading Loading @@ -47,6 +48,7 @@ import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.pm.parsing.pkg.PackageImpl; import com.android.server.pm.parsing.pkg.PackageImpl; import com.android.server.pm.parsing.pkg.ParsedPackage; import com.android.server.pm.parsing.pkg.ParsedPackage; import org.hamcrest.Matcher; import org.junit.Before; import org.junit.Before; import org.junit.Test; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runner.RunWith; Loading @@ -56,7 +58,9 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations; import java.security.cert.CertificateException; import java.security.cert.CertificateException; import java.util.Arrays; import java.util.Collections; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Map; import java.util.Set; import java.util.Set; Loading Loading @@ -635,6 +639,57 @@ public class AppsFilterTest { appsFilter.shouldFilterApplication(DUMMY_TARGET_UID, target, instrumentation, 0)); 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 { private interface WithSettingBuilder { PackageSettingBuilder withBuilder(PackageSettingBuilder builder); PackageSettingBuilder withBuilder(PackageSettingBuilder builder); } } Loading