Merge changes from topic "ir_3P"

* changes:
  Changes in queryIntentAcitivities api for intent redirection
  Adding a new permission to interact across clone profile apps.
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 299bfa2..4e882d8 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -248,6 +248,7 @@
     field public static final String PROVIDE_TRUST_AGENT = "android.permission.PROVIDE_TRUST_AGENT";
     field public static final String PROVISION_DEMO_DEVICE = "android.permission.PROVISION_DEMO_DEVICE";
     field public static final String QUERY_ADMIN_POLICY = "android.permission.QUERY_ADMIN_POLICY";
+    field public static final String QUERY_CLONED_APPS = "android.permission.QUERY_CLONED_APPS";
     field @Deprecated public static final String QUERY_TIME_ZONE_RULES = "android.permission.QUERY_TIME_ZONE_RULES";
     field public static final String QUERY_USERS = "android.permission.QUERY_USERS";
     field public static final String RADIO_SCAN_WITHOUT_LOCATION = "android.permission.RADIO_SCAN_WITHOUT_LOCATION";
@@ -3793,6 +3794,7 @@
     field @Deprecated public static final int INTENT_FILTER_VERIFICATION_SUCCESS = 1; // 0x1
     field @Deprecated public static final int MASK_PERMISSION_FLAGS = 255; // 0xff
     field public static final int MATCH_ANY_USER = 4194304; // 0x400000
+    field public static final int MATCH_CLONE_PROFILE = 536870912; // 0x20000000
     field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000
     field public static final int MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS = 536870912; // 0x20000000
     field public static final int MATCH_INSTANT = 8388608; // 0x800000
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index da36da5..1a6f6b8 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -783,6 +783,7 @@
             GET_DISABLED_COMPONENTS,
             GET_DISABLED_UNTIL_USED_COMPONENTS,
             GET_UNINSTALLED_PACKAGES,
+            MATCH_CLONE_PROFILE
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ResolveInfoFlagsBits {}
@@ -1113,6 +1114,19 @@
     public static final int MATCH_DIRECT_BOOT_AUTO = 0x10000000;
 
     /**
+     * {@link ResolveInfo} flag: allow matching components across clone profile
+     * <p>
+     * This flag is used only for query and not resolution, the default behaviour would be to
+     * restrict querying across clone profile. This flag would be honored only if caller have
+     * permission {@link Manifest.permission.QUERY_CLONED_APPS}.
+     *
+     *  @hide
+     * <p>
+     */
+    @SystemApi
+    public static final int MATCH_CLONE_PROFILE = 0x20000000;
+
+    /**
      * {@link PackageInfo} flag: return all attributions declared in the package manifest
      */
     public static final int GET_ATTRIBUTIONS = 0x80000000;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3f18e5a..f74ebc4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -7040,6 +7040,15 @@
         android:protectionLevel="signature|knownSigner"
         android:knownCerts="@array/config_healthConnectMigrationKnownSigners" />
 
+    <!-- @SystemApi Allows an app to query apps in clone profile. The permission is
+         bidirectional in nature, i.e. cloned apps would be able to query apps in root user.
+         The permission is not meant for 3P apps as of now.
+         <p>Protection level: signature|privileged
+         @hide
+    -->
+    <permission android:name="android.permission.QUERY_CLONED_APPS"
+                android:protectionLevel="signature|privileged" />
+
     <!-- Attribution for Geofencing service. -->
     <attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/>
     <!-- Attribution for Country Detector. -->
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 2752104..c2f0f52 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -766,7 +766,7 @@
              */
             crossProfileResults = mCrossProfileIntentResolverEngine.resolveIntent(this, intent,
                     resolvedType, userId, flags, pkgName, hasNonNegativePriorityResult,
-                    mSettings::getPackage);
+                    resolveForStart, mSettings::getPackage);
             if (intent.hasWebURI() || !crossProfileResults.isEmpty()) sortResult = true;
         } else {
             final PackageStateInternal setting =
@@ -791,7 +791,7 @@
              */
             crossProfileResults = mCrossProfileIntentResolverEngine.resolveIntent(this, intent,
                     resolvedType, userId, flags, pkgName, false,
-                    mSettings::getPackage);
+                    resolveForStart, mSettings::getPackage);
         }
 
         /*
diff --git a/services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java b/services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java
index 397fdd8..e149b04 100644
--- a/services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java
+++ b/services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java
@@ -84,15 +84,16 @@
      * @param pkgName the application package name this Intent is limited to.
      * @param hasNonNegativePriorityResult signifies if current profile have any non-negative(active
      *                                     and valid) ResolveInfo in current profile.
+     * @param resolveForStart true if resolution occurs to start an activity.
      * @param pkgSettingFunction function to find PackageStateInternal for given package
      * @return list of {@link CrossProfileDomainInfo} from linked profiles.
      */
     public List<CrossProfileDomainInfo> resolveIntent(@NonNull Computer computer, Intent intent,
             String resolvedType, int userId, long flags, String pkgName,
-            boolean hasNonNegativePriorityResult,
+            boolean hasNonNegativePriorityResult, boolean resolveForStart,
             Function<String, PackageStateInternal> pkgSettingFunction) {
         return resolveIntentInternal(computer, intent, resolvedType, userId, userId, flags, pkgName,
-                hasNonNegativePriorityResult, pkgSettingFunction, null);
+                hasNonNegativePriorityResult, resolveForStart, pkgSettingFunction, null);
     }
 
     /**
@@ -113,13 +114,14 @@
      * @param pkgName the application package name this Intent is limited to.
      * @param hasNonNegativePriorityResult signifies if current profile have any non-negative(active
      *                                     and valid) ResolveInfo in current profile.
+     * @param resolveForStart true if resolution occurs to start an activity.
      * @param pkgSettingFunction function to find PackageStateInternal for given package
      * @param visitedUserIds users for which we have already performed resolution
      * @return list of {@link CrossProfileDomainInfo} from linked profiles.
      */
     private List<CrossProfileDomainInfo> resolveIntentInternal(@NonNull Computer computer,
             Intent intent, String resolvedType, int sourceUserId, int userId, long flags,
-            String pkgName, boolean hasNonNegativePriorityResult,
+            String pkgName, boolean hasNonNegativePriorityResult, boolean resolveForStart,
             Function<String, PackageStateInternal> pkgSettingFunction,
             Set<Integer> visitedUserIds) {
 
@@ -184,7 +186,8 @@
 
             // Choosing strategy based on source and target user
             CrossProfileResolver crossProfileResolver =
-                    chooseCrossProfileResolver(computer, userId, targetUserId);
+                    chooseCrossProfileResolver(computer, userId, targetUserId,
+                            resolveForStart, flags);
 
         /*
         If {@link CrossProfileResolver} is available for source,target pair we will call it to
@@ -217,8 +220,8 @@
                 if (allowChainedResolution) {
                     crossProfileDomainInfos.addAll(resolveIntentInternal(computer, intent,
                             resolvedType, sourceUserId, targetUserId, flags, pkgName,
-                            hasNonNegativePriority(crossProfileInfos), pkgSettingFunction,
-                            visitedUserIds));
+                            hasNonNegativePriority(crossProfileInfos), resolveForStart,
+                            pkgSettingFunction, visitedUserIds));
                 }
 
             }
@@ -233,18 +236,21 @@
      * @param computer {@link Computer} instance used for resolution by {@link ComponentResolverApi}
      * @param sourceUserId source user
      * @param targetUserId target user
+     * @param resolveForStart true if resolution occurs to start an activity.
+     * @param flags used for intent resolver selection
      * @return {@code CrossProfileResolver} which has value if source and target have
      * strategy configured otherwise null.
      */
     @SuppressWarnings("unused")
     private CrossProfileResolver chooseCrossProfileResolver(@NonNull Computer computer,
-            @UserIdInt int sourceUserId, @UserIdInt int targetUserId) {
+            @UserIdInt int sourceUserId, @UserIdInt int targetUserId, boolean resolveForStart,
+            long flags) {
         /**
          * If source or target user is clone profile, using {@link NoFilteringResolver}
          * We would return NoFilteringResolver only if it is allowed(feature flag is set).
          */
         if (shouldUseNoFilteringResolver(sourceUserId, targetUserId)) {
-            if (NoFilteringResolver.isIntentRedirectionAllowed()) {
+            if (NoFilteringResolver.isIntentRedirectionAllowed(mContext, resolveForStart, flags)) {
                 return new NoFilteringResolver(computer.getComponentResolver(),
                         mUserManager);
             } else {
@@ -384,7 +390,6 @@
              ephemeral activities.
              */
             candidates = resolveInfoFromCrossProfileDomainInfo(crossProfileCandidates);
-
             return new QueryIntentActivitiesResult(computer.applyPostResolutionFilter(candidates,
                     instantAppPkgName, allowDynamicSplits, filterCallingUid, resolveForStart,
                     userId, intent));
@@ -404,11 +409,10 @@
              */
             candidates = filterCandidatesWithDomainPreferredActivitiesLPr(computer, intent,
                     matchFlags, candidates, crossProfileCandidates, userId,
-                    areWebInstantAppsDisabled, pkgSettingFunction);
+                    areWebInstantAppsDisabled, resolveForStart, pkgSettingFunction);
         } else {
             candidates.addAll(resolveInfoFromCrossProfileDomainInfo(crossProfileCandidates));
         }
-
         return new QueryIntentActivitiesResult(sortResult, addInstant, candidates);
     }
 
@@ -421,13 +425,14 @@
      * @param crossProfileCandidates crossProfileDomainInfos from cross profile, it have ResolveInfo
      * @param userId user id of source user
      * @param areWebInstantAppsDisabled true if web instant apps are disabled
+     * @param resolveForStart true if intent is for resolution
      * @param pkgSettingFunction function to find PackageStateInternal for given package
      * @return list of ResolveInfo
      */
     private List<ResolveInfo> filterCandidatesWithDomainPreferredActivitiesLPr(Computer computer,
             Intent intent, long matchFlags, List<ResolveInfo> candidates,
             List<CrossProfileDomainInfo> crossProfileCandidates, int userId,
-            boolean areWebInstantAppsDisabled,
+            boolean areWebInstantAppsDisabled, boolean resolveForStart,
             Function<String, PackageStateInternal> pkgSettingFunction) {
         final boolean debug = (intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0;
 
@@ -439,7 +444,7 @@
         final List<ResolveInfo> result =
                 filterCandidatesWithDomainPreferredActivitiesLPrBody(computer, intent, matchFlags,
                         candidates, crossProfileCandidates, userId, areWebInstantAppsDisabled,
-                        debug, pkgSettingFunction);
+                        debug, resolveForStart, pkgSettingFunction);
 
         if (DEBUG_PREFERRED || DEBUG_DOMAIN_VERIFICATION) {
             Slog.v(TAG, "Filtered results with preferred activities. New candidates count: "
@@ -461,13 +466,14 @@
      * @param userId user id of source user
      * @param areWebInstantAppsDisabled true if web instant apps are disabled
      * @param debug true if resolution logs needed to be printed
+     * @param resolveForStart true if intent is for resolution
      * @param pkgSettingFunction function to find PackageStateInternal for given package
      * @return list of resolve infos
      */
     private List<ResolveInfo> filterCandidatesWithDomainPreferredActivitiesLPrBody(
             Computer computer, Intent intent, long matchFlags, List<ResolveInfo> candidates,
             List<CrossProfileDomainInfo> crossProfileCandidates, int userId,
-            boolean areWebInstantAppsDisabled, boolean debug,
+            boolean areWebInstantAppsDisabled, boolean debug, boolean resolveForStart,
             Function<String, PackageStateInternal> pkgSettingFunction) {
         final ArrayList<ResolveInfo> result = new ArrayList<>();
         final ArrayList<ResolveInfo> matchAllList = new ArrayList<>();
@@ -525,7 +531,7 @@
             // calling cross profile strategy to filter corresponding results
             result.addAll(filterCrossProfileCandidatesWithDomainPreferredActivities(computer,
                     intent, matchFlags, categorizeResolveInfoByTargetUser, userId,
-                    DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE));
+                    DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE, resolveForStart));
             includeBrowser = true;
         } else {
             Pair<List<ResolveInfo>, Integer> infosAndLevel = mDomainVerificationManager
@@ -539,7 +545,7 @@
                 // calling cross profile strategy to filter corresponding results
                 result.addAll(filterCrossProfileCandidatesWithDomainPreferredActivities(computer,
                         intent, matchFlags, categorizeResolveInfoByTargetUser, userId,
-                        DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE));
+                        DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE, resolveForStart));
             } else {
                 result.addAll(approvedInfos);
 
@@ -547,7 +553,7 @@
                 // calling cross profile strategy to filter corresponding results
                 result.addAll(filterCrossProfileCandidatesWithDomainPreferredActivities(computer,
                         intent, matchFlags, categorizeResolveInfoByTargetUser, userId,
-                        highestApproval));
+                        highestApproval, resolveForStart));
             }
         }
 
@@ -612,11 +618,13 @@
      *                                          CrossProfileDomainInfos
      * @param sourceUserId user id for intent
      * @param highestApprovalLevel domain approval level
+     * @param resolveForStart true if intent is for resolution
      * @return list of ResolveInfos
      */
     private List<ResolveInfo> filterCrossProfileCandidatesWithDomainPreferredActivities(
             Computer computer, Intent intent, long flags, SparseArray<List<CrossProfileDomainInfo>>
-            categorizeResolveInfoByTargetUser, int sourceUserId, int highestApprovalLevel) {
+            categorizeResolveInfoByTargetUser, int sourceUserId, int highestApprovalLevel,
+            boolean resolveForStart) {
 
         List<CrossProfileDomainInfo> crossProfileDomainInfos = new ArrayList<>();
 
@@ -629,7 +637,8 @@
                 // finding cross profile strategy based on source and target user
                 CrossProfileResolver crossProfileIntentResolver =
                         chooseCrossProfileResolver(computer, sourceUserId,
-                                categorizeResolveInfoByTargetUser.keyAt(index));
+                                categorizeResolveInfoByTargetUser.keyAt(index), resolveForStart,
+                                flags);
                 // if strategy is available call it and add its filtered results
                 if (crossProfileIntentResolver != null) {
                     crossProfileDomainInfos.addAll(crossProfileIntentResolver
diff --git a/services/core/java/com/android/server/pm/NoFilteringResolver.java b/services/core/java/com/android/server/pm/NoFilteringResolver.java
index 492f915..999706a 100644
--- a/services/core/java/com/android/server/pm/NoFilteringResolver.java
+++ b/services/core/java/com/android/server/pm/NoFilteringResolver.java
@@ -16,7 +16,10 @@
 
 package com.android.server.pm;
 
+import android.Manifest;
+import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.os.Binder;
 import android.provider.DeviceConfig;
@@ -47,13 +50,19 @@
 
     /**
      * Returns true if intent redirection for clone profile feature flag is set
-     * @return value of flag allow_intent_redirection_for_clone_profile
+     * and if its query, then check if calling user have necessary permission
+     * (android.permission.QUERY_CLONED_APPS) as well as required flag
+     * (PackageManager.MATCH_CLONE_PROFILE) bit set.
+     * @return true if resolver would be used for cross profile resolution.
      */
-    public static boolean isIntentRedirectionAllowed() {
+    public static boolean isIntentRedirectionAllowed(Context context,
+            boolean resolveForStart, long flags) {
         final long token = Binder.clearCallingIdentity();
         try {
             return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_APP_CLONING,
-                    FLAG_ALLOW_INTENT_REDIRECTION_FOR_CLONE_PROFILE, false /* defaultValue */);
+                    FLAG_ALLOW_INTENT_REDIRECTION_FOR_CLONE_PROFILE, false /* defaultValue */)
+                    && (resolveForStart || (((flags & PackageManager.MATCH_CLONE_PROFILE) != 0)
+                    && hasPermission(context, Manifest.permission.QUERY_CLONED_APPS)));
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -123,4 +132,15 @@
         // no filtering
         return crossProfileDomainInfos;
     }
+
+    /**
+     * Checks if calling uid have the mentioned permission
+     * @param context calling context
+     * @param permission permission name
+     * @return true if uid have the permission
+     */
+    private static boolean hasPermission(Context context, String permission) {
+        return context.checkCallingOrSelfPermission(permission)
+                == PackageManager.PERMISSION_GRANTED;
+    }
 }