Merge "Revert "Check for NLS service intent filter when rebinding services"" into udc-dev
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 77b0e91..862b785 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2886,7 +2886,7 @@
             ArrayList<Person> people = extras.getParcelableArrayList(EXTRA_PEOPLE_LIST, android.app.Person.class);
             if (people != null && !people.isEmpty()) {
                 for (Person p : people) {
-                    visitor.accept(p.getIconUri());
+                    p.visitUris(visitor);
                 }
             }
 
@@ -2906,7 +2906,7 @@
             // Notification Listeners might use directly (without the isStyle check).
             final Person person = extras.getParcelable(EXTRA_MESSAGING_PERSON, Person.class);
             if (person != null) {
-                visitor.accept(person.getIconUri());
+                person.visitUris(visitor);
             }
 
             final Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES,
@@ -2914,12 +2914,7 @@
             if (!ArrayUtils.isEmpty(messages)) {
                 for (MessagingStyle.Message message : MessagingStyle.Message
                         .getMessagesFromBundleArray(messages)) {
-                    visitor.accept(message.getDataUri());
-
-                    Person senderPerson = message.getSenderPerson();
-                    if (senderPerson != null) {
-                        visitor.accept(senderPerson.getIconUri());
-                    }
+                    message.visitUris(visitor);
                 }
             }
 
@@ -2928,12 +2923,7 @@
             if (!ArrayUtils.isEmpty(historic)) {
                 for (MessagingStyle.Message message : MessagingStyle.Message
                         .getMessagesFromBundleArray(historic)) {
-                    visitor.accept(message.getDataUri());
-
-                    Person senderPerson = message.getSenderPerson();
-                    if (senderPerson != null) {
-                        visitor.accept(senderPerson.getIconUri());
-                    }
+                    message.visitUris(visitor);
                 }
             }
 
@@ -2942,7 +2932,7 @@
             // Extras for CallStyle (same reason for visiting without checking isStyle).
             Person callPerson = extras.getParcelable(EXTRA_CALL_PERSON, Person.class);
             if (callPerson != null) {
-                visitor.accept(callPerson.getIconUri());
+                callPerson.visitUris(visitor);
             }
             visitIconUri(visitor, extras.getParcelable(EXTRA_VERIFICATION_ICON, Icon.class));
         }
@@ -8844,6 +8834,18 @@
             }
 
             /**
+             * See {@link Notification#visitUris(Consumer)}.
+             *
+             * @hide
+             */
+            public void visitUris(@NonNull Consumer<Uri> visitor) {
+                visitor.accept(getDataUri());
+                if (mSender != null) {
+                    mSender.visitUris(visitor);
+                }
+            }
+
+            /**
              * Returns a list of messages read from the given bundle list, e.g.
              * {@link #EXTRA_MESSAGES} or {@link #EXTRA_HISTORIC_MESSAGES}.
              */
diff --git a/core/java/android/app/Person.java b/core/java/android/app/Person.java
index 97a794d..c7432c5 100644
--- a/core/java/android/app/Person.java
+++ b/core/java/android/app/Person.java
@@ -24,6 +24,7 @@
 import android.os.Parcelable;
 
 import java.util.Objects;
+import java.util.function.Consumer;
 
 /**
  * Provides an immutable reference to an entity that appears repeatedly on different surfaces of the
@@ -177,6 +178,22 @@
         dest.writeBoolean(mIsBot);
     }
 
+    /**
+     * Note all {@link Uri} that are referenced internally, with the expectation that Uri permission
+     * grants will need to be issued to ensure the recipient of this object is able to render its
+     * contents.
+     * See b/281044385 for more context and examples about what happens when this isn't done
+     * correctly.
+     *
+     * @hide
+     */
+    public void visitUris(@NonNull Consumer<Uri> visitor) {
+        visitor.accept(getIconUri());
+        if (mUri != null && !mUri.isEmpty()) {
+            visitor.accept(Uri.parse(mUri));
+        }
+    }
+
     /** Builder for the immutable {@link Person} class. */
     public static class Builder {
         @Nullable private CharSequence mName;
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 7f96266..88ce92f 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -960,6 +960,13 @@
             return SET_REMOTE_VIEW_ADAPTER_LIST_TAG;
         }
 
+        @Override
+        public void visitUris(@NonNull Consumer<Uri> visitor) {
+            for (RemoteViews remoteViews : list) {
+                remoteViews.visitUris(visitor);
+            }
+        }
+
         int viewTypeCount;
         ArrayList<RemoteViews> list;
     }
@@ -1082,6 +1089,13 @@
         public int getActionTag() {
             return SET_REMOTE_COLLECTION_ITEMS_ADAPTER_TAG;
         }
+
+        @Override
+        public void visitUris(@NonNull Consumer<Uri> visitor) {
+            if (mItems != null) {
+              mItems.visitUris(visitor);
+            }
+        }
     }
 
     private class SetRemoteViewsAdapterIntent extends Action {
@@ -7048,6 +7062,15 @@
                         Math.max(mViewTypeCount, 1));
             }
         }
+
+        /**
+         * See {@link RemoteViews#visitUris(Consumer)}.
+         */
+        private void visitUris(@NonNull Consumer<Uri> visitor) {
+            for (RemoteViews view : mViews) {
+                view.visitUris(visitor);
+            }
+        }
     }
 
     /**
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index d2b21ae..cce4418 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -834,9 +834,13 @@
                         + " ignored: failure to find mimeType (no access from this context?)");
                 return;
             }
-            if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg"))) {
+            if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg")
+                    || mimeType.equals("application/x-flac")
+                    // also check for video ringtones
+                    || mimeType.startsWith("video/") || mimeType.equals("application/mp4"))) {
                 Log.e(TAG, "setActualDefaultRingtoneUri for URI:" + ringtoneUri
-                        + " ignored: associated mimeType:" + mimeType + " is not an audio type");
+                        + " ignored: associated MIME type:" + mimeType
+                        + " is not a recognized audio or video type");
                 return;
             }
         }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 765edd7..9f65bb4 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1948,7 +1948,7 @@
             cacheName = Settings.System.ALARM_ALERT_CACHE;
         }
         if (cacheName != null) {
-            if (!isValidAudioUri(name, value)) {
+            if (!isValidMediaUri(name, value)) {
                 return false;
             }
             final File cacheFile = new File(
@@ -1983,7 +1983,7 @@
         }
     }
 
-    private boolean isValidAudioUri(String name, String uri) {
+    private boolean isValidMediaUri(String name, String uri) {
         if (uri != null) {
             Uri audioUri = Uri.parse(uri);
             if (Settings.AUTHORITY.equals(
@@ -2001,10 +2001,13 @@
                 return false;
             }
             if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg")
-                    || mimeType.equals("application/x-flac"))) {
+                    || mimeType.equals("application/x-flac")
+                    // also check for video ringtones
+                    || mimeType.startsWith("video/") || mimeType.equals("application/mp4"))) {
                 Slog.e(LOG_TAG,
                         "mutateSystemSetting for setting: " + name + " URI: " + audioUri
-                        + " ignored: associated mimeType: " + mimeType + " is not an audio type");
+                        + " ignored: associated MIME type: " + mimeType
+                        + " is not a recognized audio or video type");
                 return false;
             }
         }
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index b59a5ea..6179b15 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -1195,6 +1195,10 @@
                             obsoleteAuthType.add(type);
                             // And delete it from the TABLE_META
                             accountsDb.deleteMetaByAuthTypeAndUid(type, uid);
+                        } else if (knownUid != null && knownUid != uid) {
+                            Slog.w(TAG, "authenticator no longer exist for type " + type);
+                            obsoleteAuthType.add(type);
+                            accountsDb.deleteMetaByAuthTypeAndUid(type, uid);
                         }
                     }
                 }
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index f26a9f8..6ae78343 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -660,6 +660,9 @@
                     (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
             final boolean fullApp =
                     (installFlags & PackageManager.INSTALL_FULL_APP) != 0;
+            final boolean isPackageDeviceAdmin = mPm.isPackageDeviceAdmin(packageName, userId);
+            final boolean isProtectedPackage = mPm.mProtectedPackages != null
+                    && mPm.mProtectedPackages.isPackageStateProtected(userId, packageName);
 
             // writer
             synchronized (mPm.mLock) {
@@ -668,7 +671,8 @@
                 if (pkgSetting == null || pkgSetting.getPkg() == null) {
                     return Pair.create(PackageManager.INSTALL_FAILED_INVALID_URI, intentSender);
                 }
-                if (instantApp && (pkgSetting.isSystem() || pkgSetting.isUpdatedSystemApp())) {
+                if (instantApp && (pkgSetting.isSystem() || pkgSetting.isUpdatedSystemApp()
+                        || isPackageDeviceAdmin || isProtectedPackage)) {
                     return Pair.create(PackageManager.INSTALL_FAILED_INVALID_URI, intentSender);
                 }
                 if (!snapshot.canViewInstantApps(callingUid, UserHandle.getUserId(callingUid))) {
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 77b2638..3d012f6 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -819,7 +819,7 @@
             }
         }
 
-        private void notifyAccessoryModeExit(int operationId) {
+        protected void notifyAccessoryModeExit(int operationId) {
             // make sure accessory mode is off
             // and restore default functions
             Slog.d(TAG, "exited USB accessory mode");
@@ -2145,8 +2145,13 @@
                      */
                     operationId = sUsbOperationCount.incrementAndGet();
                     if (msg.arg1 != 1) {
-                        // Set this since default function may be selected from Developer options
-                        setEnabledFunctions(mScreenUnlockedFunctions, false, operationId);
+                        if (mCurrentFunctions == UsbManager.FUNCTION_ACCESSORY) {
+                            notifyAccessoryModeExit(operationId);
+                        } else {
+                            // Set this since default function may be selected from Developer
+                            // options
+                            setEnabledFunctions(mScreenUnlockedFunctions, false, operationId);
+                        }
                     }
                     break;
                 case MSG_GADGET_HAL_REGISTERED:
diff --git a/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java b/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java
index eadb726..2b515c9 100644
--- a/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java
+++ b/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java
@@ -64,6 +64,14 @@
      * @hide
      */
     public static final int DEFAULT_DESTINATION_PORT = DESTINATION_PORT_ANY;
+    /**
+     * @hide
+     */
+    public static final int MAX_STRING_LENGTH = 256;
+    /**
+     * @hide
+     */
+    public static final int MAX_LIST_SIZE = 100;
 
     /**
      * Builder class for {@link VisualVoicemailSmsFilterSettings} objects.
@@ -82,11 +90,16 @@
         /**
          * Sets the client prefix for the visual voicemail SMS filter. The client prefix will appear
          * at the start of a visual voicemail SMS message, followed by a colon(:).
+         * @throws IllegalArgumentException if the string length is greater than 256 characters
          */
         public Builder setClientPrefix(String clientPrefix) {
             if (clientPrefix == null) {
                 throw new IllegalArgumentException("Client prefix cannot be null");
             }
+            if (clientPrefix.length() > MAX_STRING_LENGTH) {
+                throw new IllegalArgumentException("Client prefix cannot be greater than "
+                        + MAX_STRING_LENGTH + " characters");
+            }
             mClientPrefix = clientPrefix;
             return this;
         }
@@ -95,11 +108,25 @@
          * Sets the originating number allow list for the visual voicemail SMS filter. If the list
          * is not null only the SMS messages from a number in the list can be considered as a visual
          * voicemail SMS. Otherwise, messages from any address will be considered.
+         * @throws IllegalArgumentException if the size of the originatingNumbers list is greater
+         * than 100 elements
+         * @throws IllegalArgumentException if an element within the originatingNumbers list has
+         * a string length greater than 256
          */
         public Builder setOriginatingNumbers(List<String> originatingNumbers) {
             if (originatingNumbers == null) {
                 throw new IllegalArgumentException("Originating numbers cannot be null");
             }
+            if (originatingNumbers.size() > MAX_LIST_SIZE) {
+                throw new IllegalArgumentException("The originatingNumbers list size cannot be"
+                        + " greater than " + MAX_STRING_LENGTH + " elements");
+            }
+            for (String num : originatingNumbers) {
+                if (num != null && num.length() > MAX_STRING_LENGTH) {
+                    throw new IllegalArgumentException("Numbers within the originatingNumbers list"
+                            + " cannot be greater than" + MAX_STRING_LENGTH + " characters");
+                }
+            }
             mOriginatingNumbers = originatingNumbers;
             return this;
         }