Merge "Set default phonebook access to ACCESS_REJECTED when user didn't choose one"
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 13e1dfa..cf8df28 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -564,11 +564,13 @@
 
     // Read system memory info including ZRAM. The values are stored in the vector
     // in the same order as MEMINFO_* enum
-    std::vector<uint64_t> mem(MEMINFO_COUNT);
-    std::vector<std::string> tags(::android::meminfo::SysMemInfo::kDefaultSysMemInfoTags);
+    std::vector<std::string_view> tags(
+        ::android::meminfo::SysMemInfo::kDefaultSysMemInfoTags.begin(),
+        ::android::meminfo::SysMemInfo::kDefaultSysMemInfoTags.end());
     tags.insert(tags.begin() + MEMINFO_ZRAM_TOTAL, "Zram:");
+    std::vector<uint64_t> mem(tags.size());
     ::android::meminfo::SysMemInfo smi;
-    if (!smi.ReadMemInfo(tags, &mem)) {
+    if (!smi.ReadMemInfo(tags.size(), tags.data(), mem.data())) {
         jniThrowRuntimeException(env, "SysMemInfo read failed");
         return;
     }
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 4cb2d15..8aa6f86 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -31,6 +31,7 @@
 #include <android-base/unique_fd.h>
 
 #include <algorithm>
+#include <array>
 #include <limits>
 #include <memory>
 #include <string>
@@ -630,14 +631,16 @@
 
 static jlong android_os_Process_getFreeMemory(JNIEnv* env, jobject clazz)
 {
-    static const std::vector<std::string> memFreeTags = {
+    std::array<std::string_view, 2> memFreeTags = {
         ::android::meminfo::SysMemInfo::kMemFree,
         ::android::meminfo::SysMemInfo::kMemCached,
     };
     std::vector<uint64_t> mem(memFreeTags.size());
     ::android::meminfo::SysMemInfo smi;
 
-    if (!smi.ReadMemInfo(memFreeTags, &mem)) {
+    if (!smi.ReadMemInfo(memFreeTags.size(),
+                         memFreeTags.data(),
+                         mem.data())) {
         jniThrowRuntimeException(env, "SysMemInfo read failed to get Free Memory");
         return -1L;
     }
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index f7e825e..eb2723a 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -79,7 +79,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
-import java.util.stream.Collectors;
 
 /**
  * Since phone process can be restarted, this class provides a centralized place
@@ -849,10 +848,7 @@
                         }
                     }
                     if ((events & PhoneStateListener
-                            .LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE) != 0
-                            && TelephonyPermissions.checkReadPhoneStateOnAnyActiveSub(
-                                    r.context, r.callerPid, r.callerUid, r.callingPackage,
-                            "listen_active_data_subid_change")) {
+                            .LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE) != 0) {
                         try {
                             r.callback.onActiveDataSubIdChanged(mActiveDataSubId);
                         } catch (RemoteException ex) {
@@ -1829,23 +1825,11 @@
             log("notifyActiveDataSubIdChanged: activeDataSubId=" + activeDataSubId);
         }
 
-        // Create a copy to prevent the IPC call while checking carrier privilege under the lock.
-        List<Record> copiedRecords;
-        synchronized (mRecords) {
-            copiedRecords = new ArrayList<>(mRecords);
-        }
         mActiveDataSubId = activeDataSubId;
-
-        // Filter the record that does not listen to this change or does not have the permission.
-        copiedRecords = copiedRecords.stream().filter(r -> r.matchPhoneStateListenerEvent(
-                PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE)
-                && TelephonyPermissions.checkReadPhoneStateOnAnyActiveSub(
-                        mContext, r.callerPid, r.callerUid, r.callingPackage,
-                "notifyActiveDataSubIdChanged")).collect(Collectors.toCollection(ArrayList::new));
-
         synchronized (mRecords) {
-            for (Record r : copiedRecords) {
-                if (mRecords.contains(r)) {
+            for (Record r : mRecords) {
+                if (r.matchPhoneStateListenerEvent(
+                        PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE)) {
                     try {
                         r.callback.onActiveDataSubIdChanged(activeDataSubId);
                     } catch (RemoteException ex) {
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 36e872a..4a62bc5 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -55,6 +55,7 @@
 import android.os.ShellCallback;
 import android.os.UserHandle;
 import android.text.TextUtils;
+import android.text.format.DateUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
@@ -64,6 +65,8 @@
 import android.util.SparseIntArray;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.BinderDeathDispatcher;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
@@ -89,6 +92,14 @@
     /** Do a WTF if a single observer is registered more than this times. */
     private static final int TOO_MANY_OBSERVERS_THRESHOLD = 1000;
 
+    /**
+     * Delay to apply to content change notifications dispatched to apps running
+     * in the background. This is used to help prevent stampeding when the user
+     * is performing CPU/RAM intensive foreground tasks, such as when capturing
+     * burst photos.
+     */
+    private static final long BACKGROUND_OBSERVER_DELAY = 10 * DateUtils.SECOND_IN_MILLIS;
+
     public static class Lifecycle extends SystemService {
         private ContentService mService;
 
@@ -426,28 +437,15 @@
                         flags, userHandle, calls);
             }
             final int numCalls = calls.size();
-            for (int i=0; i<numCalls; i++) {
-                ObserverCall oc = calls.get(i);
-                try {
-                    oc.mObserver.onChange(oc.mSelfChange, uri, userHandle);
-                    if (DEBUG) Slog.d(TAG, "Notified " + oc.mObserver + " of " + "update at "
-                            + uri);
-                } catch (RemoteException ex) {
-                    synchronized (mRootNode) {
-                        Log.w(TAG, "Found dead observer, removing");
-                        IBinder binder = oc.mObserver.asBinder();
-                        final ArrayList<ObserverNode.ObserverEntry> list
-                                = oc.mNode.mObservers;
-                        int numList = list.size();
-                        for (int j=0; j<numList; j++) {
-                            ObserverNode.ObserverEntry oe = list.get(j);
-                            if (oe.observer.asBinder() == binder) {
-                                list.remove(j);
-                                j--;
-                                numList--;
-                            }
-                        }
-                    }
+            for (int i = 0; i < numCalls; i++) {
+                // Immediately dispatch notifications to foreground apps that
+                // are important to the user; all other background observers are
+                // delayed to avoid stampeding
+                final ObserverCall oc = calls.get(i);
+                if (oc.mProcState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
+                    oc.run();
+                } else {
+                    BackgroundThread.getHandler().postDelayed(oc, BACKGROUND_OBSERVER_DELAY);
                 }
             }
             if ((flags&ContentResolver.NOTIFY_SYNC_TO_NETWORK) != 0) {
@@ -486,23 +484,33 @@
                 UserHandle.getCallingUserId(), Build.VERSION_CODES.CUR_DEVELOPMENT, callingPackage);
     }
 
-    /**
-     * Hide this class since it is not part of api,
-     * but current unittest framework requires it to be public
-     * @hide
-     *
-     */
-    public static final class ObserverCall {
-        final ObserverNode mNode;
+    /** {@hide} */
+    @VisibleForTesting
+    public static final class ObserverCall implements Runnable {
         final IContentObserver mObserver;
         final boolean mSelfChange;
-        final int mObserverUserId;
+        final Uri mUri;
+        final int mUserId;
+        final int mProcState;
 
-        ObserverCall(ObserverNode node, IContentObserver observer, boolean selfChange, int observerUserId) {
-            mNode = node;
+        ObserverCall(IContentObserver observer, boolean selfChange, Uri uri, int userId,
+                int procState) {
             mObserver = observer;
             mSelfChange = selfChange;
-            mObserverUserId = observerUserId;
+            mUri = uri;
+            mUserId = userId;
+            mProcState = procState;
+        }
+
+        @Override
+        public void run() {
+            try {
+                mObserver.onChange(mSelfChange, mUri, mUserId);
+                if (DEBUG) Slog.d(TAG, "Notified " + mObserver + " of update at " + mUri);
+            } catch (RemoteException ignored) {
+                // We already have a death observer that will clean up if the
+                // remote process dies
+            }
         }
     }
 
@@ -1345,11 +1353,8 @@
         return ContentResolver.SYNC_EXEMPTION_NONE;
     }
 
-    /**
-     * Hide this class since it is not part of api,
-     * but current unittest framework requires it to be public
-     * @hide
-     */
+    /** {@hide} */
+    @VisibleForTesting
     public static final class ObserverNode {
         private class ObserverEntry implements IBinder.DeathRecipient {
             public final IContentObserver observer;
@@ -1546,7 +1551,7 @@
             return false;
         }
 
-        private void collectMyObserversLocked(boolean leaf, IContentObserver observer,
+        private void collectMyObserversLocked(Uri uri, boolean leaf, IContentObserver observer,
                                               boolean observerWantsSelfNotifications, int flags,
                                               int targetUserHandle, ArrayList<ObserverCall> calls) {
             int N = mObservers.size();
@@ -1588,8 +1593,10 @@
                     if (DEBUG) Slog.d(TAG, "Reporting to " + entry.observer + ": leaf=" + leaf
                             + " flags=" + Integer.toHexString(flags)
                             + " desc=" + entry.notifyForDescendants);
-                    calls.add(new ObserverCall(this, entry.observer, selfChange,
-                            UserHandle.getUserId(entry.uid)));
+                    final int procState = LocalServices.getService(ActivityManagerInternal.class)
+                            .getUidProcessState(entry.uid);
+                    calls.add(new ObserverCall(entry.observer, selfChange, uri,
+                            targetUserHandle, procState));
                 }
             }
         }
@@ -1605,14 +1612,14 @@
             if (index >= segmentCount) {
                 // This is the leaf node, notify all observers
                 if (DEBUG) Slog.d(TAG, "Collecting leaf observers @ #" + index + ", node " + mName);
-                collectMyObserversLocked(true, observer, observerWantsSelfNotifications,
+                collectMyObserversLocked(uri, true, observer, observerWantsSelfNotifications,
                         flags, targetUserHandle, calls);
             } else if (index < segmentCount){
                 segment = getUriSegment(uri, index);
                 if (DEBUG) Slog.d(TAG, "Collecting non-leaf observers @ #" + index + " / "
                         + segment);
                 // Notify any observers at this level who are interested in descendants
-                collectMyObserversLocked(false, observer, observerWantsSelfNotifications,
+                collectMyObserversLocked(uri, false, observer, observerWantsSelfNotifications,
                         flags, targetUserHandle, calls);
             }
 
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 271195b..6a3c06e 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -33,13 +33,13 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.IPhoneStateListener;
 
+import dalvik.system.VMRuntime;
+
 import java.lang.ref.WeakReference;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Executor;
 
-import dalvik.system.VMRuntime;
-
 /**
  * A listener class for monitoring changes in specific telephony states
  * on the device, including service state, signal strength, message
@@ -301,11 +301,6 @@
      *  it could be the current active opportunistic subscription in use, or the
      *  subscription user selected as default data subscription in DSDS mode.
      *
-     *  Requires Permission: No permission is required to listen, but notification requires
-     *  {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} or the calling
-     *  app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges})
-     *  on any active subscription.
-     *
      *  @see #onActiveDataSubscriptionIdChanged
      */
     public static final int LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE = 0x00400000;