OSDN Git Service

Add new internal resolve method
authorTodd Kennedy <toddke@google.com>
Thu, 23 Feb 2017 18:32:18 +0000 (10:32 -0800)
committerTodd Kennedy <toddke@google.com>
Thu, 23 Feb 2017 23:38:55 +0000 (15:38 -0800)
Instant apps are unique in that any application can start them
with a VIEW/BROWSABLE while only very few apps can see an
instant app using queryIntentActivites, etc... In order to
support this dichotomy, we need an internal hook to resolution
for activity start.

Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.EphemeralTest
Bug: 25119046
Change-Id: If6974c09c733ff0417ef72cabb9d9e9aca86c37c

core/java/android/content/pm/PackageManagerInternal.java
services/core/java/com/android/server/am/ActivityStackSupervisor.java
services/core/java/com/android/server/pm/PackageManagerService.java
services/core/java/com/android/server/pm/Settings.java

index 94fe572..6272822 100644 (file)
@@ -306,4 +306,10 @@ public abstract class PackageManagerInternal {
      */
     public abstract boolean setEnabledOverlayPackages(int userId, String targetPackageName,
             List<String> overlayPackageNames);
+
+    /**
+     * Resolves an intent, allowing instant apps to be resolved.
+     */
+    public abstract ResolveInfo resolveIntent(Intent intent, String resolvedType,
+            int flags, int userId);
 }
index 1e33bb9..6f79bc2 100644 (file)
@@ -1196,13 +1196,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
     }
 
     ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags) {
-        try {
-            return AppGlobals.getPackageManager().resolveIntent(intent, resolvedType,
+        synchronized (mService) {
+            return mService.getPackageManagerInternalLocked().resolveIntent(intent, resolvedType,
                     PackageManager.MATCH_INSTANT | PackageManager.MATCH_DEFAULT_ONLY | flags
                     | ActivityManagerService.STOCK_PM_FLAGS, userId);
-        } catch (RemoteException e) {
         }
-        return null;
     }
 
     ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
index fe2fb66..33bd350 100644 (file)
@@ -4012,8 +4012,17 @@ public class PackageManagerService extends IPackageManager.Stub {
 
     /**
      * Update given flags when being used to request {@link ResolveInfo}.
+     * <p>Instant apps are resolved specially, depending upon context. Minimally,
+     * {@code}flags{@code} must have the {@link PackageManager#MATCH_INSTANT}
+     * flag set. However, this flag is only honoured in three circumstances:
+     * <ul>
+     * <li>when called from a system process</li>
+     * <li>when the caller holds the permission {@code android.permission.ACCESS_INSTANT_APPS}</li>
+     * <li>when resolution occurs to start an activity with a {@code android.intent.action.VIEW}
+     * action and a {@code android.intent.category.BROWSABLE} category</li>
+     * </ul>
      */
-    int updateFlagsForResolve(int flags, int userId, Object cookie) {
+    int updateFlagsForResolve(int flags, int userId, Intent intent, boolean includeInstantApp) {
         // Safe mode means we shouldn't match any third-party components
         if (mSafeMode) {
             flags |= PackageManager.MATCH_SYSTEM_ONLY;
@@ -4025,15 +4034,24 @@ public class PackageManagerService extends IPackageManager.Stub {
             flags |= PackageManager.MATCH_INSTANT;
         } else {
             // Otherwise, prevent leaking ephemeral components
+            final boolean isSpecialProcess =
+                    callingUid == Process.SYSTEM_UID
+                    || callingUid == Process.SHELL_UID
+                    || callingUid == 0;
+            final boolean allowMatchInstant =
+                    (includeInstantApp
+                            && Intent.ACTION_VIEW.equals(intent.getAction())
+                            && intent.hasCategory(Intent.CATEGORY_BROWSABLE)
+                            && hasWebURI(intent))
+                    || isSpecialProcess
+                    || mContext.checkCallingOrSelfPermission(
+                            android.Manifest.permission.ACCESS_INSTANT_APPS) == PERMISSION_GRANTED;
             flags &= ~PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY;
-            if (callingUid != Process.SYSTEM_UID
-                    && callingUid != Process.SHELL_UID
-                    && callingUid != 0) {
-                // Unless called from the system process
+            if (!allowMatchInstant) {
                 flags &= ~PackageManager.MATCH_INSTANT;
             }
         }
-        return updateFlagsForComponent(flags, userId, cookie);
+        return updateFlagsForComponent(flags, userId, intent /*cookie*/);
     }
 
     @Override
@@ -5558,17 +5576,23 @@ public class PackageManagerService extends IPackageManager.Stub {
     @Override
     public ResolveInfo resolveIntent(Intent intent, String resolvedType,
             int flags, int userId) {
+        return resolveIntentInternal(
+                intent, resolvedType, flags, userId, false /*includeInstantApp*/);
+    }
+
+    private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType,
+            int flags, int userId, boolean includeInstantApp) {
         try {
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");
 
             if (!sUserManager.exists(userId)) return null;
-            flags = updateFlagsForResolve(flags, userId, intent);
+            flags = updateFlagsForResolve(flags, userId, intent, includeInstantApp);
             enforceCrossUserPermission(Binder.getCallingUid(), userId,
                     false /*requireFullPermission*/, false /*checkShell*/, "resolve intent");
 
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
             final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
-                    flags, userId);
+                    flags, userId, includeInstantApp);
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
 
             final ResolveInfo bestChoice =
@@ -5590,7 +5614,7 @@ public class PackageManagerService extends IPackageManager.Stub {
         }
         intent = updateIntentForResolve(intent);
         final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
-        final int flags = updateFlagsForResolve(0, userId, intent);
+        final int flags = updateFlagsForResolve(0, userId, intent, false);
         final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags,
                 userId);
         synchronized (mPackages) {
@@ -5749,6 +5773,13 @@ public class PackageManagerService extends IPackageManager.Stub {
                 if (ri != null) {
                     return ri;
                 }
+                // If we have an ephemeral app, use it
+                for (int i = 0; i < N; i++) {
+                    ri = query.get(i);
+                    if (ri.activityInfo.applicationInfo.isInstantApp()) {
+                        return ri;
+                    }
+                }
                 ri = new ResolveInfo(mResolveInfo);
                 ri.activityInfo = new ActivityInfo(ri.activityInfo);
                 ri.activityInfo.labelRes = ResolverActivity.getLabelRes(intent.getAction());
@@ -5867,7 +5898,7 @@ public class PackageManagerService extends IPackageManager.Stub {
             List<ResolveInfo> query, int priority, boolean always,
             boolean removeMatches, boolean debug, int userId) {
         if (!sUserManager.exists(userId)) return null;
-        flags = updateFlagsForResolve(flags, userId, intent);
+        flags = updateFlagsForResolve(flags, userId, intent, false);
         intent = updateIntentForResolve(intent);
         // writer
         synchronized (mPackages) {
@@ -6035,7 +6066,7 @@ public class PackageManagerService extends IPackageManager.Stub {
             // cross-profile app linking works only towards the parent.
             final UserInfo parent = getProfileParent(sourceUserId);
             synchronized(mPackages) {
-                int flags = updateFlagsForResolve(0, parent.id, intent);
+                int flags = updateFlagsForResolve(0, parent.id, intent, false);
                 CrossProfileDomainInfo xpDomainInfo = getCrossProfileDomainPreferredLpr(
                         intent, resolvedType, flags, sourceUserId, parent.id);
                 return xpDomainInfo != null;
@@ -6094,9 +6125,14 @@ public class PackageManagerService extends IPackageManager.Stub {
 
     private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
             String resolvedType, int flags, int userId) {
+        return queryIntentActivitiesInternal(intent, resolvedType, flags, userId, false);
+    }
+
+    private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
+            String resolvedType, int flags, int userId, boolean includeInstantApp) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
         final String instantAppPkgName = getInstantAppPackageName(Binder.getCallingUid());
-        flags = updateFlagsForResolve(flags, userId, intent);
+        flags = updateFlagsForResolve(flags, userId, intent, includeInstantApp);
         enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 false /* requireFullPermission */, false /* checkShell */,
                 "query intent activities");
@@ -6723,7 +6759,7 @@ public class PackageManagerService extends IPackageManager.Stub {
             Intent[] specifics, String[] specificTypes, Intent intent,
             String resolvedType, int flags, int userId) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
-        flags = updateFlagsForResolve(flags, userId, intent);
+        flags = updateFlagsForResolve(flags, userId, intent, false);
         enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 false /* requireFullPermission */, false /* checkShell */,
                 "query intent activity options");
@@ -6903,7 +6939,7 @@ public class PackageManagerService extends IPackageManager.Stub {
     private @NonNull List<ResolveInfo> queryIntentReceiversInternal(Intent intent,
             String resolvedType, int flags, int userId) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
-        flags = updateFlagsForResolve(flags, userId, intent);
+        flags = updateFlagsForResolve(flags, userId, intent, false);
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -6940,7 +6976,7 @@ public class PackageManagerService extends IPackageManager.Stub {
     @Override
     public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
-        flags = updateFlagsForResolve(flags, userId, intent);
+        flags = updateFlagsForResolve(flags, userId, intent, false);
         List<ResolveInfo> query = queryIntentServicesInternal(intent, resolvedType, flags, userId);
         if (query != null) {
             if (query.size() >= 1) {
@@ -6962,7 +6998,7 @@ public class PackageManagerService extends IPackageManager.Stub {
     private @NonNull List<ResolveInfo> queryIntentServicesInternal(Intent intent,
             String resolvedType, int flags, int userId) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
-        flags = updateFlagsForResolve(flags, userId, intent);
+        flags = updateFlagsForResolve(flags, userId, intent, false);
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -7006,7 +7042,7 @@ public class PackageManagerService extends IPackageManager.Stub {
     private @NonNull List<ResolveInfo> queryIntentContentProvidersInternal(
             Intent intent, String resolvedType, int flags, int userId) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
-        flags = updateFlagsForResolve(flags, userId, intent);
+        flags = updateFlagsForResolve(flags, userId, intent, false);
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -23003,13 +23039,18 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
             return targetPackages;
         }
 
-
         @Override
         public boolean setEnabledOverlayPackages(int userId, String targetPackageName,
                 List<String> overlayPackageNames) {
             // TODO: implement when we integrate OMS properly
             return false;
         }
+
+        public ResolveInfo resolveIntent(Intent intent, String resolvedType,
+                int flags, int userId) {
+            return resolveIntentInternal(
+                    intent, resolvedType, flags, userId, true /*includeInstantApp*/);
+        }
     }
 
     @Override
index a8a5ff0..a057e9b 100644 (file)
@@ -3370,7 +3370,7 @@ final class Settings {
     private void applyDefaultPreferredActivityLPw(PackageManagerService service,
             Intent intent, int flags, ComponentName cn, String scheme, PatternMatcher ssp,
             IntentFilter.AuthorityEntry auth, PatternMatcher path, int userId) {
-        flags = service.updateFlagsForResolve(flags, userId, intent);
+        flags = service.updateFlagsForResolve(flags, userId, intent, false);
         List<ResolveInfo> ri = service.mActivities.queryIntent(intent,
                 intent.getType(), flags, 0);
         if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Queried " + intent