diff options
| author | 2017-05-31 16:20:21 -0700 | |
|---|---|---|
| committer | 2017-07-21 16:51:16 -0700 | |
| commit | 97f82f28da5a2d3bc6229fee9ce493dc037727b9 (patch) | |
| tree | 8c035e4b2967cb5f244647298776a9c7afd2ac82 | |
| parent | d57fcca82343d276e9d35e86bd7039f19db819a1 (diff) | |
Don't keep parceled extras for history broadcasts.
On dumpsys we do show history broadcast intents with extras, but
if an intent's extras are still parceled, we can't show anything
(but the length) anyway, so let's just remove them, because sometimes
they contain heavy objects such as bitmaps.
Bug: 62144301
Test: manual tests: Boot, add account start apps, insert SIM
Change-Id: Ia64dd46d66fba3098e32c435509f4940ae978710
| -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) { |