diff options
| -rw-r--r-- | core/java/android/content/Intent.java | 94 | ||||
| -rw-r--r-- | core/java/android/os/Bundle.java | 9 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/BroadcastQueue.java | 22 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/BroadcastRecord.java | 49 |
4 files changed, 138 insertions, 36 deletions
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index f70215b46a5e..daeb987f5f2a 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -5587,6 +5587,16 @@ public class Intent implements Parcelable, Cloneable { // --------------------------------------------------------------------- + private static final int COPY_MODE_ALL = 0; + private static final int COPY_MODE_FILTER = 1; + private static final int COPY_MODE_HISTORY = 2; + + /** @hide */ + @IntDef(value = {COPY_MODE_ALL, COPY_MODE_FILTER, COPY_MODE_HISTORY}) + @Retention(RetentionPolicy.SOURCE) + public @interface CopyMode {} + + /** * Create an empty intent. */ @@ -5597,28 +5607,46 @@ public class Intent implements Parcelable, Cloneable { * Copy constructor. */ public Intent(Intent o) { + this(o, COPY_MODE_ALL); + } + + private Intent(Intent o, @CopyMode int copyMode) { this.mAction = o.mAction; this.mData = o.mData; this.mType = o.mType; this.mPackage = o.mPackage; this.mComponent = o.mComponent; - this.mFlags = o.mFlags; - this.mContentUserHint = o.mContentUserHint; - this.mLaunchToken = o.mLaunchToken; + if (o.mCategories != null) { - this.mCategories = new ArraySet<String>(o.mCategories); - } - if (o.mExtras != null) { - this.mExtras = new Bundle(o.mExtras); - } - if (o.mSourceBounds != null) { - this.mSourceBounds = new Rect(o.mSourceBounds); - } - if (o.mSelector != null) { - this.mSelector = new Intent(o.mSelector); + this.mCategories = new ArraySet<>(o.mCategories); } - if (o.mClipData != null) { - this.mClipData = new ClipData(o.mClipData); + + if (copyMode != COPY_MODE_FILTER) { + this.mFlags = o.mFlags; + this.mContentUserHint = o.mContentUserHint; + this.mLaunchToken = o.mLaunchToken; + if (o.mSourceBounds != null) { + this.mSourceBounds = new Rect(o.mSourceBounds); + } + if (o.mSelector != null) { + this.mSelector = new Intent(o.mSelector); + } + + if (copyMode != COPY_MODE_HISTORY) { + if (o.mExtras != null) { + this.mExtras = new Bundle(o.mExtras); + } + if (o.mClipData != null) { + this.mClipData = new ClipData(o.mClipData); + } + } else { + if (o.mExtras != null && !o.mExtras.maybeIsEmpty()) { + this.mExtras = Bundle.STRIPPED; + } + + // Also set "stripped" clip data when we ever log mClipData in the (broadcast) + // history. + } } } @@ -5627,23 +5655,12 @@ public class Intent implements Parcelable, Cloneable { return new Intent(this); } - private Intent(Intent o, boolean all) { - this.mAction = o.mAction; - this.mData = o.mData; - this.mType = o.mType; - this.mPackage = o.mPackage; - this.mComponent = o.mComponent; - if (o.mCategories != null) { - this.mCategories = new ArraySet<String>(o.mCategories); - } - } - /** * Make a clone of only the parts of the Intent that are relevant for * filter matching: the action, data, type, component, and categories. */ public @NonNull Intent cloneFilter() { - return new Intent(this, false); + return new Intent(this, COPY_MODE_FILTER); } /** @@ -7395,6 +7412,29 @@ public class Intent implements Parcelable, Cloneable { } /** + * @return Whether {@link #maybeStripForHistory} will return an lightened intent or + * return itself as-is. + * @hide + */ + public boolean canStripForHistory() { + return ((mExtras != null) && mExtras.isParcelled()) || (mClipData != null); + } + + /** + * Call it when the system needs to keep an intent for logging purposes to remove fields + * that are not needed for logging. + * @hide + */ + public Intent maybeStripForHistory() { + // TODO Scan and remove possibly heavy instances like Bitmaps from unparcelled extras? + + if (!canStripForHistory()) { + return this; + } + return new Intent(this, COPY_MODE_HISTORY); + } + + /** * Retrieve any special flags associated with this intent. You will * normally just set them with {@link #setFlags} and let the system * take the appropriate action with them. diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java index ec01364b63b4..51f96eed822e 100644 --- a/core/java/android/os/Bundle.java +++ b/core/java/android/os/Bundle.java @@ -38,9 +38,18 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { public static final Bundle EMPTY; + /** + * Special extras used to denote extras have been stripped off. + * @hide + */ + public static final Bundle STRIPPED; + static { EMPTY = new Bundle(); EMPTY.mMap = ArrayMap.EMPTY; + + STRIPPED = new Bundle(); + STRIPPED.putInt("STRIPPED", 1); } /** diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 064ca58dee96..739497b771aa 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -1498,25 +1498,29 @@ public final class BroadcastQueue { else return x; } - private final void addBroadcastToHistoryLocked(BroadcastRecord r) { - if (r.callingUid < 0) { + private final void addBroadcastToHistoryLocked(BroadcastRecord original) { + if (original.callingUid < 0) { // This was from a registerReceiver() call; ignore it. return; } - r.finishTime = SystemClock.uptimeMillis(); + original.finishTime = SystemClock.uptimeMillis(); if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) { Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, - createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_DELIVERED), - System.identityHashCode(r)); + createBroadcastTraceTitle(original, BroadcastRecord.DELIVERY_DELIVERED), + System.identityHashCode(original)); } - mBroadcastHistory[mHistoryNext] = r; + // Note sometimes (only for sticky broadcasts?) we reuse BroadcastRecords, + // So don't change the incoming record directly. + final BroadcastRecord historyRecord = original.maybeStripForHistory(); + + mBroadcastHistory[mHistoryNext] = historyRecord; mHistoryNext = ringAdvance(mHistoryNext, 1, MAX_BROADCAST_HISTORY); - mBroadcastSummaryHistory[mSummaryHistoryNext] = r.intent; - mSummaryHistoryEnqueueTime[mSummaryHistoryNext] = r.enqueueClockTime; - mSummaryHistoryDispatchTime[mSummaryHistoryNext] = r.dispatchClockTime; + mBroadcastSummaryHistory[mSummaryHistoryNext] = historyRecord.intent; + mSummaryHistoryEnqueueTime[mSummaryHistoryNext] = historyRecord.enqueueClockTime; + mSummaryHistoryDispatchTime[mSummaryHistoryNext] = historyRecord.dispatchClockTime; mSummaryHistoryFinishTime[mSummaryHistoryNext] = System.currentTimeMillis(); mSummaryHistoryNext = ringAdvance(mSummaryHistoryNext, 1, MAX_BROADCAST_SUMMARY_HISTORY); } diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java index 7764be794c19..6bc0744fe9a4 100644 --- a/services/core/java/com/android/server/am/BroadcastRecord.java +++ b/services/core/java/com/android/server/am/BroadcastRecord.java @@ -248,6 +248,55 @@ final class BroadcastRecord extends Binder { state = IDLE; } + /** + * Copy constructor which takes a different intent. + * Only used by {@link #maybeStripForHistory}. + */ + private BroadcastRecord(BroadcastRecord from, Intent newIntent) { + intent = newIntent; + targetComp = newIntent.getComponent(); + + callerApp = from.callerApp; + callerPackage = from.callerPackage; + callingPid = from.callingPid; + callingUid = from.callingUid; + callerInstantApp = from.callerInstantApp; + ordered = from.ordered; + sticky = from.sticky; + initialSticky = from.initialSticky; + userId = from.userId; + resolvedType = from.resolvedType; + requiredPermissions = from.requiredPermissions; + appOp = from.appOp; + options = from.options; + receivers = from.receivers; + delivery = from.delivery; + resultTo = from.resultTo; + enqueueClockTime = from.enqueueClockTime; + dispatchTime = from.dispatchTime; + dispatchClockTime = from.dispatchClockTime; + receiverTime = from.receiverTime; + finishTime = from.finishTime; + resultCode = from.resultCode; + resultData = from.resultData; + resultExtras = from.resultExtras; + resultAbort = from.resultAbort; + nextReceiver = from.nextReceiver; + receiver = from.receiver; + state = from.state; + anrCount = from.anrCount; + manifestCount = from.manifestCount; + manifestSkipCount = from.manifestSkipCount; + queue = from.queue; + } + + public BroadcastRecord maybeStripForHistory() { + if (!intent.canStripForHistory()) { + return this; + } + return new BroadcastRecord(this, intent.maybeStripForHistory()); + } + boolean cleanupDisabledPackageReceiversLocked( String packageName, Set<String> filterByClasses, int userId, boolean doit) { if ((userId != UserHandle.USER_ALL && this.userId != userId) || receivers == null) { |