Merge changes from topic "nov1"
* changes: BroadcastQueue: add more performance tracing. BroadcastQueue: post finishReceiver() as async. BroadcastQueue: better state transition logging. BroadcastQueue: return reasons from skip policy. BroadcastQueue: skip ANRs when assuming success.
This commit is contained in:
@@ -13874,6 +13874,29 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
@Nullable IBinder backgroundActivityStartsToken,
|
||||
@Nullable int[] broadcastAllowList,
|
||||
@Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver) {
|
||||
final int cookie = BroadcastQueue.traceBegin("broadcastIntentLockedTraced");
|
||||
final int res = broadcastIntentLockedTraced(callerApp, callerPackage, callerFeatureId,
|
||||
intent, resolvedType, resultToApp, resultTo, resultCode, resultData, resultExtras,
|
||||
requiredPermissions, excludedPermissions, excludedPackages, appOp, bOptions,
|
||||
ordered, sticky, callingPid, callingUid, realCallingUid, realCallingPid, userId,
|
||||
allowBackgroundActivityStarts, backgroundActivityStartsToken, broadcastAllowList,
|
||||
filterExtrasForReceiver);
|
||||
BroadcastQueue.traceEnd(cookie);
|
||||
return res;
|
||||
}
|
||||
|
||||
@GuardedBy("this")
|
||||
final int broadcastIntentLockedTraced(ProcessRecord callerApp, String callerPackage,
|
||||
@Nullable String callerFeatureId, Intent intent, String resolvedType,
|
||||
ProcessRecord resultToApp, IIntentReceiver resultTo, int resultCode, String resultData,
|
||||
Bundle resultExtras, String[] requiredPermissions,
|
||||
String[] excludedPermissions, String[] excludedPackages, int appOp, Bundle bOptions,
|
||||
boolean ordered, boolean sticky, int callingPid, int callingUid,
|
||||
int realCallingUid, int realCallingPid, int userId,
|
||||
boolean allowBackgroundActivityStarts,
|
||||
@Nullable IBinder backgroundActivityStartsToken,
|
||||
@Nullable int[] broadcastAllowList,
|
||||
@Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver) {
|
||||
// Ensure all internal loopers are registered for idle checks
|
||||
BroadcastLoopers.addMyLooper();
|
||||
|
||||
@@ -14425,6 +14448,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
}
|
||||
|
||||
// Figure out who all will receive this broadcast.
|
||||
final int cookie = BroadcastQueue.traceBegin("queryReceivers");
|
||||
List receivers = null;
|
||||
List<BroadcastFilter> registeredReceivers = null;
|
||||
// Need to resolve the intent to interested receivers...
|
||||
@@ -14455,6 +14479,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
resolvedType, false /*defaultOnly*/, userId);
|
||||
}
|
||||
}
|
||||
BroadcastQueue.traceEnd(cookie);
|
||||
|
||||
final boolean replacePending =
|
||||
(intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
|
||||
|
||||
@@ -25,6 +25,8 @@ import android.os.SystemClock;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@@ -37,6 +39,7 @@ import java.util.concurrent.CountDownLatch;
|
||||
public class BroadcastLoopers {
|
||||
private static final String TAG = "BroadcastLoopers";
|
||||
|
||||
@GuardedBy("sLoopers")
|
||||
private static final ArraySet<Looper> sLoopers = new ArraySet<>();
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.DropBoxManager;
|
||||
import android.os.Handler;
|
||||
import android.os.Trace;
|
||||
import android.util.Slog;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
|
||||
@@ -76,6 +77,18 @@ public abstract class BroadcastQueue {
|
||||
}
|
||||
}
|
||||
|
||||
static int traceBegin(@NonNull String methodName) {
|
||||
final int cookie = methodName.hashCode();
|
||||
Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
|
||||
TAG, methodName, cookie);
|
||||
return cookie;
|
||||
}
|
||||
|
||||
static void traceEnd(int cookie) {
|
||||
Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
|
||||
TAG, cookie);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return mQueueName;
|
||||
|
||||
@@ -64,7 +64,6 @@ import android.os.Message;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.os.Trace;
|
||||
import android.os.UserHandle;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.IndentingPrintWriter;
|
||||
@@ -144,14 +143,6 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
mRunning = new BroadcastProcessQueue[mConstants.MAX_RUNNING_PROCESS_QUEUES];
|
||||
}
|
||||
|
||||
// TODO: add support for replacing pending broadcasts
|
||||
// TODO: add support for merging pending broadcasts
|
||||
|
||||
// TODO: consider reordering foreground broadcasts within queue
|
||||
|
||||
// TODO: pause queues when background services are running
|
||||
// TODO: pause queues when processes are frozen
|
||||
|
||||
/**
|
||||
* Map from UID to per-process broadcast queues. If a UID hosts more than
|
||||
* one process, each additional process is stored as a linked list using
|
||||
@@ -222,12 +213,22 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
private static final int MSG_DELIVERY_TIMEOUT_HARD = 3;
|
||||
private static final int MSG_BG_ACTIVITY_START_TIMEOUT = 4;
|
||||
private static final int MSG_CHECK_HEALTH = 5;
|
||||
private static final int MSG_FINISH_RECEIVER = 6;
|
||||
|
||||
private void enqueueUpdateRunningList() {
|
||||
mLocalHandler.removeMessages(MSG_UPDATE_RUNNING_LIST);
|
||||
mLocalHandler.sendEmptyMessage(MSG_UPDATE_RUNNING_LIST);
|
||||
}
|
||||
|
||||
private void enqueueFinishReceiver(@NonNull BroadcastProcessQueue queue,
|
||||
@DeliveryState int deliveryState, @NonNull String reason) {
|
||||
final SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = queue;
|
||||
args.argi1 = deliveryState;
|
||||
args.arg2 = reason;
|
||||
mLocalHandler.sendMessage(Message.obtain(mLocalHandler, MSG_FINISH_RECEIVER, args));
|
||||
}
|
||||
|
||||
private final Handler mLocalHandler;
|
||||
|
||||
private final Handler.Callback mLocalCallback = (msg) -> {
|
||||
@@ -266,6 +267,17 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case MSG_FINISH_RECEIVER: {
|
||||
synchronized (mService) {
|
||||
final SomeArgs args = (SomeArgs) msg.obj;
|
||||
final BroadcastProcessQueue queue = (BroadcastProcessQueue) args.arg1;
|
||||
final int deliveryState = args.argi1;
|
||||
final String reason = (String) args.arg2;
|
||||
args.recycle();
|
||||
finishReceiverLocked(queue, deliveryState, reason);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
@@ -309,6 +321,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
return;
|
||||
}
|
||||
|
||||
final int cookie = traceBegin("updateRunnableList");
|
||||
final boolean wantQueue = queue.isRunnable();
|
||||
final boolean inQueue = (queue == mRunnableHead) || (queue.runnableAtPrev != null)
|
||||
|| (queue.runnableAtNext != null);
|
||||
@@ -335,6 +348,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
if (queue.isEmpty() && !queue.isActive() && !queue.isProcessWarm()) {
|
||||
removeProcessQueue(queue.processName, queue.uid);
|
||||
}
|
||||
|
||||
traceEnd(cookie);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -349,7 +364,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
int avail = mRunning.length - getRunningSize();
|
||||
if (avail == 0) return;
|
||||
|
||||
final int cookie = traceBegin(TAG, "updateRunningList");
|
||||
final int cookie = traceBegin("updateRunningList");
|
||||
final long now = SystemClock.uptimeMillis();
|
||||
|
||||
// If someone is waiting for a state, everything is runnable now
|
||||
@@ -449,7 +464,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
});
|
||||
}
|
||||
|
||||
traceEnd(TAG, cookie);
|
||||
traceEnd(cookie);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -516,7 +531,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
if (queue != null) {
|
||||
// If queue was running a broadcast, fail it
|
||||
if (queue.isActive()) {
|
||||
finishReceiverLocked(queue, BroadcastRecord.DELIVERY_FAILURE);
|
||||
finishReceiverLocked(queue, BroadcastRecord.DELIVERY_FAILURE,
|
||||
"onApplicationCleanupLocked");
|
||||
}
|
||||
|
||||
// Skip any pending registered receivers, since the old process
|
||||
@@ -544,6 +560,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
public void enqueueBroadcastLocked(@NonNull BroadcastRecord r) {
|
||||
if (DEBUG_BROADCAST) logv("Enqueuing " + r + " for " + r.receivers.size() + " receivers");
|
||||
|
||||
final int cookie = traceBegin("enqueueBroadcast");
|
||||
r.applySingletonPolicy(mService);
|
||||
|
||||
final IntentFilter removeMatchingFilter = (r.options != null)
|
||||
@@ -613,6 +630,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
if (r.receivers.isEmpty()) {
|
||||
scheduleResultTo(r);
|
||||
}
|
||||
|
||||
traceEnd(cookie);
|
||||
}
|
||||
|
||||
private void applyDeliveryGroupPolicy(@NonNull BroadcastRecord r) {
|
||||
@@ -668,7 +687,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
// Ignore registered receivers from a previous PID
|
||||
if (receiver instanceof BroadcastFilter) {
|
||||
mRunningColdStart = null;
|
||||
finishReceiverLocked(queue, BroadcastRecord.DELIVERY_SKIPPED);
|
||||
enqueueFinishReceiver(queue, BroadcastRecord.DELIVERY_SKIPPED,
|
||||
"BroadcastFilter for cold app");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -690,7 +710,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
hostingRecord, zygotePolicyFlags, allowWhileBooting, false);
|
||||
if (queue.app == null) {
|
||||
mRunningColdStart = null;
|
||||
finishReceiverLocked(queue, BroadcastRecord.DELIVERY_FAILURE);
|
||||
enqueueFinishReceiver(queue, BroadcastRecord.DELIVERY_FAILURE,
|
||||
"startProcessLocked failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -721,33 +742,37 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
// If someone already finished this broadcast, finish immediately
|
||||
final int oldDeliveryState = getDeliveryState(r, index);
|
||||
if (isDeliveryStateTerminal(oldDeliveryState)) {
|
||||
finishReceiverLocked(queue, oldDeliveryState);
|
||||
enqueueFinishReceiver(queue, oldDeliveryState, "already terminal state");
|
||||
return;
|
||||
}
|
||||
|
||||
// Consider additional cases where we'd want to finish immediately
|
||||
if (app.isInFullBackup()) {
|
||||
finishReceiverLocked(queue, BroadcastRecord.DELIVERY_SKIPPED);
|
||||
enqueueFinishReceiver(queue, BroadcastRecord.DELIVERY_SKIPPED, "isInFullBackup");
|
||||
return;
|
||||
}
|
||||
if (mSkipPolicy.shouldSkip(r, receiver)) {
|
||||
finishReceiverLocked(queue, BroadcastRecord.DELIVERY_SKIPPED);
|
||||
enqueueFinishReceiver(queue, BroadcastRecord.DELIVERY_SKIPPED, "mSkipPolicy");
|
||||
return;
|
||||
}
|
||||
final Intent receiverIntent = r.getReceiverIntent(receiver);
|
||||
if (receiverIntent == null) {
|
||||
finishReceiverLocked(queue, BroadcastRecord.DELIVERY_SKIPPED);
|
||||
enqueueFinishReceiver(queue, BroadcastRecord.DELIVERY_SKIPPED, "isInFullBackup");
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore registered receivers from a previous PID
|
||||
if ((receiver instanceof BroadcastFilter)
|
||||
&& ((BroadcastFilter) receiver).receiverList.pid != app.getPid()) {
|
||||
finishReceiverLocked(queue, BroadcastRecord.DELIVERY_SKIPPED);
|
||||
enqueueFinishReceiver(queue, BroadcastRecord.DELIVERY_SKIPPED,
|
||||
"BroadcastFilter for mismatched PID");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mService.mProcessesReady && !r.timeoutExempt) {
|
||||
// Skip ANR tracking early during boot, when requested, or when we
|
||||
// immediately assume delivery success
|
||||
final boolean assumeDelivered = (receiver instanceof BroadcastFilter) && !r.ordered;
|
||||
if (mService.mProcessesReady && !r.timeoutExempt && !assumeDelivered) {
|
||||
queue.lastCpuDelayTime = queue.app.getCpuDelayTime();
|
||||
|
||||
final long timeout = r.isForeground() ? mFgConstants.TIMEOUT : mBgConstants.TIMEOUT;
|
||||
@@ -775,7 +800,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
}
|
||||
|
||||
if (DEBUG_BROADCAST) logv("Scheduling " + r + " to warm " + app);
|
||||
setDeliveryState(queue, app, r, index, receiver, BroadcastRecord.DELIVERY_SCHEDULED);
|
||||
setDeliveryState(queue, app, r, index, receiver, BroadcastRecord.DELIVERY_SCHEDULED,
|
||||
"scheduleReceiverWarmLocked");
|
||||
|
||||
final IApplicationThread thread = app.getOnewayThread();
|
||||
if (thread != null) {
|
||||
@@ -789,8 +815,9 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
|
||||
// TODO: consider making registered receivers of unordered
|
||||
// broadcasts report results to detect ANRs
|
||||
if (!r.ordered) {
|
||||
finishReceiverLocked(queue, BroadcastRecord.DELIVERY_DELIVERED);
|
||||
if (assumeDelivered) {
|
||||
enqueueFinishReceiver(queue, BroadcastRecord.DELIVERY_DELIVERED,
|
||||
"assuming delivered");
|
||||
}
|
||||
} else {
|
||||
notifyScheduleReceiver(app, r, (ResolveInfo) receiver);
|
||||
@@ -804,10 +831,11 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
logw(msg);
|
||||
app.scheduleCrashLocked(msg, CannotDeliverBroadcastException.TYPE_ID, null);
|
||||
app.setKilled(true);
|
||||
finishReceiverLocked(queue, BroadcastRecord.DELIVERY_FAILURE);
|
||||
enqueueFinishReceiver(queue, BroadcastRecord.DELIVERY_FAILURE, "remote app");
|
||||
}
|
||||
} else {
|
||||
finishReceiverLocked(queue, BroadcastRecord.DELIVERY_FAILURE);
|
||||
enqueueFinishReceiver(queue, BroadcastRecord.DELIVERY_FAILURE,
|
||||
"missing IApplicationThread");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -851,7 +879,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
}
|
||||
|
||||
private void deliveryTimeoutHardLocked(@NonNull BroadcastProcessQueue queue) {
|
||||
finishReceiverLocked(queue, BroadcastRecord.DELIVERY_TIMEOUT);
|
||||
finishReceiverLocked(queue, BroadcastRecord.DELIVERY_TIMEOUT,
|
||||
"deliveryTimeoutHardLocked");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -878,16 +907,17 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
if (r.resultAbort) {
|
||||
for (int i = r.terminalCount + 1; i < r.receivers.size(); i++) {
|
||||
setDeliveryState(null, null, r, i, r.receivers.get(i),
|
||||
BroadcastRecord.DELIVERY_SKIPPED);
|
||||
BroadcastRecord.DELIVERY_SKIPPED, "resultAbort");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return finishReceiverLocked(queue, BroadcastRecord.DELIVERY_DELIVERED);
|
||||
return finishReceiverLocked(queue, BroadcastRecord.DELIVERY_DELIVERED, "remote app");
|
||||
}
|
||||
|
||||
private boolean finishReceiverLocked(@NonNull BroadcastProcessQueue queue,
|
||||
@DeliveryState int deliveryState) {
|
||||
@DeliveryState int deliveryState, @NonNull String reason) {
|
||||
final int cookie = traceBegin("finishReceiver");
|
||||
checkState(queue.isActive(), "isActive");
|
||||
|
||||
final ProcessRecord app = queue.app;
|
||||
@@ -895,7 +925,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
final int index = queue.getActiveIndex();
|
||||
final Object receiver = r.receivers.get(index);
|
||||
|
||||
setDeliveryState(queue, app, r, index, receiver, deliveryState);
|
||||
setDeliveryState(queue, app, r, index, receiver, deliveryState, reason);
|
||||
|
||||
if (deliveryState == BroadcastRecord.DELIVERY_TIMEOUT) {
|
||||
r.anrCount++;
|
||||
@@ -914,11 +944,12 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
final boolean shouldRetire =
|
||||
(queue.getActiveCountSinceIdle() >= mConstants.MAX_RUNNING_ACTIVE_BROADCASTS);
|
||||
|
||||
final boolean res;
|
||||
if (queue.isRunnable() && queue.isProcessWarm() && !shouldRetire) {
|
||||
// We're on a roll; move onto the next broadcast for this process
|
||||
queue.makeActiveNextPending();
|
||||
scheduleReceiverWarmLocked(queue);
|
||||
return true;
|
||||
res = true;
|
||||
} else {
|
||||
// We've drained running broadcasts; maybe move back to runnable
|
||||
queue.makeActiveIdle();
|
||||
@@ -932,8 +963,10 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
// Tell other OS components that app is not actively running, giving
|
||||
// a chance to update OOM adjustment
|
||||
notifyStoppedRunning(queue);
|
||||
return false;
|
||||
res = false;
|
||||
}
|
||||
traceEnd(cookie);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -942,7 +975,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
*/
|
||||
private void setDeliveryState(@Nullable BroadcastProcessQueue queue,
|
||||
@Nullable ProcessRecord app, @NonNull BroadcastRecord r, int index,
|
||||
@NonNull Object receiver, @DeliveryState int newDeliveryState) {
|
||||
@NonNull Object receiver, @DeliveryState int newDeliveryState, String reason) {
|
||||
final int cookie = traceBegin("setDeliveryState");
|
||||
final int oldDeliveryState = getDeliveryState(r, index);
|
||||
|
||||
// Only apply state when we haven't already reached a terminal state;
|
||||
@@ -970,7 +1004,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
logw("Delivery state of " + r + " to " + receiver
|
||||
+ " via " + app + " changed from "
|
||||
+ deliveryStateToString(oldDeliveryState) + " to "
|
||||
+ deliveryStateToString(newDeliveryState));
|
||||
+ deliveryStateToString(newDeliveryState) + " because " + reason);
|
||||
}
|
||||
|
||||
r.terminalCount++;
|
||||
@@ -1000,6 +1034,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
enqueueUpdateRunningList();
|
||||
}
|
||||
}
|
||||
|
||||
traceEnd(cookie);
|
||||
}
|
||||
|
||||
private @DeliveryState int getDeliveryState(@NonNull BroadcastRecord r, int index) {
|
||||
@@ -1060,7 +1096,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
* of it matching a predicate.
|
||||
*/
|
||||
private final BroadcastConsumer mBroadcastConsumerSkip = (r, i) -> {
|
||||
setDeliveryState(null, null, r, i, r.receivers.get(i), BroadcastRecord.DELIVERY_SKIPPED);
|
||||
setDeliveryState(null, null, r, i, r.receivers.get(i), BroadcastRecord.DELIVERY_SKIPPED,
|
||||
"mBroadcastConsumerSkip");
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1068,7 +1105,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
* cancelled, usually as a result of it matching a predicate.
|
||||
*/
|
||||
private final BroadcastConsumer mBroadcastConsumerSkipAndCanceled = (r, i) -> {
|
||||
setDeliveryState(null, null, r, i, r.receivers.get(i), BroadcastRecord.DELIVERY_SKIPPED);
|
||||
setDeliveryState(null, null, r, i, r.receivers.get(i), BroadcastRecord.DELIVERY_SKIPPED,
|
||||
"mBroadcastConsumerSkipAndCanceled");
|
||||
r.resultCode = Activity.RESULT_CANCELED;
|
||||
r.resultData = null;
|
||||
r.resultExtras = null;
|
||||
@@ -1260,18 +1298,6 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
}
|
||||
}
|
||||
|
||||
private int traceBegin(String trackName, String methodName) {
|
||||
final int cookie = methodName.hashCode();
|
||||
Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
|
||||
trackName, methodName, cookie);
|
||||
return cookie;
|
||||
}
|
||||
|
||||
private void traceEnd(String trackName, int cookie) {
|
||||
Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
|
||||
trackName, cookie);
|
||||
}
|
||||
|
||||
private void updateWarmProcess(@NonNull BroadcastProcessQueue queue) {
|
||||
if (!queue.isProcessWarm()) {
|
||||
queue.setProcess(mService.getProcessRecordLocked(queue.processName, queue.uid));
|
||||
|
||||
@@ -21,6 +21,7 @@ import static com.android.server.am.ActivityManagerService.checkComponentPermiss
|
||||
import static com.android.server.am.BroadcastQueue.TAG;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.AppGlobals;
|
||||
import android.app.AppOpsManager;
|
||||
@@ -42,6 +43,8 @@ import android.util.Slog;
|
||||
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Policy logic that decides if delivery of a particular {@link BroadcastRecord}
|
||||
* should be skipped for a given {@link ResolveInfo} or {@link BroadcastFilter}.
|
||||
@@ -51,8 +54,8 @@ import com.android.internal.util.ArrayUtils;
|
||||
public class BroadcastSkipPolicy {
|
||||
private final ActivityManagerService mService;
|
||||
|
||||
public BroadcastSkipPolicy(ActivityManagerService service) {
|
||||
mService = service;
|
||||
public BroadcastSkipPolicy(@NonNull ActivityManagerService service) {
|
||||
mService = Objects.requireNonNull(service);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,18 +63,39 @@ public class BroadcastSkipPolicy {
|
||||
* the given {@link BroadcastFilter} or {@link ResolveInfo}.
|
||||
*/
|
||||
public boolean shouldSkip(@NonNull BroadcastRecord r, @NonNull Object target) {
|
||||
if (target instanceof BroadcastFilter) {
|
||||
return shouldSkip(r, (BroadcastFilter) target);
|
||||
final String msg = shouldSkipMessage(r, target);
|
||||
if (msg != null) {
|
||||
Slog.w(TAG, msg);
|
||||
return true;
|
||||
} else {
|
||||
return shouldSkip(r, (ResolveInfo) target);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given {@link BroadcastRecord} is eligible to be sent to
|
||||
* the given {@link BroadcastFilter} or {@link ResolveInfo}.
|
||||
*
|
||||
* @return message indicating why the argument should be skipped, otherwise
|
||||
* {@code null} if it can proceed.
|
||||
*/
|
||||
public @Nullable String shouldSkipMessage(@NonNull BroadcastRecord r, @NonNull Object target) {
|
||||
if (target instanceof BroadcastFilter) {
|
||||
return shouldSkipMessage(r, (BroadcastFilter) target);
|
||||
} else {
|
||||
return shouldSkipMessage(r, (ResolveInfo) target);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given {@link BroadcastRecord} is eligible to be sent to
|
||||
* the given {@link ResolveInfo}.
|
||||
*
|
||||
* @return message indicating why the argument should be skipped, otherwise
|
||||
* {@code null} if it can proceed.
|
||||
*/
|
||||
public boolean shouldSkip(@NonNull BroadcastRecord r, @NonNull ResolveInfo info) {
|
||||
private @Nullable String shouldSkipMessage(@NonNull BroadcastRecord r,
|
||||
@NonNull ResolveInfo info) {
|
||||
final BroadcastOptions brOptions = r.options;
|
||||
final ComponentName component = new ComponentName(
|
||||
info.activityInfo.applicationInfo.packageName,
|
||||
@@ -82,58 +106,52 @@ public class BroadcastSkipPolicy {
|
||||
< brOptions.getMinManifestReceiverApiLevel() ||
|
||||
info.activityInfo.applicationInfo.targetSdkVersion
|
||||
> brOptions.getMaxManifestReceiverApiLevel())) {
|
||||
Slog.w(TAG, "Target SDK mismatch: receiver " + info.activityInfo
|
||||
return "Target SDK mismatch: receiver " + info.activityInfo
|
||||
+ " targets " + info.activityInfo.applicationInfo.targetSdkVersion
|
||||
+ " but delivery restricted to ["
|
||||
+ brOptions.getMinManifestReceiverApiLevel() + ", "
|
||||
+ brOptions.getMaxManifestReceiverApiLevel()
|
||||
+ "] broadcasting " + broadcastDescription(r, component));
|
||||
return true;
|
||||
+ "] broadcasting " + broadcastDescription(r, component);
|
||||
}
|
||||
if (brOptions != null &&
|
||||
!brOptions.testRequireCompatChange(info.activityInfo.applicationInfo.uid)) {
|
||||
Slog.w(TAG, "Compat change filtered: broadcasting " + broadcastDescription(r, component)
|
||||
return "Compat change filtered: broadcasting " + broadcastDescription(r, component)
|
||||
+ " to uid " + info.activityInfo.applicationInfo.uid + " due to compat change "
|
||||
+ r.options.getRequireCompatChangeId());
|
||||
return true;
|
||||
+ r.options.getRequireCompatChangeId();
|
||||
}
|
||||
if (!mService.validateAssociationAllowedLocked(r.callerPackage, r.callingUid,
|
||||
component.getPackageName(), info.activityInfo.applicationInfo.uid)) {
|
||||
Slog.w(TAG, "Association not allowed: broadcasting "
|
||||
+ broadcastDescription(r, component));
|
||||
return true;
|
||||
return "Association not allowed: broadcasting "
|
||||
+ broadcastDescription(r, component);
|
||||
}
|
||||
if (!mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
|
||||
r.callingPid, r.resolvedType, info.activityInfo.applicationInfo.uid)) {
|
||||
Slog.w(TAG, "Firewall blocked: broadcasting "
|
||||
+ broadcastDescription(r, component));
|
||||
return true;
|
||||
return "Firewall blocked: broadcasting "
|
||||
+ broadcastDescription(r, component);
|
||||
}
|
||||
int perm = checkComponentPermission(info.activityInfo.permission,
|
||||
r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
|
||||
info.activityInfo.exported);
|
||||
if (perm != PackageManager.PERMISSION_GRANTED) {
|
||||
if (!info.activityInfo.exported) {
|
||||
Slog.w(TAG, "Permission Denial: broadcasting "
|
||||
return "Permission Denial: broadcasting "
|
||||
+ broadcastDescription(r, component)
|
||||
+ " is not exported from uid " + info.activityInfo.applicationInfo.uid);
|
||||
+ " is not exported from uid " + info.activityInfo.applicationInfo.uid;
|
||||
} else {
|
||||
Slog.w(TAG, "Permission Denial: broadcasting "
|
||||
return "Permission Denial: broadcasting "
|
||||
+ broadcastDescription(r, component)
|
||||
+ " requires " + info.activityInfo.permission);
|
||||
+ " requires " + info.activityInfo.permission;
|
||||
}
|
||||
return true;
|
||||
} else if (info.activityInfo.permission != null) {
|
||||
final int opCode = AppOpsManager.permissionToOpCode(info.activityInfo.permission);
|
||||
if (opCode != AppOpsManager.OP_NONE && mService.getAppOpsManager().noteOpNoThrow(opCode,
|
||||
r.callingUid, r.callerPackage, r.callerFeatureId,
|
||||
"Broadcast delivered to " + info.activityInfo.name)
|
||||
!= AppOpsManager.MODE_ALLOWED) {
|
||||
Slog.w(TAG, "Appop Denial: broadcasting "
|
||||
return "Appop Denial: broadcasting "
|
||||
+ broadcastDescription(r, component)
|
||||
+ " requires appop " + AppOpsManager.permissionToOp(
|
||||
info.activityInfo.permission));
|
||||
return true;
|
||||
info.activityInfo.permission);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,38 +160,34 @@ public class BroadcastSkipPolicy {
|
||||
android.Manifest.permission.INTERACT_ACROSS_USERS,
|
||||
info.activityInfo.applicationInfo.uid)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
Slog.w(TAG, "Permission Denial: Receiver " + component.flattenToShortString()
|
||||
return "Permission Denial: Receiver " + component.flattenToShortString()
|
||||
+ " requests FLAG_SINGLE_USER, but app does not hold "
|
||||
+ android.Manifest.permission.INTERACT_ACROSS_USERS);
|
||||
return true;
|
||||
+ android.Manifest.permission.INTERACT_ACROSS_USERS;
|
||||
}
|
||||
}
|
||||
if (info.activityInfo.applicationInfo.isInstantApp()
|
||||
&& r.callingUid != info.activityInfo.applicationInfo.uid) {
|
||||
Slog.w(TAG, "Instant App Denial: receiving "
|
||||
return "Instant App Denial: receiving "
|
||||
+ r.intent
|
||||
+ " to " + component.flattenToShortString()
|
||||
+ " due to sender " + r.callerPackage
|
||||
+ " (uid " + r.callingUid + ")"
|
||||
+ " Instant Apps do not support manifest receivers");
|
||||
return true;
|
||||
+ " Instant Apps do not support manifest receivers";
|
||||
}
|
||||
if (r.callerInstantApp
|
||||
&& (info.activityInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) == 0
|
||||
&& r.callingUid != info.activityInfo.applicationInfo.uid) {
|
||||
Slog.w(TAG, "Instant App Denial: receiving "
|
||||
return "Instant App Denial: receiving "
|
||||
+ r.intent
|
||||
+ " to " + component.flattenToShortString()
|
||||
+ " requires receiver have visibleToInstantApps set"
|
||||
+ " due to sender " + r.callerPackage
|
||||
+ " (uid " + r.callingUid + ")");
|
||||
return true;
|
||||
+ " (uid " + r.callingUid + ")";
|
||||
}
|
||||
if (r.curApp != null && r.curApp.mErrorState.isCrashing()) {
|
||||
// If the target process is crashing, just skip it.
|
||||
Slog.w(TAG, "Skipping deliver ordered [" + r.queue.toString() + "] " + r
|
||||
+ " to " + r.curApp + ": process crashing");
|
||||
return true;
|
||||
return "Skipping deliver ordered [" + r.queue.toString() + "] " + r
|
||||
+ " to " + r.curApp + ": process crashing";
|
||||
}
|
||||
|
||||
boolean isAvailable = false;
|
||||
@@ -183,15 +197,13 @@ public class BroadcastSkipPolicy {
|
||||
UserHandle.getUserId(info.activityInfo.applicationInfo.uid));
|
||||
} catch (Exception e) {
|
||||
// all such failures mean we skip this receiver
|
||||
Slog.w(TAG, "Exception getting recipient info for "
|
||||
+ info.activityInfo.packageName, e);
|
||||
return "Exception getting recipient info for "
|
||||
+ info.activityInfo.packageName;
|
||||
}
|
||||
if (!isAvailable) {
|
||||
Slog.w(TAG,
|
||||
"Skipping delivery to " + info.activityInfo.packageName + " / "
|
||||
return "Skipping delivery to " + info.activityInfo.packageName + " / "
|
||||
+ info.activityInfo.applicationInfo.uid
|
||||
+ " : package no longer available");
|
||||
return true;
|
||||
+ " : package no longer available";
|
||||
}
|
||||
|
||||
// If permissions need a review before any of the app components can run, we drop
|
||||
@@ -201,10 +213,8 @@ public class BroadcastSkipPolicy {
|
||||
if (!requestStartTargetPermissionsReviewIfNeededLocked(r,
|
||||
info.activityInfo.packageName, UserHandle.getUserId(
|
||||
info.activityInfo.applicationInfo.uid))) {
|
||||
Slog.w(TAG,
|
||||
"Skipping delivery: permission review required for "
|
||||
+ broadcastDescription(r, component));
|
||||
return true;
|
||||
return "Skipping delivery: permission review required for "
|
||||
+ broadcastDescription(r, component);
|
||||
}
|
||||
|
||||
final int allowed = mService.getAppStartModeLOSP(
|
||||
@@ -216,10 +226,9 @@ public class BroadcastSkipPolicy {
|
||||
// to it and the app is in a state that should not receive it
|
||||
// (depending on how getAppStartModeLOSP has determined that).
|
||||
if (allowed == ActivityManager.APP_START_MODE_DISABLED) {
|
||||
Slog.w(TAG, "Background execution disabled: receiving "
|
||||
return "Background execution disabled: receiving "
|
||||
+ r.intent + " to "
|
||||
+ component.flattenToShortString());
|
||||
return true;
|
||||
+ component.flattenToShortString();
|
||||
} else if (((r.intent.getFlags()&Intent.FLAG_RECEIVER_EXCLUDE_BACKGROUND) != 0)
|
||||
|| (r.intent.getComponent() == null
|
||||
&& r.intent.getPackage() == null
|
||||
@@ -228,10 +237,9 @@ public class BroadcastSkipPolicy {
|
||||
&& !isSignaturePerm(r.requiredPermissions))) {
|
||||
mService.addBackgroundCheckViolationLocked(r.intent.getAction(),
|
||||
component.getPackageName());
|
||||
Slog.w(TAG, "Background execution not allowed: receiving "
|
||||
return "Background execution not allowed: receiving "
|
||||
+ r.intent + " to "
|
||||
+ component.flattenToShortString());
|
||||
return true;
|
||||
+ component.flattenToShortString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,10 +247,8 @@ public class BroadcastSkipPolicy {
|
||||
&& !mService.mUserController
|
||||
.isUserRunning(UserHandle.getUserId(info.activityInfo.applicationInfo.uid),
|
||||
0 /* flags */)) {
|
||||
Slog.w(TAG,
|
||||
"Skipping delivery to " + info.activityInfo.packageName + " / "
|
||||
+ info.activityInfo.applicationInfo.uid + " : user is not running");
|
||||
return true;
|
||||
return "Skipping delivery to " + info.activityInfo.packageName + " / "
|
||||
+ info.activityInfo.applicationInfo.uid + " : user is not running";
|
||||
}
|
||||
|
||||
if (r.excludedPermissions != null && r.excludedPermissions.length > 0) {
|
||||
@@ -268,13 +274,15 @@ public class BroadcastSkipPolicy {
|
||||
info.activityInfo.applicationInfo.uid,
|
||||
info.activityInfo.packageName)
|
||||
== AppOpsManager.MODE_ALLOWED)) {
|
||||
return true;
|
||||
return "Skipping delivery to " + info.activityInfo.packageName
|
||||
+ " due to excluded permission " + excludedPermission;
|
||||
}
|
||||
} else {
|
||||
// When there is no app op associated with the permission,
|
||||
// skip when permission is granted.
|
||||
if (perm == PackageManager.PERMISSION_GRANTED) {
|
||||
return true;
|
||||
return "Skipping delivery to " + info.activityInfo.packageName
|
||||
+ " due to excluded permission " + excludedPermission;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -283,13 +291,12 @@ public class BroadcastSkipPolicy {
|
||||
// Check that the receiver does *not* belong to any of the excluded packages
|
||||
if (r.excludedPackages != null && r.excludedPackages.length > 0) {
|
||||
if (ArrayUtils.contains(r.excludedPackages, component.getPackageName())) {
|
||||
Slog.w(TAG, "Skipping delivery of excluded package "
|
||||
return "Skipping delivery of excluded package "
|
||||
+ r.intent + " to "
|
||||
+ component.flattenToShortString()
|
||||
+ " excludes package " + component.getPackageName()
|
||||
+ " due to sender " + r.callerPackage
|
||||
+ " (uid " + r.callingUid + ")");
|
||||
return true;
|
||||
+ " (uid " + r.callingUid + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,95 +314,94 @@ public class BroadcastSkipPolicy {
|
||||
perm = PackageManager.PERMISSION_DENIED;
|
||||
}
|
||||
if (perm != PackageManager.PERMISSION_GRANTED) {
|
||||
Slog.w(TAG, "Permission Denial: receiving "
|
||||
return "Permission Denial: receiving "
|
||||
+ r.intent + " to "
|
||||
+ component.flattenToShortString()
|
||||
+ " requires " + requiredPermission
|
||||
+ " due to sender " + r.callerPackage
|
||||
+ " (uid " + r.callingUid + ")");
|
||||
return true;
|
||||
+ " (uid " + r.callingUid + ")";
|
||||
}
|
||||
int appOp = AppOpsManager.permissionToOpCode(requiredPermission);
|
||||
if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp) {
|
||||
if (!noteOpForManifestReceiver(appOp, r, info, component)) {
|
||||
return true;
|
||||
return "Skipping delivery to " + info.activityInfo.packageName
|
||||
+ " due to required appop " + appOp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (r.appOp != AppOpsManager.OP_NONE) {
|
||||
if (!noteOpForManifestReceiver(r.appOp, r, info, component)) {
|
||||
return true;
|
||||
return "Skipping delivery to " + info.activityInfo.packageName
|
||||
+ " due to required appop " + r.appOp;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given {@link BroadcastRecord} is eligible to be sent to
|
||||
* the given {@link BroadcastFilter}.
|
||||
*
|
||||
* @return message indicating why the argument should be skipped, otherwise
|
||||
* {@code null} if it can proceed.
|
||||
*/
|
||||
public boolean shouldSkip(@NonNull BroadcastRecord r, @NonNull BroadcastFilter filter) {
|
||||
private @Nullable String shouldSkipMessage(@NonNull BroadcastRecord r,
|
||||
@NonNull BroadcastFilter filter) {
|
||||
if (r.options != null && !r.options.testRequireCompatChange(filter.owningUid)) {
|
||||
Slog.w(TAG, "Compat change filtered: broadcasting " + r.intent.toString()
|
||||
return "Compat change filtered: broadcasting " + r.intent.toString()
|
||||
+ " to uid " + filter.owningUid + " due to compat change "
|
||||
+ r.options.getRequireCompatChangeId());
|
||||
return true;
|
||||
+ r.options.getRequireCompatChangeId();
|
||||
}
|
||||
if (!mService.validateAssociationAllowedLocked(r.callerPackage, r.callingUid,
|
||||
filter.packageName, filter.owningUid)) {
|
||||
Slog.w(TAG, "Association not allowed: broadcasting "
|
||||
return "Association not allowed: broadcasting "
|
||||
+ r.intent.toString()
|
||||
+ " from " + r.callerPackage + " (pid=" + r.callingPid
|
||||
+ ", uid=" + r.callingUid + ") to " + filter.packageName + " through "
|
||||
+ filter);
|
||||
return true;
|
||||
+ filter;
|
||||
}
|
||||
if (!mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
|
||||
r.callingPid, r.resolvedType, filter.receiverList.uid)) {
|
||||
Slog.w(TAG, "Firewall blocked: broadcasting "
|
||||
return "Firewall blocked: broadcasting "
|
||||
+ r.intent.toString()
|
||||
+ " from " + r.callerPackage + " (pid=" + r.callingPid
|
||||
+ ", uid=" + r.callingUid + ") to " + filter.packageName + " through "
|
||||
+ filter);
|
||||
return true;
|
||||
+ filter;
|
||||
}
|
||||
// Check that the sender has permission to send to this receiver
|
||||
if (filter.requiredPermission != null) {
|
||||
int perm = checkComponentPermission(filter.requiredPermission,
|
||||
r.callingPid, r.callingUid, -1, true);
|
||||
if (perm != PackageManager.PERMISSION_GRANTED) {
|
||||
Slog.w(TAG, "Permission Denial: broadcasting "
|
||||
return "Permission Denial: broadcasting "
|
||||
+ r.intent.toString()
|
||||
+ " from " + r.callerPackage + " (pid="
|
||||
+ r.callingPid + ", uid=" + r.callingUid + ")"
|
||||
+ " requires " + filter.requiredPermission
|
||||
+ " due to registered receiver " + filter);
|
||||
return true;
|
||||
+ " due to registered receiver " + filter;
|
||||
} else {
|
||||
final int opCode = AppOpsManager.permissionToOpCode(filter.requiredPermission);
|
||||
if (opCode != AppOpsManager.OP_NONE
|
||||
&& mService.getAppOpsManager().noteOpNoThrow(opCode, r.callingUid,
|
||||
r.callerPackage, r.callerFeatureId, "Broadcast sent to protected receiver")
|
||||
!= AppOpsManager.MODE_ALLOWED) {
|
||||
Slog.w(TAG, "Appop Denial: broadcasting "
|
||||
return "Appop Denial: broadcasting "
|
||||
+ r.intent.toString()
|
||||
+ " from " + r.callerPackage + " (pid="
|
||||
+ r.callingPid + ", uid=" + r.callingUid + ")"
|
||||
+ " requires appop " + AppOpsManager.permissionToOp(
|
||||
filter.requiredPermission)
|
||||
+ " due to registered receiver " + filter);
|
||||
return true;
|
||||
+ " due to registered receiver " + filter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((filter.receiverList.app == null || filter.receiverList.app.isKilled()
|
||||
|| filter.receiverList.app.mErrorState.isCrashing())) {
|
||||
Slog.w(TAG, "Skipping deliver [" + r.queue.toString() + "] " + r
|
||||
+ " to " + filter.receiverList + ": process gone or crashing");
|
||||
return true;
|
||||
return "Skipping deliver [" + r.queue.toString() + "] " + r
|
||||
+ " to " + filter.receiverList + ": process gone or crashing";
|
||||
}
|
||||
|
||||
// Ensure that broadcasts are only sent to other Instant Apps if they are marked as
|
||||
@@ -405,28 +411,26 @@ public class BroadcastSkipPolicy {
|
||||
|
||||
if (!visibleToInstantApps && filter.instantApp
|
||||
&& filter.receiverList.uid != r.callingUid) {
|
||||
Slog.w(TAG, "Instant App Denial: receiving "
|
||||
return "Instant App Denial: receiving "
|
||||
+ r.intent.toString()
|
||||
+ " to " + filter.receiverList.app
|
||||
+ " (pid=" + filter.receiverList.pid
|
||||
+ ", uid=" + filter.receiverList.uid + ")"
|
||||
+ " due to sender " + r.callerPackage
|
||||
+ " (uid " + r.callingUid + ")"
|
||||
+ " not specifying FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS");
|
||||
return true;
|
||||
+ " not specifying FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS";
|
||||
}
|
||||
|
||||
if (!filter.visibleToInstantApp && r.callerInstantApp
|
||||
&& filter.receiverList.uid != r.callingUid) {
|
||||
Slog.w(TAG, "Instant App Denial: receiving "
|
||||
return "Instant App Denial: receiving "
|
||||
+ r.intent.toString()
|
||||
+ " to " + filter.receiverList.app
|
||||
+ " (pid=" + filter.receiverList.pid
|
||||
+ ", uid=" + filter.receiverList.uid + ")"
|
||||
+ " requires receiver be visible to instant apps"
|
||||
+ " due to sender " + r.callerPackage
|
||||
+ " (uid " + r.callingUid + ")");
|
||||
return true;
|
||||
+ " (uid " + r.callingUid + ")";
|
||||
}
|
||||
|
||||
// Check that the receiver has the required permission(s) to receive this broadcast.
|
||||
@@ -436,15 +440,14 @@ public class BroadcastSkipPolicy {
|
||||
int perm = checkComponentPermission(requiredPermission,
|
||||
filter.receiverList.pid, filter.receiverList.uid, -1, true);
|
||||
if (perm != PackageManager.PERMISSION_GRANTED) {
|
||||
Slog.w(TAG, "Permission Denial: receiving "
|
||||
return "Permission Denial: receiving "
|
||||
+ r.intent.toString()
|
||||
+ " to " + filter.receiverList.app
|
||||
+ " (pid=" + filter.receiverList.pid
|
||||
+ ", uid=" + filter.receiverList.uid + ")"
|
||||
+ " requires " + requiredPermission
|
||||
+ " due to sender " + r.callerPackage
|
||||
+ " (uid " + r.callingUid + ")");
|
||||
return true;
|
||||
+ " (uid " + r.callingUid + ")";
|
||||
}
|
||||
int appOp = AppOpsManager.permissionToOpCode(requiredPermission);
|
||||
if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp
|
||||
@@ -452,7 +455,7 @@ public class BroadcastSkipPolicy {
|
||||
filter.receiverList.uid, filter.packageName, filter.featureId,
|
||||
"Broadcast delivered to registered receiver " + filter.receiverId)
|
||||
!= AppOpsManager.MODE_ALLOWED) {
|
||||
Slog.w(TAG, "Appop Denial: receiving "
|
||||
return "Appop Denial: receiving "
|
||||
+ r.intent.toString()
|
||||
+ " to " + filter.receiverList.app
|
||||
+ " (pid=" + filter.receiverList.pid
|
||||
@@ -460,8 +463,7 @@ public class BroadcastSkipPolicy {
|
||||
+ " requires appop " + AppOpsManager.permissionToOp(
|
||||
requiredPermission)
|
||||
+ " due to sender " + r.callerPackage
|
||||
+ " (uid " + r.callingUid + ")");
|
||||
return true;
|
||||
+ " (uid " + r.callingUid + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -469,14 +471,13 @@ public class BroadcastSkipPolicy {
|
||||
int perm = checkComponentPermission(null,
|
||||
filter.receiverList.pid, filter.receiverList.uid, -1, true);
|
||||
if (perm != PackageManager.PERMISSION_GRANTED) {
|
||||
Slog.w(TAG, "Permission Denial: security check failed when receiving "
|
||||
return "Permission Denial: security check failed when receiving "
|
||||
+ r.intent.toString()
|
||||
+ " to " + filter.receiverList.app
|
||||
+ " (pid=" + filter.receiverList.pid
|
||||
+ ", uid=" + filter.receiverList.uid + ")"
|
||||
+ " due to sender " + r.callerPackage
|
||||
+ " (uid " + r.callingUid + ")");
|
||||
return true;
|
||||
+ " (uid " + r.callingUid + ")";
|
||||
}
|
||||
}
|
||||
// Check that the receiver does *not* have any excluded permissions
|
||||
@@ -496,7 +497,7 @@ public class BroadcastSkipPolicy {
|
||||
filter.receiverList.uid,
|
||||
filter.packageName)
|
||||
== AppOpsManager.MODE_ALLOWED)) {
|
||||
Slog.w(TAG, "Appop Denial: receiving "
|
||||
return "Appop Denial: receiving "
|
||||
+ r.intent.toString()
|
||||
+ " to " + filter.receiverList.app
|
||||
+ " (pid=" + filter.receiverList.pid
|
||||
@@ -504,22 +505,20 @@ public class BroadcastSkipPolicy {
|
||||
+ " excludes appop " + AppOpsManager.permissionToOp(
|
||||
excludedPermission)
|
||||
+ " due to sender " + r.callerPackage
|
||||
+ " (uid " + r.callingUid + ")");
|
||||
return true;
|
||||
+ " (uid " + r.callingUid + ")";
|
||||
}
|
||||
} else {
|
||||
// When there is no app op associated with the permission,
|
||||
// skip when permission is granted.
|
||||
if (perm == PackageManager.PERMISSION_GRANTED) {
|
||||
Slog.w(TAG, "Permission Denial: receiving "
|
||||
return "Permission Denial: receiving "
|
||||
+ r.intent.toString()
|
||||
+ " to " + filter.receiverList.app
|
||||
+ " (pid=" + filter.receiverList.pid
|
||||
+ ", uid=" + filter.receiverList.uid + ")"
|
||||
+ " excludes " + excludedPermission
|
||||
+ " due to sender " + r.callerPackage
|
||||
+ " (uid " + r.callingUid + ")");
|
||||
return true;
|
||||
+ " (uid " + r.callingUid + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -528,15 +527,14 @@ public class BroadcastSkipPolicy {
|
||||
// Check that the receiver does *not* belong to any of the excluded packages
|
||||
if (r.excludedPackages != null && r.excludedPackages.length > 0) {
|
||||
if (ArrayUtils.contains(r.excludedPackages, filter.packageName)) {
|
||||
Slog.w(TAG, "Skipping delivery of excluded package "
|
||||
return "Skipping delivery of excluded package "
|
||||
+ r.intent.toString()
|
||||
+ " to " + filter.receiverList.app
|
||||
+ " (pid=" + filter.receiverList.pid
|
||||
+ ", uid=" + filter.receiverList.uid + ")"
|
||||
+ " excludes package " + filter.packageName
|
||||
+ " due to sender " + r.callerPackage
|
||||
+ " (uid " + r.callingUid + ")");
|
||||
return true;
|
||||
+ " (uid " + r.callingUid + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -546,15 +544,14 @@ public class BroadcastSkipPolicy {
|
||||
filter.receiverList.uid, filter.packageName, filter.featureId,
|
||||
"Broadcast delivered to registered receiver " + filter.receiverId)
|
||||
!= AppOpsManager.MODE_ALLOWED) {
|
||||
Slog.w(TAG, "Appop Denial: receiving "
|
||||
return "Appop Denial: receiving "
|
||||
+ r.intent.toString()
|
||||
+ " to " + filter.receiverList.app
|
||||
+ " (pid=" + filter.receiverList.pid
|
||||
+ ", uid=" + filter.receiverList.uid + ")"
|
||||
+ " requires appop " + AppOpsManager.opToName(r.appOp)
|
||||
+ " due to sender " + r.callerPackage
|
||||
+ " (uid " + r.callingUid + ")");
|
||||
return true;
|
||||
+ " (uid " + r.callingUid + ")";
|
||||
}
|
||||
|
||||
// Ensure that broadcasts are only sent to other apps if they are explicitly marked as
|
||||
@@ -562,15 +559,14 @@ public class BroadcastSkipPolicy {
|
||||
if (!filter.exported && checkComponentPermission(null, r.callingPid,
|
||||
r.callingUid, filter.receiverList.uid, filter.exported)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
Slog.w(TAG, "Exported Denial: sending "
|
||||
return "Exported Denial: sending "
|
||||
+ r.intent.toString()
|
||||
+ ", action: " + r.intent.getAction()
|
||||
+ " from " + r.callerPackage
|
||||
+ " (uid=" + r.callingUid + ")"
|
||||
+ " due to receiver " + filter.receiverList.app
|
||||
+ " (uid " + filter.receiverList.uid + ")"
|
||||
+ " not specifying RECEIVER_EXPORTED");
|
||||
return true;
|
||||
+ " not specifying RECEIVER_EXPORTED";
|
||||
}
|
||||
|
||||
// If permissions need a review before any of the app components can run, we drop
|
||||
@@ -579,10 +575,10 @@ public class BroadcastSkipPolicy {
|
||||
// broadcast.
|
||||
if (!requestStartTargetPermissionsReviewIfNeededLocked(r, filter.packageName,
|
||||
filter.owningUserId)) {
|
||||
return true;
|
||||
return "Skipping delivery to " + filter.packageName + " due to permissions review";
|
||||
}
|
||||
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String broadcastDescription(BroadcastRecord r, ComponentName component) {
|
||||
|
||||
@@ -280,13 +280,13 @@ public class BroadcastQueueTest {
|
||||
constants.TIMEOUT = 100;
|
||||
constants.ALLOW_BG_ACTIVITY_START_TIMEOUT = 0;
|
||||
final BroadcastSkipPolicy emptySkipPolicy = new BroadcastSkipPolicy(mAms) {
|
||||
public boolean shouldSkip(BroadcastRecord r, ResolveInfo info) {
|
||||
public boolean shouldSkip(BroadcastRecord r, Object o) {
|
||||
// Ignored
|
||||
return false;
|
||||
}
|
||||
public boolean shouldSkip(BroadcastRecord r, BroadcastFilter filter) {
|
||||
public String shouldSkipMessage(BroadcastRecord r, Object o) {
|
||||
// Ignored
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
};
|
||||
final BroadcastHistory emptyHistory = new BroadcastHistory(constants) {
|
||||
|
||||
Reference in New Issue
Block a user