Merge "[Output Switcher] Add group title" into tm-qpr-dev
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index b3435b1..63f7b8e 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -2405,6 +2405,29 @@
         */
     }
 
+    /**
+     * Perform a check on data paths and scheme specific parts of the intent filter.
+     * Return true if it passed.
+     * @hide
+     */
+    public boolean checkDataPathAndSchemeSpecificParts() {
+        final int numDataPath = mDataPaths == null
+                ? 0 : mDataPaths.size();
+        final int numDataSchemeSpecificParts = mDataSchemeSpecificParts == null
+                ? 0 : mDataSchemeSpecificParts.size();
+        for (int i = 0; i < numDataPath; i++) {
+            if (!mDataPaths.get(i).check()) {
+                return false;
+            }
+        }
+        for (int i = 0; i < numDataSchemeSpecificParts; i++) {
+            if (!mDataSchemeSpecificParts.get(i).check()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     /** @hide */
     public IntentFilter(Parcel source) {
         mActions = new ArrayList<String>();
diff --git a/core/java/android/os/PatternMatcher.java b/core/java/android/os/PatternMatcher.java
index 631c98a..b5425b4 100644
--- a/core/java/android/os/PatternMatcher.java
+++ b/core/java/android/os/PatternMatcher.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.util.Log;
 import android.util.proto.ProtoOutputStream;
 
 import java.util.Arrays;
@@ -151,6 +152,23 @@
         proto.end(token);
     }
 
+    /**
+     * Perform a check on the matcher for the pattern type of {@link #PATTERN_ADVANCED_GLOB}.
+     * Return true if it passed.
+     * @hide
+     */
+    public boolean check() {
+        try {
+            if (mType == PATTERN_ADVANCED_GLOB) {
+                return Arrays.equals(mParsedPattern, parseAndVerifyAdvancedPattern(mPattern));
+            }
+        } catch (IllegalArgumentException e) {
+            Log.w(TAG, "Failed to verify advanced pattern: " + e.getMessage());
+            return false;
+        }
+        return true;
+    }
+
     public int describeContents() {
         return 0;
     }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7787b7c..d83e40c 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -6100,7 +6100,7 @@
     <!-- @SystemApi Allows to access all app shortcuts.
          @hide -->
     <permission android:name="android.permission.ACCESS_SHORTCUTS"
-        android:protectionLevel="signature|role" />
+        android:protectionLevel="signature|role|recents" />
 
     <!-- @SystemApi Allows unlimited calls to shortcut mutation APIs.
          @hide -->
diff --git a/data/etc/com.android.launcher3.xml b/data/etc/com.android.launcher3.xml
index 36a5134..5616d1d 100644
--- a/data/etc/com.android.launcher3.xml
+++ b/data/etc/com.android.launcher3.xml
@@ -25,5 +25,6 @@
         <permission name="android.permission.START_TASKS_FROM_RECENTS"/>
         <permission name="android.permission.STATUS_BAR"/>
         <permission name="android.permission.STOP_APP_SWITCHES"/>
+        <permission name="android.permission.ACCESS_SHORTCUTS"/>
     </privapp-permissions>
 </permissions>
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 1ea0984..8d2714c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3395,6 +3395,11 @@
         enforceOwnerRights(snapshot, ownerPackage, callingUid);
         PackageManagerServiceUtils.enforceShellRestriction(mInjector.getUserManagerInternal(),
                 UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, sourceUserId);
+        if (!intentFilter.checkDataPathAndSchemeSpecificParts()) {
+            EventLog.writeEvent(0x534e4554, "246749936", callingUid);
+            throw new IllegalArgumentException("Invalid intent data paths or scheme specific parts"
+                    + " in the filter.");
+        }
         if (intentFilter.countActions() == 0) {
             Slog.w(TAG, "Cannot set a crossProfile intent filter with no filter actions");
             return;
diff --git a/services/core/java/com/android/server/pm/PreferredActivityHelper.java b/services/core/java/com/android/server/pm/PreferredActivityHelper.java
index 9befd6e..2b092b9 100644
--- a/services/core/java/com/android/server/pm/PreferredActivityHelper.java
+++ b/services/core/java/com/android/server/pm/PreferredActivityHelper.java
@@ -37,6 +37,7 @@
 import android.os.Process;
 import android.os.UserHandle;
 import android.text.TextUtils;
+import android.util.EventLog;
 import android.util.Log;
 import android.util.LogPrinter;
 import android.util.PrintStreamPrinter;
@@ -388,6 +389,11 @@
             throw new SecurityException(
                     "addPersistentPreferredActivity can only be run by the system");
         }
+        if (!filter.checkDataPathAndSchemeSpecificParts()) {
+            EventLog.writeEvent(0x534e4554, "246749702", callingUid);
+            throw new IllegalArgumentException("Invalid intent data paths or scheme specific parts"
+                    + " in the filter.");
+        }
         if (filter.countActions() == 0) {
             Slog.w(TAG, "Cannot set a preferred activity with no filter actions");
             return;
diff --git a/services/core/java/com/android/server/pm/WatchedIntentFilter.java b/services/core/java/com/android/server/pm/WatchedIntentFilter.java
index 5d7a2a3..09cf094 100644
--- a/services/core/java/com/android/server/pm/WatchedIntentFilter.java
+++ b/services/core/java/com/android/server/pm/WatchedIntentFilter.java
@@ -671,6 +671,13 @@
     }
 
     /**
+     * @see IntentFilter#checkDataPathAndSchemeSpecificParts()
+     */
+    public boolean checkDataPathAndSchemeSpecificParts() {
+        return mFilter.checkDataPathAndSchemeSpecificParts();
+    }
+
+    /**
      * @see IntentFilter#getHostsList()
      */
     public ArrayList<String> getHostsList() {