Merge changes from topic "presubmit-am-77aaf4d1c96d4bd0bf1f886d74ab8a9c" into sc-qpr1-dev

* changes:
  [automerge] Make sure parallel broadcasts enforce excluded permissions 2p: 0eee4fa476
  Make sure parallel broadcasts enforce excluded permissions
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index 9572808..d1e3481 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -104,6 +104,7 @@
 import android.text.format.DateFormat;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.EventLog;
 import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.util.LongArrayQueue;
@@ -2031,7 +2032,11 @@
                                 + " reached for uid: " + UserHandle.formatUid(callingUid)
                                 + ", callingPackage: " + callingPackage;
                 Slog.w(TAG, errorMsg);
-                throw new IllegalStateException(errorMsg);
+                if (callingUid != Process.SYSTEM_UID) {
+                    throw new IllegalStateException(errorMsg);
+                } else {
+                    EventLog.writeEvent(0x534e4554, "234441463", -1, errorMsg);
+                }
             }
             setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, interval, operation,
                     directReceiver, listenerTag, flags, workSource, alarmClock, callingUid,
diff --git a/core/java/android/accounts/Account.java b/core/java/android/accounts/Account.java
index e6cdcc0..0d6a079 100644
--- a/core/java/android/accounts/Account.java
+++ b/core/java/android/accounts/Account.java
@@ -31,7 +31,6 @@
 
 import com.android.internal.annotations.GuardedBy;
 
-import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -87,12 +86,6 @@
         if (TextUtils.isEmpty(type)) {
             throw new IllegalArgumentException("the type must not be empty: " + type);
         }
-        if (name.length() > 200) {
-            throw new IllegalArgumentException("account name is longer than 200 characters");
-        }
-        if (type.length() > 200) {
-            throw new IllegalArgumentException("account type is longer than 200 characters");
-        }
         this.name = name;
         this.type = type;
         this.accessId = accessId;
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index d932a29..fc89e13 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -2463,8 +2463,8 @@
      * restriction} for a certain app-op.
      */
     private static RestrictionBypass[] sOpAllowSystemRestrictionBypass = new RestrictionBypass[] {
-            new RestrictionBypass(true, false), //COARSE_LOCATION
-            new RestrictionBypass(true, false), //FINE_LOCATION
+            new RestrictionBypass(true, false, false), //COARSE_LOCATION
+            new RestrictionBypass(true, false, false), //FINE_LOCATION
             null, //GPS
             null, //VIBRATE
             null, //READ_CONTACTS
@@ -2473,7 +2473,7 @@
             null, //WRITE_CALL_LOG
             null, //READ_CALENDAR
             null, //WRITE_CALENDAR
-            new RestrictionBypass(true, false), //WIFI_SCAN
+            new RestrictionBypass(false, true, false), //WIFI_SCAN
             null, //POST_NOTIFICATION
             null, //NEIGHBORING_CELLS
             null, //CALL_PHONE
@@ -2487,10 +2487,10 @@
             null, //READ_ICC_SMS
             null, //WRITE_ICC_SMS
             null, //WRITE_SETTINGS
-            new RestrictionBypass(true, false), //SYSTEM_ALERT_WINDOW
+            new RestrictionBypass(false, true, false), //SYSTEM_ALERT_WINDOW
             null, //ACCESS_NOTIFICATIONS
             null, //CAMERA
-            new RestrictionBypass(false, true), //RECORD_AUDIO
+            new RestrictionBypass(false, false, true), //RECORD_AUDIO
             null, //PLAY_AUDIO
             null, //READ_CLIPBOARD
             null, //WRITE_CLIPBOARD
@@ -2508,7 +2508,7 @@
             null, //MONITOR_HIGH_POWER_LOCATION
             null, //GET_USAGE_STATS
             null, //MUTE_MICROPHONE
-            new RestrictionBypass(true, false), //TOAST_WINDOW
+            new RestrictionBypass(false, true, false), //TOAST_WINDOW
             null, //PROJECT_MEDIA
             null, //ACTIVATE_VPN
             null, //WALLPAPER
@@ -2540,7 +2540,7 @@
             null, // ACCEPT_HANDOVER
             null, // MANAGE_IPSEC_HANDOVERS
             null, // START_FOREGROUND
-            new RestrictionBypass(true, false), // BLUETOOTH_SCAN
+            new RestrictionBypass(false, true, false), // BLUETOOTH_SCAN
             null, // USE_BIOMETRIC
             null, // ACTIVITY_RECOGNITION
             null, // SMS_FINANCIAL_TRANSACTIONS
@@ -3105,6 +3105,9 @@
      * @hide
      */
     public static class RestrictionBypass {
+        /** Does the app need to be system uid to bypass the restriction */
+        public boolean isSystemUid;
+
         /** Does the app need to be privileged to bypass the restriction */
         public boolean isPrivileged;
 
@@ -3114,12 +3117,14 @@
          */
         public boolean isRecordAudioRestrictionExcept;
 
-        public RestrictionBypass(boolean isPrivileged, boolean isRecordAudioRestrictionExcept) {
+        public RestrictionBypass(boolean isSystemUid, boolean isPrivileged,
+                boolean isRecordAudioRestrictionExcept) {
+            this.isSystemUid = isSystemUid;
             this.isPrivileged = isPrivileged;
             this.isRecordAudioRestrictionExcept = isRecordAudioRestrictionExcept;
         }
 
-        public static RestrictionBypass UNRESTRICTED = new RestrictionBypass(true, true);
+        public static RestrictionBypass UNRESTRICTED = new RestrictionBypass(false, true, true);
     }
 
     /**
diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java
index 7a806bd..27a9a27 100644
--- a/core/java/android/app/AutomaticZenRule.java
+++ b/core/java/android/app/AutomaticZenRule.java
@@ -48,6 +48,13 @@
     private String mPkg;
 
     /**
+     * The maximum string length for any string contained in this automatic zen rule. This pertains
+     * both to fields in the rule itself (such as its name) and items with sub-fields.
+     * @hide
+     */
+    public static final int MAX_STRING_LENGTH = 1000;
+
+    /**
      * Creates an automatic zen rule.
      *
      * @param name The name of the rule.
@@ -93,10 +100,10 @@
     public AutomaticZenRule(@NonNull String name, @Nullable ComponentName owner,
             @Nullable ComponentName configurationActivity, @NonNull Uri conditionId,
             @Nullable ZenPolicy policy, int interruptionFilter, boolean enabled) {
-        this.name = name;
-        this.owner = owner;
-        this.configurationActivity = configurationActivity;
-        this.conditionId = conditionId;
+        this.name = getTrimmedString(name);
+        this.owner = getTrimmedComponentName(owner);
+        this.configurationActivity = getTrimmedComponentName(configurationActivity);
+        this.conditionId = getTrimmedUri(conditionId);
         this.interruptionFilter = interruptionFilter;
         this.enabled = enabled;
         this.mZenPolicy = policy;
@@ -115,12 +122,12 @@
     public AutomaticZenRule(Parcel source) {
         enabled = source.readInt() == ENABLED;
         if (source.readInt() == ENABLED) {
-            name = source.readString();
+            name = getTrimmedString(source.readString());
         }
         interruptionFilter = source.readInt();
         conditionId = source.readParcelable(null);
-        owner = source.readParcelable(null);
-        configurationActivity = source.readParcelable(null);
+        owner = getTrimmedComponentName(source.readParcelable(null));
+        configurationActivity = getTrimmedComponentName(source.readParcelable(null));
         creationTime = source.readLong();
         mZenPolicy = source.readParcelable(null);
         mModified = source.readInt() == ENABLED;
@@ -196,7 +203,7 @@
      * Sets the representation of the state that causes this rule to become active.
      */
     public void setConditionId(Uri conditionId) {
-        this.conditionId = conditionId;
+        this.conditionId = getTrimmedUri(conditionId);
     }
 
     /**
@@ -211,7 +218,7 @@
      * Sets the name of this rule.
      */
     public void setName(String name) {
-        this.name = name;
+        this.name = getTrimmedString(name);
     }
 
     /**
@@ -243,7 +250,7 @@
      * that are not backed by {@link android.service.notification.ConditionProviderService}.
      */
     public void setConfigurationActivity(@Nullable ComponentName componentName) {
-        this.configurationActivity = componentName;
+        this.configurationActivity = getTrimmedComponentName(componentName);
     }
 
     /**
@@ -333,4 +340,35 @@
             return new AutomaticZenRule[size];
         }
     };
+
+    /**
+     * If the package or class name of the provided ComponentName are longer than MAX_STRING_LENGTH,
+     * return a trimmed version that truncates each of the package and class name at the max length.
+     */
+    private static ComponentName getTrimmedComponentName(ComponentName cn) {
+        if (cn == null) return null;
+        return new ComponentName(getTrimmedString(cn.getPackageName()),
+                getTrimmedString(cn.getClassName()));
+    }
+
+    /**
+     * Returns a truncated copy of the string if the string is longer than MAX_STRING_LENGTH.
+     */
+    private static String getTrimmedString(String input) {
+        if (input != null && input.length() > MAX_STRING_LENGTH) {
+            return input.substring(0, MAX_STRING_LENGTH);
+        }
+        return input;
+    }
+
+    /**
+     * Returns a truncated copy of the Uri by trimming the string representation to the maximum
+     * string length.
+     */
+    private static Uri getTrimmedUri(Uri input) {
+        if (input != null && input.toString().length() > MAX_STRING_LENGTH) {
+            return Uri.parse(getTrimmedString(input.toString()));
+        }
+        return input;
+    }
 }
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 6553b61..748f874 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -124,8 +124,13 @@
     /**
      * The maximum length for text fields in a NotificationChannel. Fields will be truncated at this
      * limit.
+     * @hide
      */
-    private static final int MAX_TEXT_LENGTH = 1000;
+    public static final int MAX_TEXT_LENGTH = 1000;
+    /**
+     * @hide
+     */
+    public static final int MAX_VIBRATION_LENGTH = 1000;
 
     private static final String TAG_CHANNEL = "channel";
     private static final String ATT_NAME = "name";
@@ -284,17 +289,17 @@
      */
     protected NotificationChannel(Parcel in) {
         if (in.readByte() != 0) {
-            mId = in.readString();
+            mId = getTrimmedString(in.readString());
         } else {
             mId = null;
         }
         if (in.readByte() != 0) {
-            mName = in.readString();
+            mName = getTrimmedString(in.readString());
         } else {
             mName = null;
         }
         if (in.readByte() != 0) {
-            mDesc = in.readString();
+            mDesc = getTrimmedString(in.readString());
         } else {
             mDesc = null;
         }
@@ -303,18 +308,22 @@
         mLockscreenVisibility = in.readInt();
         if (in.readByte() != 0) {
             mSound = Uri.CREATOR.createFromParcel(in);
+            mSound = Uri.parse(getTrimmedString(mSound.toString()));
         } else {
             mSound = null;
         }
         mLights = in.readByte() != 0;
         mVibration = in.createLongArray();
+        if (mVibration != null && mVibration.length > MAX_VIBRATION_LENGTH) {
+            mVibration = Arrays.copyOf(mVibration, MAX_VIBRATION_LENGTH);
+        }
         mUserLockedFields = in.readInt();
         mFgServiceShown = in.readByte() != 0;
         mVibrationEnabled = in.readByte() != 0;
         mShowBadge = in.readByte() != 0;
         mDeleted = in.readByte() != 0;
         if (in.readByte() != 0) {
-            mGroup = in.readString();
+            mGroup = getTrimmedString(in.readString());
         } else {
             mGroup = null;
         }
@@ -324,8 +333,8 @@
         mAllowBubbles = in.readInt();
         mImportanceLockedByOEM = in.readBoolean();
         mOriginalImportance = in.readInt();
-        mParentId = in.readString();
-        mConversationId = in.readString();
+        mParentId = getTrimmedString(in.readString());
+        mConversationId = getTrimmedString(in.readString());
         mDemoted = in.readBoolean();
         mImportantConvo = in.readBoolean();
         mDeletedTime = in.readLong();
diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java
index cd6df0b..c194a28 100644
--- a/core/java/android/app/NotificationChannelGroup.java
+++ b/core/java/android/app/NotificationChannelGroup.java
@@ -43,8 +43,9 @@
     /**
      * The maximum length for text fields in a NotificationChannelGroup. Fields will be truncated at
      * this limit.
+     * @hide
      */
-    private static final int MAX_TEXT_LENGTH = 1000;
+    public static final int MAX_TEXT_LENGTH = 1000;
 
     private static final String TAG_GROUP = "channelGroup";
     private static final String ATT_NAME = "name";
@@ -90,13 +91,14 @@
      */
     protected NotificationChannelGroup(Parcel in) {
         if (in.readByte() != 0) {
-            mId = in.readString();
+            mId = getTrimmedString(in.readString());
         } else {
             mId = null;
         }
         mName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+        mName = getTrimmedString(mName.toString());
         if (in.readByte() != 0) {
-            mDescription = in.readString();
+            mDescription = getTrimmedString(in.readString());
         } else {
             mDescription = null;
         }
@@ -120,7 +122,7 @@
         } else {
             dest.writeByte((byte) 0);
         }
-        TextUtils.writeToParcel(mName, dest, flags);
+        TextUtils.writeToParcel(mName.toString(), dest, flags);
         if (mDescription != null) {
             dest.writeByte((byte) 1);
             dest.writeString(mDescription);
diff --git a/core/tests/coretests/src/android/app/AutomaticZenRuleTest.java b/core/tests/coretests/src/android/app/AutomaticZenRuleTest.java
new file mode 100644
index 0000000..282fdad
--- /dev/null
+++ b/core/tests/coretests/src/android/app/AutomaticZenRuleTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.fail;
+
+import android.content.ComponentName;
+import android.net.Uri;
+import android.os.Parcel;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.google.common.base.Strings;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Field;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class AutomaticZenRuleTest {
+    private static final String CLASS = "android.app.AutomaticZenRule";
+
+    @Test
+    public void testLongFields_inConstructor() {
+        String longString = Strings.repeat("A", 65536);
+        Uri longUri = Uri.parse("uri://" + Strings.repeat("A", 65530));
+
+        // test both variants where there's an owner, and where there's a configuration activity
+        AutomaticZenRule rule1 = new AutomaticZenRule(
+                longString, // name
+                new ComponentName("pkg", longString), // owner
+                null,  // configuration activity
+                longUri, // conditionId
+                null, // zen policy
+                0, // interruption filter
+                true); // enabled
+
+        assertEquals(AutomaticZenRule.MAX_STRING_LENGTH, rule1.getName().length());
+        assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+                rule1.getConditionId().toString().length());
+        assertEquals(AutomaticZenRule.MAX_STRING_LENGTH, rule1.getOwner().getClassName().length());
+
+        AutomaticZenRule rule2 = new AutomaticZenRule(
+                longString, // name
+                null, // owner
+                new ComponentName(longString, "SomeClassName"), // configuration activity
+                longUri, // conditionId
+                null, // zen policy
+                0, // interruption filter
+                false); // enabled
+
+        assertEquals(AutomaticZenRule.MAX_STRING_LENGTH, rule2.getName().length());
+        assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+                rule2.getConditionId().toString().length());
+        assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+                rule2.getConfigurationActivity().getPackageName().length());
+    }
+
+    @Test
+    public void testLongFields_inSetters() {
+        String longString = Strings.repeat("A", 65536);
+        Uri longUri = Uri.parse("uri://" + Strings.repeat("A", 65530));
+
+        AutomaticZenRule rule = new AutomaticZenRule(
+                "sensible name",
+                new ComponentName("pkg", "ShortClass"),
+                null,
+                Uri.parse("uri://short"),
+                null, 0, true);
+
+        rule.setName(longString);
+        rule.setConditionId(longUri);
+        rule.setConfigurationActivity(new ComponentName(longString, longString));
+
+        assertEquals(AutomaticZenRule.MAX_STRING_LENGTH, rule.getName().length());
+        assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+                rule.getConditionId().toString().length());
+        assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+                rule.getConfigurationActivity().getPackageName().length());
+        assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+                rule.getConfigurationActivity().getClassName().length());
+    }
+
+    @Test
+    public void testLongInputsFromParcel() {
+        // Create a rule with long fields, set directly via reflection so that we can confirm that
+        // a rule with too-long fields that comes in via a parcel has its fields truncated directly.
+        AutomaticZenRule rule = new AutomaticZenRule(
+                "placeholder",
+                new ComponentName("place", "holder"),
+                null,
+                Uri.parse("uri://placeholder"),
+                null, 0, true);
+
+        try {
+            String longString = Strings.repeat("A", 65536);
+            Uri longUri = Uri.parse("uri://" + Strings.repeat("A", 65530));
+            Field name = Class.forName(CLASS).getDeclaredField("name");
+            name.setAccessible(true);
+            name.set(rule, longString);
+            Field conditionId = Class.forName(CLASS).getDeclaredField("conditionId");
+            conditionId.setAccessible(true);
+            conditionId.set(rule, longUri);
+            Field owner = Class.forName(CLASS).getDeclaredField("owner");
+            owner.setAccessible(true);
+            owner.set(rule, new ComponentName(longString, longString));
+            Field configActivity = Class.forName(CLASS).getDeclaredField("configurationActivity");
+            configActivity.setAccessible(true);
+            configActivity.set(rule, new ComponentName(longString, longString));
+        } catch (NoSuchFieldException e) {
+            fail(e.toString());
+        } catch (ClassNotFoundException e) {
+            fail(e.toString());
+        } catch (IllegalAccessException e) {
+            fail(e.toString());
+        }
+
+        Parcel parcel = Parcel.obtain();
+        rule.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+
+        AutomaticZenRule fromParcel = new AutomaticZenRule(parcel);
+        assertEquals(AutomaticZenRule.MAX_STRING_LENGTH, fromParcel.getName().length());
+        assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+                fromParcel.getConditionId().toString().length());
+        assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+                fromParcel.getConfigurationActivity().getPackageName().length());
+        assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+                fromParcel.getConfigurationActivity().getClassName().length());
+        assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+                fromParcel.getOwner().getPackageName().length());
+        assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+                fromParcel.getOwner().getClassName().length());
+    }
+}
diff --git a/core/tests/coretests/src/android/app/NotificationChannelGroupTest.java b/core/tests/coretests/src/android/app/NotificationChannelGroupTest.java
new file mode 100644
index 0000000..2a3da05
--- /dev/null
+++ b/core/tests/coretests/src/android/app/NotificationChannelGroupTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import static junit.framework.TestCase.assertEquals;
+
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.google.common.base.Strings;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Field;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NotificationChannelGroupTest {
+    private final String CLASS = "android.app.NotificationChannelGroup";
+
+    @Test
+    public void testLongStringFields() {
+        NotificationChannelGroup group = new NotificationChannelGroup("my_group_01", "groupName");
+
+        try {
+            String longString = Strings.repeat("A", 65536);
+            Field mName = Class.forName(CLASS).getDeclaredField("mName");
+            mName.setAccessible(true);
+            mName.set(group, longString);
+            Field mId = Class.forName(CLASS).getDeclaredField("mId");
+            mId.setAccessible(true);
+            mId.set(group, longString);
+            Field mDescription = Class.forName(CLASS).getDeclaredField("mDescription");
+            mDescription.setAccessible(true);
+            mDescription.set(group, longString);
+        } catch (NoSuchFieldException e) {
+            e.printStackTrace();
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+        }
+
+        Parcel parcel = Parcel.obtain();
+        group.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+
+        NotificationChannelGroup fromParcel =
+                NotificationChannelGroup.CREATOR.createFromParcel(parcel);
+        assertEquals(NotificationChannelGroup.MAX_TEXT_LENGTH, fromParcel.getId().length());
+        assertEquals(NotificationChannelGroup.MAX_TEXT_LENGTH, fromParcel.getName().length());
+        assertEquals(NotificationChannelGroup.MAX_TEXT_LENGTH,
+                fromParcel.getDescription().length());
+    }
+}
diff --git a/core/tests/coretests/src/android/app/NotificationChannelTest.java b/core/tests/coretests/src/android/app/NotificationChannelTest.java
new file mode 100644
index 0000000..647bfe8
--- /dev/null
+++ b/core/tests/coretests/src/android/app/NotificationChannelTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import static junit.framework.TestCase.assertEquals;
+
+import android.net.Uri;
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.google.common.base.Strings;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Field;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NotificationChannelTest {
+    private final String CLASS = "android.app.NotificationChannel";
+
+    @Test
+    public void testLongStringFields() {
+        NotificationChannel channel = new NotificationChannel("id", "name", 3);
+
+        try {
+            String longString = Strings.repeat("A", 65536);
+            Field mName = Class.forName(CLASS).getDeclaredField("mName");
+            mName.setAccessible(true);
+            mName.set(channel, longString);
+            Field mId = Class.forName(CLASS).getDeclaredField("mId");
+            mId.setAccessible(true);
+            mId.set(channel, longString);
+            Field mDesc = Class.forName(CLASS).getDeclaredField("mDesc");
+            mDesc.setAccessible(true);
+            mDesc.set(channel, longString);
+            Field mParentId = Class.forName(CLASS).getDeclaredField("mParentId");
+            mParentId.setAccessible(true);
+            mParentId.set(channel, longString);
+            Field mGroup = Class.forName(CLASS).getDeclaredField("mGroup");
+            mGroup.setAccessible(true);
+            mGroup.set(channel, longString);
+            Field mConversationId = Class.forName(CLASS).getDeclaredField("mConversationId");
+            mConversationId.setAccessible(true);
+            mConversationId.set(channel, longString);
+        } catch (NoSuchFieldException e) {
+            e.printStackTrace();
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+        }
+
+        Parcel parcel = Parcel.obtain();
+        channel.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+
+        NotificationChannel fromParcel = NotificationChannel.CREATOR.createFromParcel(parcel);
+        assertEquals(NotificationChannel.MAX_TEXT_LENGTH, fromParcel.getId().length());
+        assertEquals(NotificationChannel.MAX_TEXT_LENGTH, fromParcel.getName().length());
+        assertEquals(NotificationChannel.MAX_TEXT_LENGTH,
+                fromParcel.getDescription().length());
+        assertEquals(NotificationChannel.MAX_TEXT_LENGTH,
+                fromParcel.getParentChannelId().length());
+        assertEquals(NotificationChannel.MAX_TEXT_LENGTH,
+                fromParcel.getGroup().length());
+        assertEquals(NotificationChannel.MAX_TEXT_LENGTH,
+                fromParcel.getConversationId().length());
+    }
+
+    @Test
+    public void testLongAlertFields() {
+        NotificationChannel channel = new NotificationChannel("id", "name", 3);
+
+        channel.setSound(Uri.parse("content://" + Strings.repeat("A",65536)),
+                Notification.AUDIO_ATTRIBUTES_DEFAULT);
+        channel.setVibrationPattern(new long[65550/2]);
+
+        Parcel parcel = Parcel.obtain();
+        channel.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+
+        NotificationChannel fromParcel = NotificationChannel.CREATOR.createFromParcel(parcel);
+        assertEquals(NotificationChannel.MAX_VIBRATION_LENGTH,
+                fromParcel.getVibrationPattern().length);
+        assertEquals(NotificationChannel.MAX_TEXT_LENGTH,
+                fromParcel.getSound().toString().length());
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java b/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
index c346142..f9584a3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
@@ -21,8 +21,6 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
@@ -85,7 +83,6 @@
     private static final int DEFAULT_PHOTO_SIZE = 500;
 
     private static final String IMAGES_DIR = "multi_user";
-    private static final String PRE_CROP_PICTURE_FILE_NAME = "PreCropEditUserPhoto.jpg";
     private static final String CROP_PICTURE_FILE_NAME = "CropEditUserPhoto.jpg";
     private static final String TAKE_PICTURE_FILE_NAME = "TakeEditUserPhoto.jpg";
     private static final String NEW_USER_PHOTO_FILE_NAME = "NewUserPhoto.png";
@@ -98,7 +95,6 @@
     private final String mFileAuthority;
 
     private final File mImagesDir;
-    private final Uri mPreCropPictureUri;
     private final Uri mCropPictureUri;
     private final Uri mTakePictureUri;
 
@@ -114,7 +110,6 @@
 
         mImagesDir = new File(activity.getCacheDir(), IMAGES_DIR);
         mImagesDir.mkdir();
-        mPreCropPictureUri = createTempImageUri(activity, PRE_CROP_PICTURE_FILE_NAME, !waiting);
         mCropPictureUri = createTempImageUri(activity, CROP_PICTURE_FILE_NAME, !waiting);
         mTakePictureUri = createTempImageUri(activity, TAKE_PICTURE_FILE_NAME, !waiting);
         mPhotoSize = getPhotoSize(activity);
@@ -148,7 +143,7 @@
             case REQUEST_CODE_CHOOSE_PHOTO:
                 if (mTakePictureUri.equals(pictureUri)) {
                     if (PhotoCapabilityUtils.canCropPhoto(mActivity)) {
-                        cropPhoto(pictureUri);
+                        cropPhoto();
                     } else {
                         onPhotoNotCropped(pictureUri);
                     }
@@ -229,7 +224,7 @@
             protected Void doInBackground(Void... params) {
                 final ContentResolver cr = mActivity.getContentResolver();
                 try (InputStream in = cr.openInputStream(pictureUri);
-                        OutputStream out = cr.openOutputStream(mPreCropPictureUri)) {
+                     OutputStream out = cr.openOutputStream(mTakePictureUri)) {
                     Streams.copy(in, out);
                 } catch (IOException e) {
                     Log.w(TAG, "Failed to copy photo", e);
@@ -240,41 +235,28 @@
             @Override
             protected void onPostExecute(Void result) {
                 if (!mActivity.isFinishing() && !mActivity.isDestroyed()) {
-                    cropPhoto(mPreCropPictureUri);
+                    cropPhoto();
                 }
             }
         }.execute();
     }
 
-    private void cropPhoto(final Uri pictureUri) {
+    private void cropPhoto() {
         // TODO: Use a public intent, when there is one.
         Intent intent = new Intent("com.android.camera.action.CROP");
-        intent.setDataAndType(pictureUri, "image/*");
+        intent.setDataAndType(mTakePictureUri, "image/*");
         appendOutputExtra(intent, mCropPictureUri);
         appendCropExtras(intent);
-        try {
-            StrictMode.disableDeathOnFileUriExposure();
-            if (startSystemActivityForResult(intent, REQUEST_CODE_CROP_PHOTO)) {
-                return;
+        if (intent.resolveActivity(mActivity.getPackageManager()) != null) {
+            try {
+                StrictMode.disableDeathOnFileUriExposure();
+                mActivityStarter.startActivityForResult(intent, REQUEST_CODE_CROP_PHOTO);
+            } finally {
+                StrictMode.enableDeathOnFileUriExposure();
             }
-        } finally {
-            StrictMode.enableDeathOnFileUriExposure();
+        } else {
+            onPhotoNotCropped(mTakePictureUri);
         }
-
-        onPhotoNotCropped(mTakePictureUri);
-
-    }
-
-    private boolean startSystemActivityForResult(Intent intent, int code) {
-        ActivityInfo info = intent.resolveActivityInfo(mActivity.getPackageManager(),
-                PackageManager.MATCH_SYSTEM_ONLY);
-        if (info == null) {
-            Log.w(TAG, "No system package activity could be found for code " + code);
-            return false;
-        }
-        intent.setPackage(info.packageName);
-        mActivityStarter.startActivityForResult(intent, code);
-        return true;
     }
 
     private void appendOutputExtra(Intent intent, Uri pictureUri) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
index 433d5e1..8313299 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
@@ -175,9 +175,86 @@
      */
     @Override
     public boolean shouldLaunchFullScreenIntentWhenAdded(NotificationEntry entry) {
-        return entry.getSbn().getNotification().fullScreenIntent != null
-                && (!shouldHeadsUp(entry)
-                || mStatusBarStateController.getState() == StatusBarState.KEYGUARD);
+        if (entry.getSbn().getNotification().fullScreenIntent == null) {
+            return false;
+        }
+
+        // Never show FSI when suppressed by DND
+        if (entry.shouldSuppressFullScreenIntent()) {
+            if (DEBUG) {
+                Log.d(TAG, "No FullScreenIntent: Suppressed by DND: " + entry.getKey());
+            }
+            return false;
+        }
+
+        // Never show FSI if importance is not HIGH
+        if (entry.getImportance() < NotificationManager.IMPORTANCE_HIGH) {
+            if (DEBUG) {
+                Log.d(TAG, "No FullScreenIntent: Not important enough: " + entry.getKey());
+            }
+            return false;
+        }
+
+        // If the notification has suppressive GroupAlertBehavior, block FSI and warn.
+        StatusBarNotification sbn = entry.getSbn();
+        if (sbn.isGroup() && sbn.getNotification().suppressAlertingDueToGrouping()) {
+            // b/231322873: Detect and report an event when a notification has both an FSI and a
+            // suppressive groupAlertBehavior, and now correctly block the FSI from firing.
+            final int uid = entry.getSbn().getUid();
+            android.util.EventLog.writeEvent(0x534e4554, "231322873", uid, "groupAlertBehavior");
+            if (DEBUG) {
+                Log.w(TAG, "No FullScreenIntent: WARNING: GroupAlertBehavior will prevent HUN: "
+                        + entry.getKey());
+            }
+            return false;
+        }
+
+        // If the screen is off, then launch the FullScreenIntent
+        if (!mPowerManager.isInteractive()) {
+            if (DEBUG) {
+                Log.d(TAG, "FullScreenIntent: Device is not interactive: " + entry.getKey());
+            }
+            return true;
+        }
+
+        // If the device is currently dreaming, then launch the FullScreenIntent
+        if (isDreaming()) {
+            if (DEBUG) {
+                Log.d(TAG, "FullScreenIntent: Device is dreaming: " + entry.getKey());
+            }
+            return true;
+        }
+
+        // If the keyguard is showing, then launch the FullScreenIntent
+        if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
+            if (DEBUG) {
+                Log.d(TAG, "FullScreenIntent: Keyguard is showing: " + entry.getKey());
+            }
+            return true;
+        }
+
+        // If the notification should HUN, then we don't need FSI
+        if (shouldHeadsUp(entry)) {
+            if (DEBUG) {
+                Log.d(TAG, "No FullScreenIntent: Expected to HUN: " + entry.getKey());
+            }
+            return false;
+        }
+
+        // If the notification won't HUN for some other reason (DND/snooze/etc), launch FSI.
+        if (DEBUG) {
+            Log.d(TAG, "FullScreenIntent: Expected not to HUN: " + entry.getKey());
+        }
+        return true;
+    }
+
+    private boolean isDreaming() {
+        try {
+            return mDreamManager.isDreaming();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to query dream manager.", e);
+            return false;
+        }
     }
 
     private boolean shouldHeadsUpWhenAwake(NotificationEntry entry) {
@@ -228,13 +305,7 @@
             return false;
         }
 
-        boolean isDreaming = false;
-        try {
-            isDreaming = mDreamManager.isDreaming();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to query dream manager.", e);
-        }
-        boolean inUse = mPowerManager.isScreenOn() && !isDreaming;
+        boolean inUse = mPowerManager.isScreenOn() && !isDreaming();
 
         if (!inUse) {
             if (DEBUG_HEADS_UP) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 1e92ca9..31a2b5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -330,6 +330,13 @@
     };
 
     /**
+     * Recalculate sensitiveness without animation; called when waking up while keyguard occluded.
+     */
+    public void updateSensitivenessForOccludedWakeup() {
+        mView.updateSensitiveness(false, mLockscreenUserManager.isAnyProfilePublicMode());
+    }
+
+    /**
      * Set the overexpansion of the panel to be applied to the view.
      */
     public void setOverExpansion(float overExpansion) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 88434cc..9ebc2f5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -4159,6 +4159,17 @@
             mWakeUpCoordinator.setFullyAwake(true);
             mBypassHeadsUpNotifier.setFullyAwake(true);
             mWakeUpCoordinator.setWakingUp(false);
+            if (isOccluded() && !mDozeParameters.canControlUnlockedScreenOff()) {
+                // When the keyguard is occluded we don't use the KEYGUARD state which would
+                // normally cause these redaction updates.  If AOD is on, the KEYGUARD state is used
+                // to show the doze, AND UnlockedScreenOffAnimationController.onFinishedWakingUp()
+                // would force a KEYGUARD state that would take care of recalculating redaction.
+                // So if AOD is off or unsupported we need to trigger these updates at screen on
+                // when the keyguard is occluded.
+                mLockscreenUserManager.updatePublicMode();
+                mNotificationPanelViewController.getNotificationStackScrollLayoutController()
+                        .updateSensitivenessForOccludedWakeup();
+            }
             if (mLaunchCameraWhenFinishedWaking) {
                 mNotificationPanelViewController.launchCamera(
                         false /* animate */, mLastCameraLaunchSource);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
index 60c3bc8..440f76a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
@@ -24,6 +24,7 @@
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
 
 import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking;
+import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
 import static com.android.systemui.statusbar.StatusBarState.SHADE;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -84,6 +85,8 @@
     BatteryController mBatteryController;
     @Mock
     Handler mMockHandler;
+    @Mock
+    PendingIntent mPendingIntent;
 
     private NotificationInterruptStateProviderImpl mNotifInterruptionStateProvider;
 
@@ -399,6 +402,97 @@
         assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isFalse();
     }
 
+    @Test
+    public void testShouldNotFullScreen_notPendingIntent() throws RemoteException {
+        NotificationEntry entry = createNotification(IMPORTANCE_HIGH);
+        when(mPowerManager.isInteractive()).thenReturn(true);
+        when(mDreamManager.isDreaming()).thenReturn(false);
+        when(mStatusBarStateController.getState()).thenReturn(SHADE);
+
+        assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
+                .isFalse();
+    }
+
+    @Test
+    public void testShouldNotFullScreen_notHighImportance() throws RemoteException {
+        NotificationEntry entry = createFsiNotification(IMPORTANCE_DEFAULT, /* silenced */ false);
+        when(mPowerManager.isInteractive()).thenReturn(true);
+        when(mDreamManager.isDreaming()).thenReturn(false);
+        when(mStatusBarStateController.getState()).thenReturn(SHADE);
+
+        assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
+                .isFalse();
+    }
+
+    @Test
+    public void testShouldNotFullScreen_isGroupAlertSilenced() throws RemoteException {
+        NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ true);
+        when(mPowerManager.isInteractive()).thenReturn(false);
+        when(mDreamManager.isDreaming()).thenReturn(true);
+        when(mStatusBarStateController.getState()).thenReturn(KEYGUARD);
+
+        assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
+                .isFalse();
+    }
+
+    @Test
+    public void testShouldFullScreen_notInteractive() throws RemoteException {
+        NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
+        when(mPowerManager.isInteractive()).thenReturn(false);
+        when(mDreamManager.isDreaming()).thenReturn(false);
+        when(mStatusBarStateController.getState()).thenReturn(SHADE);
+
+        assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
+                .isTrue();
+    }
+
+    @Test
+    public void testShouldFullScreen_isDreaming() throws RemoteException {
+        NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
+        when(mPowerManager.isInteractive()).thenReturn(true);
+        when(mDreamManager.isDreaming()).thenReturn(true);
+        when(mStatusBarStateController.getState()).thenReturn(SHADE);
+
+        assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
+                .isTrue();
+    }
+
+    @Test
+    public void testShouldFullScreen_onKeyguard() throws RemoteException {
+        NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
+        when(mPowerManager.isInteractive()).thenReturn(true);
+        when(mDreamManager.isDreaming()).thenReturn(false);
+        when(mStatusBarStateController.getState()).thenReturn(KEYGUARD);
+
+        assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
+                .isTrue();
+    }
+
+    @Test
+    public void testShouldNotFullScreen_willHun() throws RemoteException {
+        NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
+        when(mPowerManager.isInteractive()).thenReturn(true);
+        when(mPowerManager.isScreenOn()).thenReturn(true);
+        when(mDreamManager.isDreaming()).thenReturn(false);
+        when(mStatusBarStateController.getState()).thenReturn(SHADE);
+
+        assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
+                .isFalse();
+    }
+
+    @Test
+    public void testShouldFullScreen_packageSnoozed() throws RemoteException {
+        NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
+        when(mPowerManager.isInteractive()).thenReturn(true);
+        when(mPowerManager.isScreenOn()).thenReturn(true);
+        when(mDreamManager.isDreaming()).thenReturn(false);
+        when(mStatusBarStateController.getState()).thenReturn(SHADE);
+        when(mHeadsUpManager.isSnoozed("a")).thenReturn(true);
+
+        assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
+                .isTrue();
+    }
+
     /**
      * Bubbles can happen.
      */
@@ -503,6 +597,10 @@
                 .setContentText("content text")
                 .build();
 
+        return createNotification(importance, n);
+    }
+
+    private NotificationEntry createNotification(int importance, Notification n) {
         return new NotificationEntryBuilder()
                 .setPkg("a")
                 .setOpPkg("a")
@@ -512,6 +610,20 @@
                 .build();
     }
 
+    private NotificationEntry createFsiNotification(int importance, boolean silent) {
+        Notification n = new Notification.Builder(getContext(), "a")
+                .setContentTitle("title")
+                .setContentText("content text")
+                .setFullScreenIntent(mPendingIntent, true)
+                .setGroup("fsi")
+                .setGroupAlertBehavior(silent
+                        ? Notification.GROUP_ALERT_SUMMARY
+                        : Notification.GROUP_ALERT_ALL)
+                .build();
+
+        return createNotification(importance, n);
+    }
+
     private final NotificationInterruptSuppressor
             mSuppressAwakeHeadsUp =
             new NotificationInterruptSuppressor() {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 400b084..ae2f934 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -1819,6 +1819,14 @@
         if (account == null) {
             return false;
         }
+        if (account.name != null && account.name.length() > 200) {
+            Log.w(TAG, "Account cannot be added - Name longer than 200 chars");
+            return false;
+        }
+        if (account.type != null && account.type.length() > 200) {
+            Log.w(TAG, "Account cannot be added - Name longer than 200 chars");
+            return false;
+        }
         if (!isLocalUnlockedUser(accounts.userId)) {
             Log.w(TAG, "Account " + account.toSafeString() + " cannot be added - user "
                     + accounts.userId + " is locked. callingUid=" + callingUid);
@@ -2064,6 +2072,10 @@
                 + ", pid " + Binder.getCallingPid());
         }
         if (accountToRename == null) throw new IllegalArgumentException("account is null");
+        if (newName != null && newName.length() > 200) {
+            Log.e(TAG, "renameAccount failed - account name longer than 200");
+            throw new IllegalArgumentException("account name longer than 200");
+        }
         int userId = UserHandle.getCallingUserId();
         if (!isAccountManagedByCaller(accountToRename.type, callingUid, userId)) {
             String msg = String.format(
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 6d29c37..3808e0c 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -3242,7 +3242,7 @@
             return AppOpsManager.MODE_IGNORED;
         }
         synchronized (this) {
-            if (isOpRestrictedLocked(uid, code, packageName, attributionTag, pvr.bypass)) {
+            if (isOpRestrictedLocked(uid, code, packageName, attributionTag, pvr.bypass, true)) {
                 return AppOpsManager.MODE_IGNORED;
             }
             code = AppOpsManager.opToSwitch(code);
@@ -3459,7 +3459,7 @@
 
             final int switchCode = AppOpsManager.opToSwitch(code);
             final UidState uidState = ops.uidState;
-            if (isOpRestrictedLocked(uid, code, packageName, attributionTag, pvr.bypass)) {
+            if (isOpRestrictedLocked(uid, code, packageName, attributionTag, pvr.bypass, false)) {
                 attributedOp.rejected(uidState.state, flags);
                 scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags,
                         AppOpsManager.MODE_IGNORED);
@@ -3973,7 +3973,8 @@
             final Op op = getOpLocked(ops, code, uid, true);
             final AttributedOp attributedOp = op.getOrCreateAttribution(op, attributionTag);
             final UidState uidState = ops.uidState;
-            isRestricted = isOpRestrictedLocked(uid, code, packageName, attributionTag, pvr.bypass);
+            isRestricted = isOpRestrictedLocked(uid, code, packageName, attributionTag, pvr.bypass,
+                    false);
             final int switchCode = AppOpsManager.opToSwitch(code);
             // If there is a non-default per UID policy (we set UID op mode only if
             // non-default) it takes over, otherwise use the per package policy.
@@ -4502,8 +4503,9 @@
      * @return The restriction matching the package
      */
     private RestrictionBypass getBypassforPackage(@NonNull AndroidPackage pkg) {
-        return new RestrictionBypass(pkg.isPrivileged(), mContext.checkPermission(
-                android.Manifest.permission.EXEMPT_FROM_AUDIO_RECORD_RESTRICTIONS, -1, pkg.getUid())
+        return new RestrictionBypass(pkg.getUid() == Process.SYSTEM_UID, pkg.isPrivileged(),
+                mContext.checkPermission(android.Manifest.permission
+                        .EXEMPT_FROM_AUDIO_RECORD_RESTRICTIONS, -1, pkg.getUid())
                 == PackageManager.PERMISSION_GRANTED);
     }
 
@@ -4763,7 +4765,7 @@
     }
 
     private boolean isOpRestrictedLocked(int uid, int code, String packageName,
-            String attributionTag, @Nullable RestrictionBypass appBypass) {
+            String attributionTag, @Nullable RestrictionBypass appBypass, boolean isCheckOp) {
         int restrictionSetCount = mOpGlobalRestrictions.size();
 
         for (int i = 0; i < restrictionSetCount; i++) {
@@ -4780,11 +4782,15 @@
             // For each client, check that the given op is not restricted, or that the given
             // package is exempt from the restriction.
             ClientUserRestrictionState restrictionState = mOpUserRestrictions.valueAt(i);
-            if (restrictionState.hasRestriction(code, packageName, attributionTag, userHandle)) {
+            if (restrictionState.hasRestriction(code, packageName, attributionTag, userHandle,
+                    isCheckOp)) {
                 RestrictionBypass opBypass = opAllowSystemBypassRestriction(code);
                 if (opBypass != null) {
                     // If we are the system, bypass user restrictions for certain codes
                     synchronized (this) {
+                        if (opBypass.isSystemUid && appBypass != null && appBypass.isSystemUid) {
+                            return false;
+                        }
                         if (opBypass.isPrivileged && appBypass != null && appBypass.isPrivileged) {
                             return false;
                         }
@@ -7137,7 +7143,7 @@
         }
 
         public boolean hasRestriction(int restriction, String packageName, String attributionTag,
-                int userId) {
+                int userId, boolean isCheckOp) {
             if (perUserRestrictions == null) {
                 return false;
             }
@@ -7156,6 +7162,9 @@
                 return true;
             }
 
+            if (isCheckOp) {
+                return !perUserExclusions.includes(packageName);
+            }
             return !perUserExclusions.contains(packageName, attributionTag);
         }
 
@@ -7322,7 +7331,8 @@
                 int numRestrictions = mOpUserRestrictions.size();
                 for (int i = 0; i < numRestrictions; i++) {
                     if (mOpUserRestrictions.valueAt(i)
-                            .hasRestriction(code, pkg, attributionTag, user.getIdentifier())) {
+                            .hasRestriction(code, pkg, attributionTag, user.getIdentifier(),
+                                    false)) {
                         number++;
                     }
                 }
diff --git a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
index 9a19031..6759d79 100644
--- a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
+++ b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
@@ -32,6 +32,7 @@
 import android.os.PowerWhitelistManager;
 import android.os.UserHandle;
 import android.text.TextUtils;
+import android.util.EventLog;
 import android.util.Log;
 import android.view.KeyEvent;
 
@@ -117,6 +118,12 @@
         int componentType = getComponentType(pendingIntent);
         ComponentName componentName = getComponentName(pendingIntent, componentType);
         if (componentName != null) {
+            if (!TextUtils.equals(componentName.getPackageName(), sessionPackageName)) {
+                EventLog.writeEvent(0x534e4554, "238177121", -1, ""); // SafetyNet logging
+                throw new IllegalArgumentException("ComponentName does not belong to "
+                        + "sessionPackageName. sessionPackageName = " + sessionPackageName
+                        + ", ComponentName pkg = " + componentName.getPackageName());
+            }
             return new MediaButtonReceiverHolder(userId, pendingIntent, componentName,
                     componentType);
         }
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 4822d6a..ca5e97c 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -53,6 +53,7 @@
 import android.os.ResultReceiver;
 import android.os.SystemClock;
 import android.text.TextUtils;
+import android.util.EventLog;
 import android.util.Log;
 import android.view.KeyEvent;
 
@@ -934,6 +935,14 @@
         @Override
         public void setMediaButtonReceiver(PendingIntent pi, String sessionPackageName)
                 throws RemoteException {
+            //mPackageName has been verified in MediaSessionService.enforcePackageName().
+            if (!TextUtils.equals(sessionPackageName, mPackageName)) {
+                EventLog.writeEvent(0x534e4554, "238177121", -1, ""); // SafetyNet logging
+                throw new IllegalArgumentException("sessionPackageName name does not match "
+                        + "package name provided to MediaSessionRecord. sessionPackageName = "
+                        + sessionPackageName + ", pkg = "
+                        + mPackageName);
+            }
             final long token = Binder.clearCallingIdentity();
             try {
                 if ((mPolicies & MediaSessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_RECEIVER)
@@ -952,6 +961,15 @@
         public void setMediaButtonBroadcastReceiver(ComponentName receiver) throws RemoteException {
             final long token = Binder.clearCallingIdentity();
             try {
+                //mPackageName has been verified in MediaSessionService.enforcePackageName().
+                if (receiver != null && !TextUtils.equals(
+                        mPackageName, receiver.getPackageName())) {
+                    EventLog.writeEvent(0x534e4554, "238177121", -1, ""); // SafetyNet logging
+                    throw new IllegalArgumentException("receiver does not belong to "
+                            + "package name provided to MediaSessionRecord. Pkg = " + mPackageName
+                            + ", Receiver Pkg = " + receiver.getPackageName());
+                }
+
                 if ((mPolicies & MediaSessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_RECEIVER)
                         != 0) {
                     return;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 32cb42f..6e7737f 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -4889,7 +4889,16 @@
             }
             enforcePolicyAccess(Binder.getCallingUid(), "addAutomaticZenRule");
 
-            return mZenModeHelper.addAutomaticZenRule(pkg, automaticZenRule,
+            // If the caller is system, take the package name from the rule's owner rather than
+            // from the caller's package.
+            String rulePkg = pkg;
+            if (isCallingUidSystem()) {
+                if (automaticZenRule.getOwner() != null) {
+                    rulePkg = automaticZenRule.getOwner().getPackageName();
+                }
+            }
+
+            return mZenModeHelper.addAutomaticZenRule(rulePkg, automaticZenRule,
                     "addAutomaticZenRule");
         }
 
@@ -7507,7 +7516,8 @@
                 && (record.getSuppressedVisualEffects() & SUPPRESSED_EFFECT_STATUS_BAR) != 0;
         if (!record.isUpdate
                 && record.getImportance() > IMPORTANCE_MIN
-                && !suppressedByDnd) {
+                && !suppressedByDnd
+                && isNotificationForCurrentUser(record)) {
             sendAccessibilityEvent(record);
             sentAccessibilityEvent = true;
         }
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index c11116c..9fd4801 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -310,7 +310,7 @@
 
     public String addAutomaticZenRule(String pkg, AutomaticZenRule automaticZenRule,
             String reason) {
-        if (!isSystemRule(automaticZenRule)) {
+        if (!ZenModeConfig.SYSTEM_AUTHORITY.equals(pkg)) {
             PackageItemInfo component = getServiceInfo(automaticZenRule.getOwner());
             if (component == null) {
                 component = getActivityInfo(automaticZenRule.getConfigurationActivity());
@@ -326,7 +326,8 @@
             int newRuleInstanceCount = getCurrentInstanceCount(automaticZenRule.getOwner())
                     + getCurrentInstanceCount(automaticZenRule.getConfigurationActivity())
                     + 1;
-            if (newRuleInstanceCount > RULE_LIMIT_PER_PACKAGE
+            int newPackageRuleCount = getPackageRuleCount(pkg) + 1;
+            if (newPackageRuleCount > RULE_LIMIT_PER_PACKAGE
                     || (ruleInstanceLimit > 0 && ruleInstanceLimit < newRuleInstanceCount)) {
                 throw new IllegalArgumentException("Rule instance limit exceeded");
             }
@@ -507,6 +508,23 @@
         return count;
     }
 
+    // Equivalent method to getCurrentInstanceCount, but for all rules associated with a specific
+    // package rather than a condition provider service or activity.
+    private int getPackageRuleCount(String pkg) {
+        if (pkg == null) {
+            return 0;
+        }
+        int count = 0;
+        synchronized (mConfig) {
+            for (ZenRule rule : mConfig.automaticRules.values()) {
+                if (pkg.equals(rule.getPkg())) {
+                    count++;
+                }
+            }
+        }
+        return count;
+    }
+
     public boolean canManageAutomaticZenRule(ZenRule rule) {
         final int callingUid = Binder.getCallingUid();
         if (callingUid == 0 || callingUid == Process.SYSTEM_UID) {
@@ -548,11 +566,6 @@
         }
     }
 
-    private boolean isSystemRule(AutomaticZenRule rule) {
-        return rule.getOwner() != null
-                && ZenModeConfig.SYSTEM_AUTHORITY.equals(rule.getOwner().getPackageName());
-    }
-
     private ServiceInfo getServiceInfo(ComponentName owner) {
         Intent queryIntent = new Intent();
         queryIntent.setComponent(owner);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d03aaee..6249eca 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -21662,7 +21662,8 @@
                 return PackageManager.DELETE_FAILED_INTERNAL_ERROR;
             }
 
-            if (isSystemApp(uninstalledPs)) {
+            if (isSystemApp(uninstalledPs)
+                    && (deleteFlags & PackageManager.DELETE_SYSTEM_APP) == 0) {
                 UserInfo userInfo = mUserManager.getUserInfo(userId);
                 if (userInfo == null || !userInfo.isAdmin()) {
                     Slog.w(TAG, "Not removing package " + packageName
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 09c6b50..92abc486 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -88,6 +88,7 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.AtomicFile;
+import android.util.EventLog;
 import android.util.IndentingPrintWriter;
 import android.util.IntArray;
 import android.util.Slog;
@@ -4499,6 +4500,13 @@
     public void setApplicationRestrictions(String packageName, Bundle restrictions,
             @UserIdInt int userId) {
         checkSystemOrRoot("set application restrictions");
+        String validationResult = validateName(packageName);
+        if (validationResult != null) {
+            if (packageName.contains("../")) {
+                EventLog.writeEvent(0x534e4554, "239701237", -1, "");
+            }
+            throw new IllegalArgumentException("Invalid package name: " + validationResult);
+        }
         if (restrictions != null) {
             restrictions.setDefusable(true);
         }
@@ -4525,6 +4533,39 @@
         mContext.sendBroadcastAsUser(changeIntent, UserHandle.of(userId));
     }
 
+    /**
+     * Check if the given name is valid.
+     *
+     * Note: the logic is taken from FrameworkParsingPackageUtils in master, edited to remove
+     * unnecessary parts. Copied here for a security fix.
+     *
+     * @param name The name to check.
+     * @return null if it's valid, error message if not
+     */
+    @VisibleForTesting
+    static String validateName(String name) {
+        final int n = name.length();
+        boolean front = true;
+        for (int i = 0; i < n; i++) {
+            final char c = name.charAt(i);
+            if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
+                front = false;
+                continue;
+            }
+            if (!front) {
+                if ((c >= '0' && c <= '9') || c == '_') {
+                    continue;
+                }
+                if (c == '.') {
+                    front = true;
+                    continue;
+                }
+            }
+            return "bad character '" + c + "'";
+        }
+        return null;
+    }
+
     private int getUidForPackage(String packageName) {
         final long ident = Binder.clearCallingIdentity();
         try {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 54a6c67..2662f62 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -2764,7 +2764,6 @@
                     final Permission bp = mRegistry.getPermission(permName);
                     final boolean appSupportsRuntimePermissions =
                             pkg.getTargetSdkVersion() >= Build.VERSION_CODES.M;
-                    String legacyActivityRecognitionPermission = null;
 
                     if (DEBUG_INSTALL && bp != null) {
                         Log.i(TAG, "Package " + friendlyName
@@ -2788,47 +2787,12 @@
                     // Cache newImplicitPermissions before modifing permissionsState as for the
                     // shared uids the original and new state are the same object
                     if (!origState.hasPermissionState(permName)
-                            && (pkg.getImplicitPermissions().contains(permName)
-                            || (permName.equals(Manifest.permission.ACTIVITY_RECOGNITION)))) {
-                        if (pkg.getImplicitPermissions().contains(permName)) {
+                            && (pkg.getImplicitPermissions().contains(permName))) {
                             // If permName is an implicit permission, try to auto-grant
                             newImplicitPermissions.add(permName);
-
                             if (DEBUG_PERMISSIONS) {
                                 Slog.i(TAG, permName + " is newly added for " + friendlyName);
                             }
-                        } else {
-                            // Special case for Activity Recognition permission. Even if AR
-                            // permission is not an implicit permission we want to add it to the
-                            // list (try to auto-grant it) if the app was installed on a device
-                            // before AR permission was split, regardless of if the app now requests
-                            // the new AR permission or has updated its target SDK and AR is no
-                            // longer implicit to it. This is a compatibility workaround for apps
-                            // when AR permission was split in Q.
-                            // TODO(zhanghai): This calls into SystemConfig, which generally
-                            //  shouldn't  cause deadlock, but maybe we should keep a cache of the
-                            //  split permission  list and just eliminate the possibility.
-                            final List<PermissionManager.SplitPermissionInfo> permissionList =
-                                    getSplitPermissionInfos();
-                            int numSplitPerms = permissionList.size();
-                            for (int splitPermNum = 0; splitPermNum < numSplitPerms;
-                                    splitPermNum++) {
-                                PermissionManager.SplitPermissionInfo sp = permissionList.get(
-                                        splitPermNum);
-                                String splitPermName = sp.getSplitPermission();
-                                if (sp.getNewPermissions().contains(permName)
-                                        && origState.isPermissionGranted(splitPermName)) {
-                                    legacyActivityRecognitionPermission = splitPermName;
-                                    newImplicitPermissions.add(permName);
-
-                                    if (DEBUG_PERMISSIONS) {
-                                        Slog.i(TAG, permName + " is newly added for "
-                                                + friendlyName);
-                                    }
-                                    break;
-                                }
-                            }
-                        }
                     }
 
                     // TODO(b/140256621): The package instant app method has been removed
@@ -2959,8 +2923,7 @@
                             // Hard restricted permissions cannot be held.
                             } else if (!permissionPolicyInitialized
                                     || (!hardRestricted || restrictionExempt)) {
-                                if ((origPermState != null && origPermState.isGranted())
-                                        || legacyActivityRecognitionPermission != null) {
+                                if ((origPermState != null && origPermState.isGranted())) {
                                     if (!uidState.grantPermission(bp)) {
                                         wasChanged = true;
                                     }
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 8723ecb..ebd8dc0 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -7030,7 +7030,23 @@
                     parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK ||
                     parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP ||
                     (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
-                parent.deliverNewIntentLocked(callingUid, destIntent, destGrants, srec.packageName);
+                boolean abort;
+                try {
+                    abort = !mTaskSupervisor.checkStartAnyActivityPermission(destIntent,
+                            parent.info, null /* resultWho */, -1 /* requestCode */, srec.getPid(),
+                            callingUid, srec.info.packageName, null /* callingFeatureId */,
+                            false /* ignoreTargetSecurity */, false /* launchingInTask */, srec.app,
+                            null /* resultRecord */, null /* resultRootTask */);
+                } catch (SecurityException e) {
+                    abort = true;
+                }
+                if (abort) {
+                    android.util.EventLog.writeEvent(0x534e4554, "238605611", callingUid, "");
+                    foundParentInTask = false;
+                } else {
+                    parent.deliverNewIntentLocked(callingUid, destIntent, destGrants,
+                            srec.packageName);
+                }
             } else {
                 try {
                     ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 0af6a29..d1e8927 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3532,7 +3532,10 @@
         }
         // Exclude toast because legacy apps may show toast window by themselves, so the misused
         // apps won't always be considered as foreground state.
-        if (mAttrs.type >= FIRST_SYSTEM_WINDOW && mAttrs.type != TYPE_TOAST) {
+        // Exclude private presentations as they can only be shown on private virtual displays and
+        // shouldn't be the cause of an app be considered foreground.
+        if (mAttrs.type >= FIRST_SYSTEM_WINDOW && mAttrs.type != TYPE_TOAST
+                && mAttrs.type != TYPE_PRIVATE_PRESENTATION) {
             mWmService.mAtmService.mActiveUids.onNonAppSurfaceVisibilityChanged(mOwnerUid, shown);
         }
         if (mIsImWindow && mWmService.mAccessibilityController != null) {
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index 2690948..4916262 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -36,6 +36,7 @@
 import android.accounts.IAccountManagerResponse;
 import android.app.AppOpsManager;
 import android.app.INotificationManager;
+import android.app.PropertyInvalidatedCache;
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.content.BroadcastReceiver;
@@ -132,6 +133,8 @@
     protected void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
 
+        PropertyInvalidatedCache.disableForTestMode();
+
         when(mMockPackageManager.checkSignatures(anyInt(), anyInt()))
                     .thenReturn(PackageManager.SIGNATURE_MATCH);
         final UserInfo ui = new UserInfo(UserHandle.USER_SYSTEM, "user0", 0);
@@ -248,6 +251,26 @@
     }
 
     @SmallTest
+    public void testCheckAddAccountLongName() throws Exception {
+        unlockSystemUser();
+        String longString = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+                + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+                + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+                + "aaaaa";
+        Account a11 = new Account(longString, AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1);
+
+        mAms.addAccountExplicitly(
+                a11, /* password= */ "p11", /* extras= */ null, /* callerPackage= */ null);
+
+        String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE};
+        when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list);
+        Account[] accounts = mAms.getAccountsAsUser(null,
+                UserHandle.getCallingUserId(), mContext.getOpPackageName());
+        assertEquals(0, accounts.length);
+    }
+
+
+    @SmallTest
     public void testPasswords() throws Exception {
         unlockSystemUser();
         Account a11 = new Account("account1", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1);
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
index 6c1c019..658f168 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -86,6 +86,13 @@
         }
     }
 
+    public void testValidateName() {
+        assertNull(UserManagerService.validateName("android"));
+        assertNull(UserManagerService.validateName("com.company.myapp"));
+        assertNotNull(UserManagerService.validateName("/../../data"));
+        assertNotNull(UserManagerService.validateName("/dir"));
+    }
+
     private Bundle createBundle() {
         Bundle result = new Bundle();
         // Tests for 6 allowed types: Integer, Boolean, String, String[], Bundle and Parcelable[]
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index ea46eab..2340fa8 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -1293,6 +1293,21 @@
     }
 
     @Test
+    public void testA11yCrossUserEventNotSent() throws Exception {
+        final Notification n = new Builder(getContext(), "test")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
+        int userId = mUser.getIdentifier() + 1;
+        StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid,
+                mPid, n, UserHandle.of(userId), null, System.currentTimeMillis());
+        NotificationRecord r = new NotificationRecord(getContext(), sbn,
+                new NotificationChannel("test", "test", IMPORTANCE_HIGH));
+
+        mService.buzzBeepBlinkLocked(r);
+
+        verify(mAccessibilityService, never()).sendAccessibilityEvent(any(), anyInt());
+    }
+
+    @Test
     public void testLightsScreenOn() {
         mService.mScreenOn = true;
         NotificationRecord r = getLightsNotification();
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 564ace2..ce0fefa 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -6813,6 +6813,43 @@
     }
 
     @Test
+    public void testAddAutomaticZenRule_systemCallTakesPackageFromOwner() throws Exception {
+        mService.isSystemUid = true;
+        ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class);
+        when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
+                .thenReturn(true);
+        mService.setZenHelper(mockZenModeHelper);
+        ComponentName owner = new ComponentName("android", "ProviderName");
+        ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
+        boolean isEnabled = true;
+        AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
+                zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
+        mBinderService.addAutomaticZenRule(rule, "com.android.settings");
+
+        // verify that zen mode helper gets passed in a package name of "android"
+        verify(mockZenModeHelper).addAutomaticZenRule(eq("android"), eq(rule), anyString());
+    }
+
+    @Test
+    public void testAddAutomaticZenRule_nonSystemCallTakesPackageFromArg() throws Exception {
+        mService.isSystemUid = false;
+        ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class);
+        when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
+                .thenReturn(true);
+        mService.setZenHelper(mockZenModeHelper);
+        ComponentName owner = new ComponentName("android", "ProviderName");
+        ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
+        boolean isEnabled = true;
+        AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
+                zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
+        mBinderService.addAutomaticZenRule(rule, "another.package");
+
+        // verify that zen mode helper gets passed in the package name from the arg, not the owner
+        verify(mockZenModeHelper).addAutomaticZenRule(
+                eq("another.package"), eq(rule), anyString());
+    }
+
+    @Test
     public void testAreNotificationsEnabledForPackage_crossUser() throws Exception {
         try {
             mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index e03cf1c..5c2730f 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -1618,7 +1618,9 @@
                     ZenModeConfig.toScheduleConditionId(si),
                     new ZenPolicy.Builder().build(),
                     NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-            String id = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule, "test");
+            // We need the package name to be something that's not "android" so there aren't any
+            // existing rules under that package.
+            String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", zenRule, "test");
             assertNotNull(id);
         }
         try {
@@ -1628,12 +1630,71 @@
                     ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                     new ZenPolicy.Builder().build(),
                     NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-            String id = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule, "test");
+            String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", zenRule, "test");
             fail("allowed too many rules to be created");
         } catch (IllegalArgumentException e) {
             // yay
         }
+    }
 
+    @Test
+    public void testAddAutomaticZenRule_beyondSystemLimit_differentComponents() {
+        // Make sure the system limit is enforced per-package even with different component provider
+        // names.
+        for (int i = 0; i < RULE_LIMIT_PER_PACKAGE; i++) {
+            ScheduleInfo si = new ScheduleInfo();
+            si.startHour = i;
+            AutomaticZenRule zenRule = new AutomaticZenRule("name" + i,
+                    null,
+                    new ComponentName("android", "ScheduleConditionProvider" + i),
+                    ZenModeConfig.toScheduleConditionId(si),
+                    new ZenPolicy.Builder().build(),
+                    NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+            String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", zenRule, "test");
+            assertNotNull(id);
+        }
+        try {
+            AutomaticZenRule zenRule = new AutomaticZenRule("name",
+                    null,
+                    new ComponentName("android", "ScheduleConditionProviderFinal"),
+                    ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+                    new ZenPolicy.Builder().build(),
+                    NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+            String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", zenRule, "test");
+            fail("allowed too many rules to be created");
+        } catch (IllegalArgumentException e) {
+            // yay
+        }
+    }
+
+    @Test
+    public void testAddAutomaticZenRule_claimedSystemOwner() {
+        // Make sure anything that claims to have a "system" owner but not actually part of the
+        // system package still gets limited on number of rules
+        for (int i = 0; i < RULE_LIMIT_PER_PACKAGE; i++) {
+            ScheduleInfo si = new ScheduleInfo();
+            si.startHour = i;
+            AutomaticZenRule zenRule = new AutomaticZenRule("name" + i,
+                    new ComponentName("android", "ScheduleConditionProvider" + i),
+                    null, // configuration activity
+                    ZenModeConfig.toScheduleConditionId(si),
+                    new ZenPolicy.Builder().build(),
+                    NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+            String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", zenRule, "test");
+            assertNotNull(id);
+        }
+        try {
+            AutomaticZenRule zenRule = new AutomaticZenRule("name",
+                    new ComponentName("android", "ScheduleConditionProviderFinal"),
+                    null, // configuration activity
+                    ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+                    new ZenPolicy.Builder().build(),
+                    NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+            String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", zenRule, "test");
+            fail("allowed too many rules to be created");
+        } catch (IllegalArgumentException e) {
+            // yay
+        }
     }
 
     @Test
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 4cdeb0b..b31b1f7 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1257,7 +1257,7 @@
         if (service != null) {
             try {
                 return service.getPhoneAccountsSupportingScheme(uriScheme,
-                        mContext.getOpPackageName());
+                        mContext.getOpPackageName()).getList();
             } catch (RemoteException e) {
                 Log.e(TAG, "Error calling ITelecomService#getPhoneAccountsSupportingScheme", e);
             }
@@ -1299,7 +1299,7 @@
         if (service != null) {
             try {
                 return service.getSelfManagedPhoneAccounts(mContext.getOpPackageName(),
-                        mContext.getAttributionTag());
+                        mContext.getAttributionTag()).getList();
             } catch (RemoteException e) {
                 Log.e(TAG, "Error calling ITelecomService#getSelfManagedPhoneAccounts()", e);
             }
@@ -1325,7 +1325,7 @@
         if (service != null) {
             try {
                 return service.getCallCapablePhoneAccounts(includeDisabledAccounts,
-                        mContext.getOpPackageName(), mContext.getAttributionTag());
+                        mContext.getOpPackageName(), mContext.getAttributionTag()).getList();
             } catch (RemoteException e) {
                 Log.e(TAG, "Error calling ITelecomService#getCallCapablePhoneAccounts("
                         + includeDisabledAccounts + ")", e);
@@ -1349,7 +1349,7 @@
         ITelecomService service = getTelecomService();
         if (service != null) {
             try {
-                return service.getPhoneAccountsForPackage(mContext.getPackageName());
+                return service.getPhoneAccountsForPackage(mContext.getPackageName()).getList();
             } catch (RemoteException e) {
                 Log.e(TAG, "Error calling ITelecomService#getPhoneAccountsForPackage", e);
             }
@@ -1409,7 +1409,7 @@
         ITelecomService service = getTelecomService();
         if (service != null) {
             try {
-                return service.getAllPhoneAccounts();
+                return service.getAllPhoneAccounts().getList();
             } catch (RemoteException e) {
                 Log.e(TAG, "Error calling ITelecomService#getAllPhoneAccounts", e);
             }
@@ -1428,7 +1428,7 @@
         ITelecomService service = getTelecomService();
         if (service != null) {
             try {
-                return service.getAllPhoneAccountHandles();
+                return service.getAllPhoneAccountHandles().getList();
             } catch (RemoteException e) {
                 Log.e(TAG, "Error calling ITelecomService#getAllPhoneAccountHandles", e);
             }
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 6f286d9..8f409c0 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -23,6 +23,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.telecom.PhoneAccount;
+import android.content.pm.ParceledListSlice;
 
 /**
  * Interface used to interact with Telecom. Mostly this is used by TelephonyManager for passing
@@ -56,25 +57,25 @@
     /**
      * @see TelecomServiceImpl#getCallCapablePhoneAccounts
      */
-    List<PhoneAccountHandle> getCallCapablePhoneAccounts(
+    ParceledListSlice<PhoneAccountHandle> getCallCapablePhoneAccounts(
             boolean includeDisabledAccounts, String callingPackage, String callingFeatureId);
 
     /**
      * @see TelecomServiceImpl#getSelfManagedPhoneAccounts
      */
-    List<PhoneAccountHandle> getSelfManagedPhoneAccounts(String callingPackage,
+    ParceledListSlice<PhoneAccountHandle> getSelfManagedPhoneAccounts(String callingPackage,
             String callingFeatureId);
 
     /**
      * @see TelecomManager#getPhoneAccountsSupportingScheme
      */
-    List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(in String uriScheme,
+    ParceledListSlice<PhoneAccountHandle> getPhoneAccountsSupportingScheme(in String uriScheme,
             String callingPackage);
 
     /**
      * @see TelecomManager#getPhoneAccountsForPackage
      */
-    List<PhoneAccountHandle> getPhoneAccountsForPackage(in String packageName);
+    ParceledListSlice<PhoneAccountHandle> getPhoneAccountsForPackage(in String packageName);
 
     /**
      * @see TelecomManager#getPhoneAccount
@@ -89,12 +90,12 @@
     /**
      * @see TelecomManager#getAllPhoneAccounts
      */
-    List<PhoneAccount> getAllPhoneAccounts();
+    ParceledListSlice<PhoneAccount> getAllPhoneAccounts();
 
     /**
      * @see TelecomManager#getAllPhoneAccountHandles
      */
-    List<PhoneAccountHandle> getAllPhoneAccountHandles();
+    ParceledListSlice<PhoneAccountHandle> getAllPhoneAccountHandles();
 
     /**
      * @see TelecomServiceImpl#getSimCallManager