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;