diff options
author | Yi Jin <jinyithu@google.com> | 2017-09-28 15:48:38 -0700 |
---|---|---|
committer | Yi Jin <jinyithu@google.com> | 2017-10-11 18:35:14 -0700 |
commit | 129fc6ce194659eed25fc37bb382eed61a14b7a7 (patch) | |
tree | 982680ebf4354686643fff12939cca7eab6afeb0 | |
parent | bc8e230ceb2666e5302cf878b1dc51e005b05f99 (diff) |
Implement Activity Manager Broadcasts dump protos
Bug: 66729158
Test: Manually build and flash the system.img and test "activity --proto
broadcasts"
Change-Id: I3cb7474c4a3ab092f38ed6a121b4d034cadfc402
17 files changed, 598 insertions, 33 deletions
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index c9ad9519824d..e47de752ec70 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -53,6 +53,7 @@ import android.provider.OpenableColumns; import android.util.ArraySet; import android.util.AttributeSet; import android.util.Log; +import android.util.proto.ProtoOutputStream; import com.android.internal.util.XmlUtils; @@ -9371,6 +9372,57 @@ public class Intent implements Parcelable, Cloneable { } } + /** @hide */ + public void writeToProto(ProtoOutputStream proto, long fieldId, boolean secure, boolean comp, + boolean extras, boolean clip) { + long token = proto.start(fieldId); + if (mAction != null) { + proto.write(IntentProto.ACTION, mAction); + } + if (mCategories != null) { + for (String category : mCategories) { + proto.write(IntentProto.CATEGORIES, category); + } + } + if (mData != null) { + proto.write(IntentProto.DATA, secure ? mData.toSafeString() : mData.toString()); + } + if (mType != null) { + proto.write(IntentProto.TYPE, mType); + } + if (mFlags != 0) { + proto.write(IntentProto.FLAG, "0x" + Integer.toHexString(mFlags)); + } + if (mPackage != null) { + proto.write(IntentProto.PACKAGE, mPackage); + } + if (comp && mComponent != null) { + proto.write(IntentProto.COMPONENT, mComponent.flattenToShortString()); + } + if (mSourceBounds != null) { + proto.write(IntentProto.SOURCE_BOUNDS, mSourceBounds.toShortString()); + } + if (mClipData != null) { + StringBuilder b = new StringBuilder(); + if (clip) { + mClipData.toShortString(b); + } else { + mClipData.toShortStringShortItems(b, false); + } + proto.write(IntentProto.CLIP_DATA, b.toString()); + } + if (extras && mExtras != null) { + proto.write(IntentProto.EXTRAS, mExtras.toShortString()); + } + if (mContentUserHint != 0) { + proto.write(IntentProto.CONTENT_USER_HINT, mContentUserHint); + } + if (mSelector != null) { + proto.write(IntentProto.SELECTOR, mSelector.toShortString(secure, comp, extras, clip)); + } + proto.end(token); + } + /** * Call {@link #toUri} with 0 flags. * @deprecated Use {@link #toUri} instead. diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java index c9bce530be3e..a957aed8b806 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -26,6 +26,7 @@ import android.text.TextUtils; import android.util.AndroidException; import android.util.Log; import android.util.Printer; +import android.util.proto.ProtoOutputStream; import com.android.internal.util.XmlUtils; @@ -918,6 +919,15 @@ public class IntentFilter implements Parcelable { dest.writeInt(mPort); } + void writeToProto(ProtoOutputStream proto, long fieldId) { + long token = proto.start(fieldId); + // The original host information is already contained in host and wild, no output now. + proto.write(AuthorityEntryProto.HOST, mHost); + proto.write(AuthorityEntryProto.WILD, mWild); + proto.write(AuthorityEntryProto.PORT, mPort); + proto.end(token); + } + public String getHost() { return mOrigHost; } @@ -1739,6 +1749,59 @@ public class IntentFilter implements Parcelable { } } + /** @hide */ + public void writeToProto(ProtoOutputStream proto, long fieldId) { + long token = proto.start(fieldId); + if (mActions.size() > 0) { + Iterator<String> it = mActions.iterator(); + while (it.hasNext()) { + proto.write(IntentFilterProto.ACTIONS, it.next()); + } + } + if (mCategories != null) { + Iterator<String> it = mCategories.iterator(); + while (it.hasNext()) { + proto.write(IntentFilterProto.CATEGORIES, it.next()); + } + } + if (mDataSchemes != null) { + Iterator<String> it = mDataSchemes.iterator(); + while (it.hasNext()) { + proto.write(IntentFilterProto.DATA_SCHEMES, it.next()); + } + } + if (mDataSchemeSpecificParts != null) { + Iterator<PatternMatcher> it = mDataSchemeSpecificParts.iterator(); + while (it.hasNext()) { + it.next().writeToProto(proto, IntentFilterProto.DATA_SCHEME_SPECS); + } + } + if (mDataAuthorities != null) { + Iterator<AuthorityEntry> it = mDataAuthorities.iterator(); + while (it.hasNext()) { + it.next().writeToProto(proto, IntentFilterProto.DATA_AUTHORITIES); + } + } + if (mDataPaths != null) { + Iterator<PatternMatcher> it = mDataPaths.iterator(); + while (it.hasNext()) { + it.next().writeToProto(proto, IntentFilterProto.DATA_PATHS); + } + } + if (mDataTypes != null) { + Iterator<String> it = mDataTypes.iterator(); + while (it.hasNext()) { + proto.write(IntentFilterProto.DATA_TYPES, it.next()); + } + } + if (mPriority != 0 || mHasPartialTypes) { + proto.write(IntentFilterProto.PRIORITY, mPriority); + proto.write(IntentFilterProto.HAS_PARTIAL_TYPES, mHasPartialTypes); + } + proto.write(IntentFilterProto.GET_AUTO_VERIFY, getAutoVerify()); + proto.end(token); + } + public void dump(Printer du, String prefix) { StringBuilder sb = new StringBuilder(256); if (mActions.size() > 0) { diff --git a/core/java/android/os/PatternMatcher.java b/core/java/android/os/PatternMatcher.java index 1f3a1e68c9de..76b214263f22 100644 --- a/core/java/android/os/PatternMatcher.java +++ b/core/java/android/os/PatternMatcher.java @@ -16,7 +16,7 @@ package android.os; -import android.util.Log; +import android.util.proto.ProtoOutputStream; import java.util.Arrays; @@ -131,7 +131,17 @@ public class PatternMatcher implements Parcelable { } return "PatternMatcher{" + type + mPattern + "}"; } - + + /** @hide */ + public void writeToProto(ProtoOutputStream proto, long fieldId) { + long token = proto.start(fieldId); + proto.write(PatternMatcherProto.PATTERN, mPattern); + proto.write(PatternMatcherProto.TYPE, mType); + // PatternMatcherProto.PARSED_PATTERN is too much to dump, but the field is reserved to + // match the current data structure. + proto.end(token); + } + public int describeContents() { return 0; } @@ -141,7 +151,7 @@ public class PatternMatcher implements Parcelable { dest.writeInt(mType); dest.writeIntArray(mParsedPattern); } - + public PatternMatcher(Parcel src) { mPattern = src.readString(); mType = src.readInt(); diff --git a/core/proto/android/content/intent.proto b/core/proto/android/content/intent.proto new file mode 100644 index 000000000000..f2927a7a3f6e --- /dev/null +++ b/core/proto/android/content/intent.proto @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; + +option java_package = "android.content"; +option java_multiple_files = true; + +import "frameworks/base/core/proto/android/os/patternmatcher.proto"; + +package android.content; + +// Next Tag: 13 +message IntentProto { + string action = 1; + repeated string categories = 2; + string data = 3; + string type = 4; + string flag = 5; + string package = 6; + string component = 7; + string source_bounds = 8; + string clip_data = 9; + string extras = 10; + int32 content_user_hint = 11; + string selector = 12; +} + +// Next Tag: 11 +message IntentFilterProto { + repeated string actions = 1; + repeated string categories = 2; + repeated string data_schemes = 3; + repeated android.os.PatternMatcherProto data_scheme_specs = 4; + repeated AuthorityEntryProto data_authorities = 5; + repeated android.os.PatternMatcherProto data_paths = 6; + repeated string data_types = 7; + int32 priority = 8; + bool has_partial_types = 9; + bool get_auto_verify = 10; +} + +message AuthorityEntryProto { + string host = 1; + bool wild = 2; + int32 port = 3; +} diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto index b3a606f3851e..884d74046e0f 100644 --- a/core/proto/android/os/incident.proto +++ b/core/proto/android/os/incident.proto @@ -32,6 +32,7 @@ import "frameworks/base/core/proto/android/service/package.proto"; import "frameworks/base/core/proto/android/service/power.proto"; import "frameworks/base/core/proto/android/service/print.proto"; import "frameworks/base/core/proto/android/service/procstats.proto"; +import "frameworks/base/core/proto/android/server/activitymanagerservice.proto"; import "frameworks/base/core/proto/android/providers/settings.proto"; import "frameworks/base/core/proto/android/os/incidentheader.proto"; import "frameworks/base/core/proto/android/os/kernelwake.proto"; @@ -108,4 +109,17 @@ message IncidentProto { (section).type = SECTION_DUMPSYS, (section).args = "procstats --proto" ]; + + com.android.server.am.proto.ActivityStackSupervisorProto activities = 3012 [ + (section).type = SECTION_DUMPSYS, + (section).args = "activity --proto activities" + ]; + + com.android.server.am.proto.BroadcastProto broadcasts = 3013 [ + (section).type = SECTION_DUMPSYS, + (section).args = "activity --proto broadcasts" + ]; + + com.android.server.am.proto.ServiceProto amservices = 3014; + com.android.server.am.proto.ProcessProto amprocesses = 3015; } diff --git a/core/proto/android/os/patternmatcher.proto b/core/proto/android/os/patternmatcher.proto new file mode 100644 index 000000000000..cd6824532a10 --- /dev/null +++ b/core/proto/android/os/patternmatcher.proto @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; + +option java_multiple_files = true; + +package android.os; + +message PatternMatcherProto { + string pattern = 1; + + enum Type { + TYPE_LITERAL = 0; + TYPE_PREFIX = 1; + TYPE_SIMPLE_GLOB = 2; + TYPE_ADVANCED_GLOB = 3; + } + Type type = 2; + + // This data is too much for dump + // repeated int32 parsed_pattern = 3; +} diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto index d5ecacc8f72c..fe5e3f10ad34 100644 --- a/core/proto/android/server/activitymanagerservice.proto +++ b/core/proto/android/server/activitymanagerservice.proto @@ -16,8 +16,11 @@ syntax = "proto3"; +import "frameworks/base/core/proto/android/content/intent.proto"; +import "frameworks/base/core/proto/android/server/intentresolver.proto"; import "frameworks/base/core/proto/android/server/windowmanagerservice.proto"; import "frameworks/base/core/proto/android/graphics/rect.proto"; +import "frameworks/base/core/proto/android/os/looper.proto"; package com.android.server.am.proto; @@ -25,6 +28,12 @@ option java_multiple_files = true; message ActivityManagerServiceProto { ActivityStackSupervisorProto activities = 1; + + BroadcastProto broadcasts = 2; + + ServiceProto services = 3; + + ProcessProto processes = 4; } message ActivityStackSupervisorProto { @@ -81,4 +90,86 @@ message ActivityRecordProto { message KeyguardControllerProto { bool keyguard_showing = 1; bool keyguard_occluded = 2; -}
\ No newline at end of file +} + +message BroadcastProto { + repeated ReceiverListProto receiver_list = 1; + + .com.android.server.IntentResolverProto receiver_resolver = 2; + + repeated BroadcastQueueProto broadcast_queue = 3; + + repeated StickyBroadcastProto sticky_broadcasts = 4; + + message MainHandler { + string handler = 1; + .android.os.LooperProto looper = 2; + } + MainHandler handler = 5; +} + +message ReceiverListProto { + ProcessRecordProto app = 1; + int32 pid = 2; + int32 uid = 3; + int32 user = 4; + BroadcastRecordProto current = 5; + bool linked_to_death = 6; + repeated BroadcastFilterProto filters = 7; + string hex_hash = 8; // this hash is used to find the object in IntentResolver +} + +message ProcessRecordProto { + int32 pid = 1; + string process_name = 2; + int32 uid = 3; + int32 user_id = 4; + int32 app_id = 5; + int32 isolated_app_id = 6; +} + +message BroadcastRecordProto { + int32 user_id = 1; + string intent_action = 2; +} + +message BroadcastFilterProto { + .android.content.IntentFilterProto intent_filter = 1; + string required_permission = 2; + string hex_hash = 3; // used to find the object in IntentResolver + int32 owning_user_id = 4; +} + +message BroadcastQueueProto { + string queue_name = 1; + repeated BroadcastRecordProto parallel_broadcasts = 2; + repeated BroadcastRecordProto ordered_broadcasts = 3; + BroadcastRecordProto pending_broadcast = 4; + repeated BroadcastRecordProto historical_broadcasts = 5; + + message BroadcastSummary { + .android.content.IntentProto intent = 1; + int64 enqueue_clock_time_ms = 2; + int64 dispatch_clock_time_ms = 3; + int64 finish_clock_time_ms = 4; + } + repeated BroadcastSummary historical_broadcasts_summary = 6; +} + +message StickyBroadcastProto { + int32 user = 1; + + message StickyAction { + string name = 1; + repeated .android.content.IntentProto intents = 2; + } + repeated StickyAction actions = 2; +} + +message ServiceProto { + // TODO: "dumpsys activity --proto services" +} + +message ProcessProto { + // TODO: "dumpsys activity --proto processes" +} diff --git a/core/proto/android/server/intentresolver.proto b/core/proto/android/server/intentresolver.proto new file mode 100644 index 000000000000..62ec2ea5ee90 --- /dev/null +++ b/core/proto/android/server/intentresolver.proto @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; + +option java_multiple_files = true; + +package com.android.server; + +message IntentResolverProto { + + message ArrayMapEntry { + string key = 1; + repeated string values = 2; + } + + repeated ArrayMapEntry full_mime_types = 1; + repeated ArrayMapEntry base_mime_types = 2; + repeated ArrayMapEntry wild_mime_types = 3; + repeated ArrayMapEntry schemes = 4; + repeated ArrayMapEntry non_data_actions = 5; + repeated ArrayMapEntry mime_typed_actions = 6; +} + diff --git a/services/core/java/com/android/server/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java index 40499c96eb4b..119c9df6c576 100644 --- a/services/core/java/com/android/server/IntentResolver.java +++ b/services/core/java/com/android/server/IntentResolver.java @@ -38,6 +38,8 @@ import android.util.Printer; import android.content.Intent; import android.content.IntentFilter; +import android.util.proto.ProtoOutputStream; + import com.android.internal.util.FastPrintWriter; /** @@ -279,6 +281,31 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> { return printedSomething; } + void writeProtoMap(ProtoOutputStream proto, long fieldId, ArrayMap<String, F[]> map) { + int N = map.size(); + for (int mapi = 0; mapi < N; mapi++) { + long token = proto.start(fieldId); + proto.write(IntentResolverProto.ArrayMapEntry.KEY, map.keyAt(mapi)); + for (F f : map.valueAt(mapi)) { + if (f != null) { + proto.write(IntentResolverProto.ArrayMapEntry.VALUES, f.toString()); + } + } + proto.end(token); + } + } + + public void writeToProto(ProtoOutputStream proto, long fieldId) { + long token = proto.start(fieldId); + writeProtoMap(proto, IntentResolverProto.FULL_MIME_TYPES, mTypeToFilter); + writeProtoMap(proto, IntentResolverProto.BASE_MIME_TYPES, mBaseTypeToFilter); + writeProtoMap(proto, IntentResolverProto.WILD_MIME_TYPES, mWildTypeToFilter); + writeProtoMap(proto, IntentResolverProto.SCHEMES, mSchemeToFilter); + writeProtoMap(proto, IntentResolverProto.NON_DATA_ACTIONS, mActionToFilter); + writeProtoMap(proto, IntentResolverProto.MIME_TYPED_ACTIONS, mTypedActionToFilter); + proto.end(token); + } + public boolean dump(PrintWriter out, String title, String prefix, String packageName, boolean printFilter, boolean collapseDuplicates) { String innerPrefix = prefix + " "; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index ba3b2cdd4c36..294a2629ab93 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -403,6 +403,9 @@ import com.android.server.SystemServiceManager; import com.android.server.ThreadPriorityBooster; import com.android.server.Watchdog; import com.android.server.am.ActivityStack.ActivityState; +import com.android.server.am.proto.ActivityManagerServiceProto; +import com.android.server.am.proto.BroadcastProto; +import com.android.server.am.proto.StickyBroadcastProto; import com.android.server.firewall.IntentFirewall; import com.android.server.job.JobSchedulerInternal; import com.android.server.pm.Installer; @@ -15111,10 +15114,31 @@ public class ActivityManagerService extends IActivityManager.Stub long origId = Binder.clearCallingIdentity(); if (useProto) { - //TODO: Options when dumping proto final ProtoOutputStream proto = new ProtoOutputStream(fd); - synchronized (this) { - writeActivitiesToProtoLocked(proto); + String cmd = opti < args.length ? args[opti] : ""; + opti++; + + if ("activities".equals(cmd) || "a".equals(cmd)) { + // output proto is ActivityStackSupervisorProto + synchronized (this) { + writeActivitiesToProtoLocked(proto); + } + } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) { + // output proto is BroadcastProto + synchronized (this) { + writeBroadcastsToProtoLocked(proto); + } + } else { + // default option, dump everything, output is ActivityManagerServiceProto + synchronized (this) { + long activityToken = proto.start(ActivityManagerServiceProto.ACTIVITIES); + writeActivitiesToProtoLocked(proto); + proto.end(activityToken); + + long broadcastToken = proto.start(ActivityManagerServiceProto.BROADCASTS); + writeBroadcastsToProtoLocked(proto); + proto.end(broadcastToken); + } } proto.flush(); Binder.restoreCallingIdentity(origId); @@ -15465,7 +15489,8 @@ public class ActivityManagerService extends IActivityManager.Stub } private void writeActivitiesToProtoLocked(ProtoOutputStream proto) { - mStackSupervisor.writeToProto(proto, ACTIVITIES); + // The output proto of "activity --proto activities" is ActivityStackSupervisorProto + mStackSupervisor.writeToProto(proto); } private void dumpLastANRLocked(PrintWriter pw) { @@ -16379,6 +16404,40 @@ public class ActivityManagerService extends IActivityManager.Stub } } + void writeBroadcastsToProtoLocked(ProtoOutputStream proto) { + if (mRegisteredReceivers.size() > 0) { + Iterator it = mRegisteredReceivers.values().iterator(); + while (it.hasNext()) { + ReceiverList r = (ReceiverList)it.next(); + r.writeToProto(proto, BroadcastProto.RECEIVER_LIST); + } + } + mReceiverResolver.writeToProto(proto, BroadcastProto.RECEIVER_RESOLVER); + for (BroadcastQueue q : mBroadcastQueues) { + q.writeToProto(proto, BroadcastProto.BROADCAST_QUEUE); + } + for (int user=0; user<mStickyBroadcasts.size(); user++) { + long token = proto.start(BroadcastProto.STICKY_BROADCASTS); + proto.write(StickyBroadcastProto.USER, mStickyBroadcasts.keyAt(user)); + for (Map.Entry<String, ArrayList<Intent>> ent + : mStickyBroadcasts.valueAt(user).entrySet()) { + long actionToken = proto.start(StickyBroadcastProto.ACTIONS); + proto.write(StickyBroadcastProto.StickyAction.NAME, ent.getKey()); + for (Intent intent : ent.getValue()) { + intent.writeToProto(proto, StickyBroadcastProto.StickyAction.INTENTS, + false, true, true, false); + } + proto.end(actionToken); + } + proto.end(token); + } + + long handlerToken = proto.start(BroadcastProto.HANDLER); + proto.write(BroadcastProto.MainHandler.HANDLER, mHandler.toString()); + mHandler.getLooper().writeToProto(proto, BroadcastProto.MainHandler.LOOPER); + proto.end(handlerToken); + } + void dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args, int opti, boolean dumpAll, String dumpPackage) { boolean needSep = false; diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index da2827a6aedc..bd1d5fefb90a 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -3811,8 +3811,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mService.mLockTaskController.dump(pw, prefix); } - public void writeToProto(ProtoOutputStream proto, long fieldId) { - final long token = proto.start(fieldId); + public void writeToProto(ProtoOutputStream proto) { super.writeToProto(proto, CONFIGURATION_CONTAINER); for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) { ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx); @@ -3828,7 +3827,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } else { proto.write(FOCUSED_STACK_ID, INVALID_STACK_ID); } - proto.end(token); } /** diff --git a/services/core/java/com/android/server/am/BroadcastFilter.java b/services/core/java/com/android/server/am/BroadcastFilter.java index f96b06fa798e..7ff227f56ae8 100644 --- a/services/core/java/com/android/server/am/BroadcastFilter.java +++ b/services/core/java/com/android/server/am/BroadcastFilter.java @@ -19,6 +19,9 @@ package com.android.server.am; import android.content.IntentFilter; import android.util.PrintWriterPrinter; import android.util.Printer; +import android.util.proto.ProtoOutputStream; + +import com.android.server.am.proto.BroadcastFilterProto; import java.io.PrintWriter; @@ -44,27 +47,38 @@ final class BroadcastFilter extends IntentFilter { instantApp = _instantApp; visibleToInstantApp = _visibleToInstantApp; } - + + public void writeToProto(ProtoOutputStream proto, long fieldId) { + long token = proto.start(fieldId); + super.writeToProto(proto, BroadcastFilterProto.INTENT_FILTER); + if (requiredPermission != null) { + proto.write(BroadcastFilterProto.REQUIRED_PERMISSION, requiredPermission); + } + proto.write(BroadcastFilterProto.HEX_HASH, Integer.toHexString(System.identityHashCode(this))); + proto.write(BroadcastFilterProto.OWNING_USER_ID, owningUserId); + proto.end(token); + } + public void dump(PrintWriter pw, String prefix) { dumpInReceiverList(pw, new PrintWriterPrinter(pw), prefix); receiverList.dumpLocal(pw, prefix); } - + public void dumpBrief(PrintWriter pw, String prefix) { dumpBroadcastFilterState(pw, prefix); } - + public void dumpInReceiverList(PrintWriter pw, Printer pr, String prefix) { super.dump(pr, prefix); dumpBroadcastFilterState(pw, prefix); } - + void dumpBroadcastFilterState(PrintWriter pw, String prefix) { if (requiredPermission != null) { pw.print(prefix); pw.print("requiredPermission="); pw.println(requiredPermission); } } - + public String toString() { StringBuilder sb = new StringBuilder(); sb.append("BroadcastFilter{"); diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index d83545491d2d..c62cc38b716f 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -51,9 +51,12 @@ import android.os.UserHandle; import android.util.EventLog; import android.util.Slog; import android.util.TimeUtils; +import android.util.proto.ProtoOutputStream; import static com.android.server.am.ActivityManagerDebugConfig.*; +import com.android.server.am.proto.BroadcastQueueProto; + /** * BROADCASTS * @@ -1585,6 +1588,55 @@ public final class BroadcastQueue { && (mPendingBroadcast == null); } + void writeToProto(ProtoOutputStream proto, long fieldId) { + long token = proto.start(fieldId); + proto.write(BroadcastQueueProto.QUEUE_NAME, mQueueName); + int N; + N = mParallelBroadcasts.size(); + for (int i = N - 1; i >= 0; i--) { + mParallelBroadcasts.get(i).writeToProto(proto, BroadcastQueueProto.PARALLEL_BROADCASTS); + } + N = mOrderedBroadcasts.size(); + for (int i = N - 1; i >= 0; i--) { + mOrderedBroadcasts.get(i).writeToProto(proto, BroadcastQueueProto.ORDERED_BROADCASTS); + } + if (mPendingBroadcast != null) { + mPendingBroadcast.writeToProto(proto, BroadcastQueueProto.PENDING_BROADCAST); + } + + int lastIndex = mHistoryNext; + int ringIndex = lastIndex; + do { + // increasing index = more recent entry, and we want to print the most + // recent first and work backwards, so we roll through the ring backwards. + ringIndex = ringAdvance(ringIndex, -1, MAX_BROADCAST_HISTORY); + BroadcastRecord r = mBroadcastHistory[ringIndex]; + if (r != null) { + r.writeToProto(proto, BroadcastQueueProto.HISTORICAL_BROADCASTS); + } + } while (ringIndex != lastIndex); + + lastIndex = ringIndex = mSummaryHistoryNext; + do { + ringIndex = ringAdvance(ringIndex, -1, MAX_BROADCAST_SUMMARY_HISTORY); + Intent intent = mBroadcastSummaryHistory[ringIndex]; + if (intent == null) { + continue; + } + long summaryToken = proto.start(BroadcastQueueProto.HISTORICAL_BROADCASTS_SUMMARY); + intent.writeToProto(proto, BroadcastQueueProto.BroadcastSummary.INTENT, + false, true, true, false); + proto.write(BroadcastQueueProto.BroadcastSummary.ENQUEUE_CLOCK_TIME_MS, + mSummaryHistoryEnqueueTime[ringIndex]); + proto.write(BroadcastQueueProto.BroadcastSummary.DISPATCH_CLOCK_TIME_MS, + mSummaryHistoryDispatchTime[ringIndex]); + proto.write(BroadcastQueueProto.BroadcastSummary.FINISH_CLOCK_TIME_MS, + mSummaryHistoryFinishTime[ringIndex]); + proto.end(summaryToken); + } while (ringIndex != lastIndex); + proto.end(token); + } + final boolean dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args, int opti, boolean dumpAll, String dumpPackage, boolean needSep) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java index 6bc0744fe9a4..5b3b2a8ed3d8 100644 --- a/services/core/java/com/android/server/am/BroadcastRecord.java +++ b/services/core/java/com/android/server/am/BroadcastRecord.java @@ -30,6 +30,9 @@ import android.os.SystemClock; import android.os.UserHandle; import android.util.PrintWriterPrinter; import android.util.TimeUtils; +import android.util.proto.ProtoOutputStream; + +import com.android.server.am.proto.BroadcastRecordProto; import java.io.PrintWriter; import java.text.SimpleDateFormat; @@ -331,9 +334,17 @@ final class BroadcastRecord extends Binder { return didSomething; } + @Override public String toString() { return "BroadcastRecord{" + Integer.toHexString(System.identityHashCode(this)) + " u" + userId + " " + intent.getAction() + "}"; } + + public void writeToProto(ProtoOutputStream proto, long fieldId) { + long token = proto.start(fieldId); + proto.write(BroadcastRecordProto.USER_ID, userId); + proto.write(BroadcastRecordProto.INTENT_ACTION, intent.getAction()); + proto.end(token); + } } diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 0e318d9c502b..e84772318e9b 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -27,6 +27,7 @@ import android.util.Slog; import com.android.internal.app.procstats.ProcessStats; import com.android.internal.app.procstats.ProcessState; import com.android.internal.os.BatteryStatsImpl; +import com.android.server.am.proto.ProcessRecordProto; import android.app.ActivityManager; import android.app.Dialog; @@ -44,6 +45,7 @@ import android.os.Trace; import android.os.UserHandle; import android.util.ArrayMap; import android.util.TimeUtils; +import android.util.proto.ProtoOutputStream; import java.io.PrintWriter; import java.util.ArrayList; @@ -621,6 +623,22 @@ final class ProcessRecord { } } + public void writeToProto(ProtoOutputStream proto, long fieldId) { + long token = proto.start(fieldId); + proto.write(ProcessRecordProto.PID, pid); + proto.write(ProcessRecordProto.PROCESS_NAME, processName); + if (info.uid < Process.FIRST_APPLICATION_UID) { + proto.write(ProcessRecordProto.UID, uid); + } else { + proto.write(ProcessRecordProto.USER_ID, userId); + proto.write(ProcessRecordProto.APP_ID, UserHandle.getAppId(info.uid)); + if (uid != info.uid) { + proto.write(ProcessRecordProto.ISOLATED_APP_ID, UserHandle.getAppId(uid)); + } + } + proto.end(token); + } + public String toShortString() { if (shortStringName != null) { return shortStringName; diff --git a/services/core/java/com/android/server/am/ReceiverList.java b/services/core/java/com/android/server/am/ReceiverList.java index 6ade7361e72d..a98906313485 100644 --- a/services/core/java/com/android/server/am/ReceiverList.java +++ b/services/core/java/com/android/server/am/ReceiverList.java @@ -21,6 +21,8 @@ import android.os.Binder; import android.os.IBinder; import android.util.PrintWriterPrinter; import android.util.Printer; +import android.util.proto.ProtoOutputStream; +import com.android.server.am.proto.ReceiverListProto; import java.io.PrintWriter; import java.util.ArrayList; @@ -41,7 +43,7 @@ final class ReceiverList extends ArrayList<BroadcastFilter> boolean linkedToDeath = false; String stringName; - + ReceiverList(ActivityManagerService _owner, ProcessRecord _app, int _pid, int _uid, int _userId, IIntentReceiver _receiver) { owner = _owner; @@ -59,12 +61,31 @@ final class ReceiverList extends ArrayList<BroadcastFilter> public int hashCode() { return System.identityHashCode(this); } - + public void binderDied() { linkedToDeath = false; owner.unregisterReceiver(receiver); } - + + void writeToProto(ProtoOutputStream proto, long fieldId) { + long token = proto.start(fieldId); + app.writeToProto(proto, ReceiverListProto.APP); + proto.write(ReceiverListProto.PID, pid); + proto.write(ReceiverListProto.UID, uid); + proto.write(ReceiverListProto.USER, userId); + if (curBroadcast != null) { + curBroadcast.writeToProto(proto, ReceiverListProto.CURRENT); + } + proto.write(ReceiverListProto.LINKED_TO_DEATH, linkedToDeath); + final int N = size(); + for (int i=0; i<N; i++) { + BroadcastFilter bf = get(i); + bf.writeToProto(proto, ReceiverListProto.FILTERS); + } + proto.write(ReceiverListProto.HEX_HASH, Integer.toHexString(System.identityHashCode(this))); + proto.end(token); + } + void dumpLocal(PrintWriter pw, String prefix) { pw.print(prefix); pw.print("app="); pw.print(app != null ? app.toShortString() : null); pw.print(" pid="); pw.print(pid); pw.print(" uid="); pw.print(uid); @@ -74,7 +95,7 @@ final class ReceiverList extends ArrayList<BroadcastFilter> pw.print(" linkedToDeath="); pw.println(linkedToDeath); } } - + void dump(PrintWriter pw, String prefix) { Printer pr = new PrintWriterPrinter(pw); dumpLocal(pw, prefix); @@ -89,7 +110,7 @@ final class ReceiverList extends ArrayList<BroadcastFilter> bf.dumpInReceiverList(pw, pr, p2); } } - + public String toString() { if (stringName != null) { return stringName; diff --git a/tools/incident_report/main.cpp b/tools/incident_report/main.cpp index d4ad34010f57..cc252649da96 100644 --- a/tools/incident_report/main.cpp +++ b/tools/incident_report/main.cpp @@ -97,8 +97,8 @@ read_message(CodedInputStream* in, Descriptor const* descriptor, GenericMessage* message->addInt64(fieldId, value64); break; } else { - fprintf(stderr, "bad VARINT: 0x%x (%d) at index %d\n", tag, tag, - in->CurrentPosition()); + fprintf(stderr, "bad VARINT: 0x%x (%d) at index %d of field %s\n", + tag, tag, in->CurrentPosition(), descriptor->name().c_str()); return false; } case WireFormatLite::WIRETYPE_FIXED64: @@ -106,14 +106,14 @@ read_message(CodedInputStream* in, Descriptor const* descriptor, GenericMessage* message->addInt64(fieldId, value64); break; } else { - fprintf(stderr, "bad VARINT: 0x%x (%d) at index %d\n", tag, tag, - in->CurrentPosition()); + fprintf(stderr, "bad VARINT: 0x%x (%d) at index %d of field %s\n", + tag, tag, in->CurrentPosition(), descriptor->name().c_str()); return false; } case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: if (!read_length_delimited(in, fieldId, descriptor, message)) { - fprintf(stderr, "bad LENGTH_DELIMITED: 0x%x (%d) at index %d\n", - tag, tag, in->CurrentPosition()); + fprintf(stderr, "bad LENGTH_DELIMITED: 0x%x (%d) at index %d of field %s\n", + tag, tag, in->CurrentPosition(), descriptor->name().c_str()); return false; } break; @@ -122,13 +122,13 @@ read_message(CodedInputStream* in, Descriptor const* descriptor, GenericMessage* message->addInt32(fieldId, value32); break; } else { - fprintf(stderr, "bad FIXED32: 0x%x (%d) at index %d\n", tag, tag, - in->CurrentPosition()); + fprintf(stderr, "bad FIXED32: 0x%x (%d) at index %d of field %s\n", + tag, tag, in->CurrentPosition(), descriptor->name().c_str()); return false; } default: - fprintf(stderr, "bad tag: 0x%x (%d) at index %d\n", tag, tag, - in->CurrentPosition()); + fprintf(stderr, "bad tag: 0x%x (%d) at index %d of field %s\n", tag, tag, + in->CurrentPosition(), descriptor->name().c_str()); return false; } } @@ -153,7 +153,8 @@ print_value(Out* out, FieldDescriptor const* field, GenericMessage::Node const& out->printf("%f", *(float*)&node.value32); break; default: - out->printf("(unexpected value32 %d (0x%x)", node.value32, node.value32); + out->printf("(unexpected type %d: value32 %d (0x%x)", + type, node.value32, node.value32); break; } break; @@ -194,7 +195,8 @@ print_value(Out* out, FieldDescriptor const* field, GenericMessage::Node const& } break; default: - out->printf("(unexpected value64 %lld (0x%x))", node.value64, node.value64); + out->printf("(unexpected type %d: value64 %lld (0x%x))", + type, node.value64, node.value64); break; } break; |