Loading core/java/android/app/ActivityManager.java +11 −1 Original line number Diff line number Diff line Loading @@ -4216,13 +4216,23 @@ public class ActivityManager { } }*/ /** @hide * Determines whether the given UID can access unexported components * @param uid the calling UID * @return true if the calling UID is ROOT or SYSTEM */ public static boolean canAccessUnexportedComponents(int uid) { final int appId = UserHandle.getAppId(uid); return (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID); } /** @hide */ @UnsupportedAppUsage public static int checkComponentPermission(String permission, int uid, int owningUid, boolean exported) { // Root, system server get to do everything. final int appId = UserHandle.getAppId(uid); if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) { if (canAccessUnexportedComponents(uid)) { return PackageManager.PERMISSION_GRANTED; } // Isolated processes don't get any permissions. Loading services/core/java/android/content/pm/PackageManagerInternal.java +8 −0 Original line number Diff line number Diff line Loading @@ -576,6 +576,14 @@ public abstract class PackageManagerInternal { @PrivateResolveFlags long privateResolveFlags, int userId, boolean resolveForStart, int filterCallingUid); /** * Resolves an exported activity intent, allowing instant apps to be resolved. */ public abstract ResolveInfo resolveIntentExported(Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, @PrivateResolveFlags long privateResolveFlags, int userId, boolean resolveForStart, int filterCallingUid); /** * Resolves a service intent, allowing instant apps to be resolved. */ Loading services/core/java/com/android/server/am/ActivityManagerService.java +68 −0 Original line number Diff line number Diff line Loading @@ -215,6 +215,7 @@ import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetManagerInternal; import android.compat.annotation.ChangeId; import android.compat.annotation.Disabled; import android.compat.annotation.EnabledAfter; import android.content.AttributionSource; import android.content.AutofillOptions; import android.content.BroadcastReceiver; Loading Loading @@ -584,6 +585,17 @@ public class ActivityManagerService extends IActivityManager.Stub @Disabled private static final long DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED = 161145287L; /** * Apps targeting Android U and above will need to export components in order to invoke them * through implicit intents. * * If a component is not exported and invoked, it will be removed from the list of receivers. * This applies specifically to activities and broadcasts. */ @ChangeId @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU) public static final long IMPLICIT_INTENTS_ONLY_MATCH_EXPORTED_COMPONENTS = 229362273; /** * The maximum number of bytes that {@link #setProcessStateSummary} accepts. * Loading Loading @@ -12378,6 +12390,58 @@ public class ActivityManagerService extends IActivityManager.Stub return false; } /** * Filters out non-exported components in a given list of broadcast filters * @param intent the original intent * @param callingUid the calling UID * @param query the list of broadcast filters * @param platformCompat the instance of platform compat */ private static void filterNonExportedComponents(Intent intent, int callingUid, List query, PlatformCompat platformCompat, String callerPackage) { if (query == null || intent.getPackage() != null || intent.getComponent() != null || ActivityManager.canAccessUnexportedComponents(callingUid)) { return; } for (int i = query.size() - 1; i >= 0; i--) { String componentInfo; ResolveInfo resolveInfo; BroadcastFilter broadcastFilter; if (query.get(i) instanceof ResolveInfo) { resolveInfo = (ResolveInfo) query.get(i); if (resolveInfo.getComponentInfo().exported) { continue; } componentInfo = resolveInfo.getComponentInfo() .getComponentName().flattenToShortString(); } else if (query.get(i) instanceof BroadcastFilter) { broadcastFilter = (BroadcastFilter) query.get(i); if (broadcastFilter.exported) { continue; } componentInfo = broadcastFilter.packageName; } else { continue; } if (!platformCompat.isChangeEnabledByUid( IMPLICIT_INTENTS_ONLY_MATCH_EXPORTED_COMPONENTS, callingUid)) { Slog.w(TAG, "Non-exported component not filtered out " + "(will be filtered out once the app targets U+)- intent: " + intent.getAction() + ", component: " + componentInfo + ", sender: " + callerPackage); return; } Slog.w(TAG, "Non-exported component filtered out - intent: " + intent.getAction() + ", component: " + componentInfo + ", sender: " + callerPackage); query.remove(i); } } /** * Main code for cleaning up a process when it has gone away. This is * called both as a result of the process dying, or directly when stopping Loading Loading @@ -14217,6 +14281,8 @@ public class ActivityManagerService extends IActivityManager.Stub } } filterNonExportedComponents(intent, callingUid, registeredReceivers, mPlatformCompat, callerPackage); int NR = registeredReceivers != null ? registeredReceivers.size() : 0; if (!ordered && NR > 0) { // If we are not serializing this broadcast, then send the Loading Loading @@ -14319,6 +14385,8 @@ public class ActivityManagerService extends IActivityManager.Stub if ((receivers != null && receivers.size() > 0) || resultTo != null) { BroadcastQueue queue = broadcastQueueForIntent(intent); filterNonExportedComponents(intent, callingUid, receivers, mPlatformCompat, callerPackage); BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType, requiredPermissions, excludedPermissions, excludedPackages, appOp, brOptions, services/core/java/com/android/server/pm/PackageManagerInternalBase.java +14 −0 Original line number Diff line number Diff line Loading @@ -465,6 +465,20 @@ abstract class PackageManagerInternalBase extends PackageManagerInternal { filterCallingUid); } /** * @deprecated similar to {@link resolveIntent} but limits the matches to exported components. */ @Override @Deprecated public final ResolveInfo resolveIntentExported(Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags, int userId, boolean resolveForStart, int filterCallingUid) { return getResolveIntentHelper().resolveIntentInternal(snapshot(), intent, resolvedType, flags, privateResolveFlags, userId, resolveForStart, filterCallingUid, true); } @Override @Deprecated public final ResolveInfo resolveService(Intent intent, String resolvedType, Loading services/core/java/com/android/server/pm/ResolveIntentHelper.java +51 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import android.util.Slog; import com.android.internal.app.ResolverActivity; import com.android.internal.util.ArrayUtils; import com.android.server.am.ActivityManagerService; import com.android.server.compat.PlatformCompat; import com.android.server.pm.pkg.AndroidPackage; import com.android.server.pm.pkg.PackageStateInternal; Loading Loading @@ -100,6 +101,38 @@ final class ResolveIntentHelper { mInstantAppInstallerActivitySupplier = instantAppInstallerActivitySupplier; } private static void filterNonExportedComponents(Intent intent, int filterCallingUid, List<ResolveInfo> query, PlatformCompat platformCompat, Computer computer) { if (query == null || intent.getPackage() != null || intent.getComponent() != null || ActivityManager.canAccessUnexportedComponents(filterCallingUid)) { return; } AndroidPackage caller = computer.getPackage(filterCallingUid); String callerPackage = caller == null ? "Not specified" : caller.getPackageName(); for (int i = query.size() - 1; i >= 0; i--) { if (!query.get(i).getComponentInfo().exported) { if (!platformCompat.isChangeEnabledByUid( ActivityManagerService.IMPLICIT_INTENTS_ONLY_MATCH_EXPORTED_COMPONENTS, filterCallingUid)) { Slog.w(TAG, "Non-exported component not filtered out " + "(will be filtered out once the app targets U+)- intent: " + intent.getAction() + ", component: " + query.get(i).getComponentInfo() .getComponentName().flattenToShortString() + ", starter: " + callerPackage); return; } Slog.w(TAG, "Non-exported component filtered out - intent: " + intent.getAction() + ", component: " + query.get(i).getComponentInfo().getComponentName().flattenToShortString() + ", starter: " + callerPackage); query.remove(i); } } } /** * Normally instant apps can only be resolved when they're visible to the caller. * However, if {@code resolveForStart} is {@code true}, all instant apps are visible Loading @@ -109,6 +142,20 @@ final class ResolveIntentHelper { @PackageManager.ResolveInfoFlagsBits long flags, @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags, int userId, boolean resolveForStart, int filterCallingUid) { return resolveIntentInternal(computer, intent, resolvedType, flags, privateResolveFlags, userId, resolveForStart, filterCallingUid, false); } /** * Normally instant apps can only be resolved when they're visible to the caller. * However, if {@code resolveForStart} is {@code true}, all instant apps are visible * since we need to allow the system to start any installed application. * Allows picking exported components only. */ public ResolveInfo resolveIntentInternal(Computer computer, Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags, int userId, boolean resolveForStart, int filterCallingUid, boolean exportedComponentsOnly) { try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent"); Loading @@ -124,6 +171,10 @@ final class ResolveIntentHelper { final List<ResolveInfo> query = computer.queryIntentActivitiesInternal(intent, resolvedType, flags, privateResolveFlags, filterCallingUid, userId, resolveForStart, true /*allowDynamicSplits*/); if (exportedComponentsOnly) { filterNonExportedComponents(intent, filterCallingUid, query, mPlatformCompat, computer); } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); final boolean queryMayBeFiltered = Loading Loading
core/java/android/app/ActivityManager.java +11 −1 Original line number Diff line number Diff line Loading @@ -4216,13 +4216,23 @@ public class ActivityManager { } }*/ /** @hide * Determines whether the given UID can access unexported components * @param uid the calling UID * @return true if the calling UID is ROOT or SYSTEM */ public static boolean canAccessUnexportedComponents(int uid) { final int appId = UserHandle.getAppId(uid); return (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID); } /** @hide */ @UnsupportedAppUsage public static int checkComponentPermission(String permission, int uid, int owningUid, boolean exported) { // Root, system server get to do everything. final int appId = UserHandle.getAppId(uid); if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) { if (canAccessUnexportedComponents(uid)) { return PackageManager.PERMISSION_GRANTED; } // Isolated processes don't get any permissions. Loading
services/core/java/android/content/pm/PackageManagerInternal.java +8 −0 Original line number Diff line number Diff line Loading @@ -576,6 +576,14 @@ public abstract class PackageManagerInternal { @PrivateResolveFlags long privateResolveFlags, int userId, boolean resolveForStart, int filterCallingUid); /** * Resolves an exported activity intent, allowing instant apps to be resolved. */ public abstract ResolveInfo resolveIntentExported(Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, @PrivateResolveFlags long privateResolveFlags, int userId, boolean resolveForStart, int filterCallingUid); /** * Resolves a service intent, allowing instant apps to be resolved. */ Loading
services/core/java/com/android/server/am/ActivityManagerService.java +68 −0 Original line number Diff line number Diff line Loading @@ -215,6 +215,7 @@ import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetManagerInternal; import android.compat.annotation.ChangeId; import android.compat.annotation.Disabled; import android.compat.annotation.EnabledAfter; import android.content.AttributionSource; import android.content.AutofillOptions; import android.content.BroadcastReceiver; Loading Loading @@ -584,6 +585,17 @@ public class ActivityManagerService extends IActivityManager.Stub @Disabled private static final long DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED = 161145287L; /** * Apps targeting Android U and above will need to export components in order to invoke them * through implicit intents. * * If a component is not exported and invoked, it will be removed from the list of receivers. * This applies specifically to activities and broadcasts. */ @ChangeId @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU) public static final long IMPLICIT_INTENTS_ONLY_MATCH_EXPORTED_COMPONENTS = 229362273; /** * The maximum number of bytes that {@link #setProcessStateSummary} accepts. * Loading Loading @@ -12378,6 +12390,58 @@ public class ActivityManagerService extends IActivityManager.Stub return false; } /** * Filters out non-exported components in a given list of broadcast filters * @param intent the original intent * @param callingUid the calling UID * @param query the list of broadcast filters * @param platformCompat the instance of platform compat */ private static void filterNonExportedComponents(Intent intent, int callingUid, List query, PlatformCompat platformCompat, String callerPackage) { if (query == null || intent.getPackage() != null || intent.getComponent() != null || ActivityManager.canAccessUnexportedComponents(callingUid)) { return; } for (int i = query.size() - 1; i >= 0; i--) { String componentInfo; ResolveInfo resolveInfo; BroadcastFilter broadcastFilter; if (query.get(i) instanceof ResolveInfo) { resolveInfo = (ResolveInfo) query.get(i); if (resolveInfo.getComponentInfo().exported) { continue; } componentInfo = resolveInfo.getComponentInfo() .getComponentName().flattenToShortString(); } else if (query.get(i) instanceof BroadcastFilter) { broadcastFilter = (BroadcastFilter) query.get(i); if (broadcastFilter.exported) { continue; } componentInfo = broadcastFilter.packageName; } else { continue; } if (!platformCompat.isChangeEnabledByUid( IMPLICIT_INTENTS_ONLY_MATCH_EXPORTED_COMPONENTS, callingUid)) { Slog.w(TAG, "Non-exported component not filtered out " + "(will be filtered out once the app targets U+)- intent: " + intent.getAction() + ", component: " + componentInfo + ", sender: " + callerPackage); return; } Slog.w(TAG, "Non-exported component filtered out - intent: " + intent.getAction() + ", component: " + componentInfo + ", sender: " + callerPackage); query.remove(i); } } /** * Main code for cleaning up a process when it has gone away. This is * called both as a result of the process dying, or directly when stopping Loading Loading @@ -14217,6 +14281,8 @@ public class ActivityManagerService extends IActivityManager.Stub } } filterNonExportedComponents(intent, callingUid, registeredReceivers, mPlatformCompat, callerPackage); int NR = registeredReceivers != null ? registeredReceivers.size() : 0; if (!ordered && NR > 0) { // If we are not serializing this broadcast, then send the Loading Loading @@ -14319,6 +14385,8 @@ public class ActivityManagerService extends IActivityManager.Stub if ((receivers != null && receivers.size() > 0) || resultTo != null) { BroadcastQueue queue = broadcastQueueForIntent(intent); filterNonExportedComponents(intent, callingUid, receivers, mPlatformCompat, callerPackage); BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType, requiredPermissions, excludedPermissions, excludedPackages, appOp, brOptions,
services/core/java/com/android/server/pm/PackageManagerInternalBase.java +14 −0 Original line number Diff line number Diff line Loading @@ -465,6 +465,20 @@ abstract class PackageManagerInternalBase extends PackageManagerInternal { filterCallingUid); } /** * @deprecated similar to {@link resolveIntent} but limits the matches to exported components. */ @Override @Deprecated public final ResolveInfo resolveIntentExported(Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags, int userId, boolean resolveForStart, int filterCallingUid) { return getResolveIntentHelper().resolveIntentInternal(snapshot(), intent, resolvedType, flags, privateResolveFlags, userId, resolveForStart, filterCallingUid, true); } @Override @Deprecated public final ResolveInfo resolveService(Intent intent, String resolvedType, Loading
services/core/java/com/android/server/pm/ResolveIntentHelper.java +51 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import android.util.Slog; import com.android.internal.app.ResolverActivity; import com.android.internal.util.ArrayUtils; import com.android.server.am.ActivityManagerService; import com.android.server.compat.PlatformCompat; import com.android.server.pm.pkg.AndroidPackage; import com.android.server.pm.pkg.PackageStateInternal; Loading Loading @@ -100,6 +101,38 @@ final class ResolveIntentHelper { mInstantAppInstallerActivitySupplier = instantAppInstallerActivitySupplier; } private static void filterNonExportedComponents(Intent intent, int filterCallingUid, List<ResolveInfo> query, PlatformCompat platformCompat, Computer computer) { if (query == null || intent.getPackage() != null || intent.getComponent() != null || ActivityManager.canAccessUnexportedComponents(filterCallingUid)) { return; } AndroidPackage caller = computer.getPackage(filterCallingUid); String callerPackage = caller == null ? "Not specified" : caller.getPackageName(); for (int i = query.size() - 1; i >= 0; i--) { if (!query.get(i).getComponentInfo().exported) { if (!platformCompat.isChangeEnabledByUid( ActivityManagerService.IMPLICIT_INTENTS_ONLY_MATCH_EXPORTED_COMPONENTS, filterCallingUid)) { Slog.w(TAG, "Non-exported component not filtered out " + "(will be filtered out once the app targets U+)- intent: " + intent.getAction() + ", component: " + query.get(i).getComponentInfo() .getComponentName().flattenToShortString() + ", starter: " + callerPackage); return; } Slog.w(TAG, "Non-exported component filtered out - intent: " + intent.getAction() + ", component: " + query.get(i).getComponentInfo().getComponentName().flattenToShortString() + ", starter: " + callerPackage); query.remove(i); } } } /** * Normally instant apps can only be resolved when they're visible to the caller. * However, if {@code resolveForStart} is {@code true}, all instant apps are visible Loading @@ -109,6 +142,20 @@ final class ResolveIntentHelper { @PackageManager.ResolveInfoFlagsBits long flags, @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags, int userId, boolean resolveForStart, int filterCallingUid) { return resolveIntentInternal(computer, intent, resolvedType, flags, privateResolveFlags, userId, resolveForStart, filterCallingUid, false); } /** * Normally instant apps can only be resolved when they're visible to the caller. * However, if {@code resolveForStart} is {@code true}, all instant apps are visible * since we need to allow the system to start any installed application. * Allows picking exported components only. */ public ResolveInfo resolveIntentInternal(Computer computer, Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags, int userId, boolean resolveForStart, int filterCallingUid, boolean exportedComponentsOnly) { try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent"); Loading @@ -124,6 +171,10 @@ final class ResolveIntentHelper { final List<ResolveInfo> query = computer.queryIntentActivitiesInternal(intent, resolvedType, flags, privateResolveFlags, filterCallingUid, userId, resolveForStart, true /*allowDynamicSplits*/); if (exportedComponentsOnly) { filterNonExportedComponents(intent, filterCallingUid, query, mPlatformCompat, computer); } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); final boolean queryMayBeFiltered = Loading