From 2781d0b2d2c1a8f4df792e6ffdeae9ddfabbfbcb Mon Sep 17 00:00:00 2001 From: Mike Ma Date: Wed, 12 Feb 2020 13:07:47 -0800 Subject: [PATCH] Implement dumpsys bluetooth_manager --proto Add BluetoothManagerServiceDumpProto for protobuf dumpsys of bluetooth manager service. Primarily used by incident service to capture an incident report proto. Command to invoke (any of the following after lunch and env setup): $ adb shell dumpsys bluetooth_manager --proto $ adb shell incident 3050 $ incident_report 3050 Bug: 146085372 Test: Execute the above commands and compare the output against normal dumpsys Change-Id: I7ccef334ffeae02316db3afff929998b544972b1 --- core/proto/android/os/incident.proto | 6 + .../server/bluetooth_manager_service.proto | 49 +++++++ .../server/BluetoothManagerService.java | 129 +++++++++++------- 3 files changed, 137 insertions(+), 47 deletions(-) create mode 100644 core/proto/android/server/bluetooth_manager_service.proto diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto index bf4cdee72b2dc..7491f8231b132 100644 --- a/core/proto/android/os/incident.proto +++ b/core/proto/android/os/incident.proto @@ -34,6 +34,7 @@ import "frameworks/base/core/proto/android/os/system_properties.proto"; import "frameworks/base/core/proto/android/providers/settings.proto"; import "frameworks/base/core/proto/android/server/activitymanagerservice.proto"; import "frameworks/base/core/proto/android/server/alarmmanagerservice.proto"; +import "frameworks/base/core/proto/android/server/bluetooth_manager_service.proto"; import "frameworks/base/core/proto/android/server/fingerprint.proto"; import "frameworks/base/core/proto/android/server/jobscheduler.proto"; import "frameworks/base/core/proto/android/server/location/context_hub.proto"; @@ -488,6 +489,11 @@ message IncidentProto { (section).args = "connmetrics --proto" ]; + optional com.android.server.BluetoothManagerServiceDumpProto bluetooth_manager = 3050 [ + (section).type = SECTION_DUMPSYS, + (section).args = "bluetooth_manager --proto" + ]; + optional com.android.server.location.ContextHubServiceProto context_hub = 3051 [ (section).type = SECTION_DUMPSYS, (section).args = "contexthub --proto" diff --git a/core/proto/android/server/bluetooth_manager_service.proto b/core/proto/android/server/bluetooth_manager_service.proto new file mode 100644 index 0000000000000..998413f05ebe5 --- /dev/null +++ b/core/proto/android/server/bluetooth_manager_service.proto @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2020 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 = "proto2"; +package com.android.server; + +import "frameworks/base/core/proto/android/bluetooth/enums.proto"; +import "frameworks/base/core/proto/android/privacy.proto"; + +option java_multiple_files = true; + +message BluetoothManagerServiceDumpProto { + option (.android.msg_privacy).dest = DEST_AUTOMATIC; + + message ActiveLog { + option (.android.msg_privacy).dest = DEST_AUTOMATIC; + optional int64 timestamp_ms = 1; + optional bool enable = 2; + optional string package_name = 3; + optional .android.bluetooth.EnableDisableReasonEnum reason = 4; + } + + optional bool enabled = 1; + optional int32 state = 2; + optional string state_name = 3; + optional string address = 4 [(.android.privacy).dest = DEST_EXPLICIT]; + optional string name = 5 [(.android.privacy).dest = DEST_EXPLICIT]; + optional int64 last_enabled_time_ms = 6; + optional int64 curr_timestamp_ms = 7; + repeated ActiveLog active_logs = 8; + optional int32 num_crashes = 9; + optional bool crash_log_maxed = 10; + repeated int64 crash_timestamps_ms = 11; + optional int32 num_ble_apps = 12; + repeated string ble_app_package_names = 13; +} \ No newline at end of file diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 311a494ee570f..a4a42bcaecb11 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -69,6 +69,7 @@ import android.text.TextUtils; import android.util.FeatureFlagUtils; import android.util.Log; import android.util.Slog; +import android.util.proto.ProtoOutputStream; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; @@ -196,6 +197,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { + " due to " + getEnableDisableReasonString(mReason) + " by " + mPackageName; } + void dump(ProtoOutputStream proto) { + proto.write(BluetoothManagerServiceDumpProto.ActiveLog.TIMESTAMP_MS, mTimestamp); + proto.write(BluetoothManagerServiceDumpProto.ActiveLog.ENABLE, mEnable); + proto.write(BluetoothManagerServiceDumpProto.ActiveLog.PACKAGE_NAME, mPackageName); + proto.write(BluetoothManagerServiceDumpProto.ActiveLog.REASON, mReason); + } } private final LinkedList mActiveLogs = new LinkedList<>(); @@ -2408,56 +2415,56 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) { return; } + if ((args.length > 0) && args[0].startsWith("--proto")) { + dumpProto(fd); + return; + } String errorMsg = null; - boolean protoOut = (args.length > 0) && args[0].startsWith("--proto"); + writer.println("Bluetooth Status"); + writer.println(" enabled: " + isEnabled()); + writer.println(" state: " + BluetoothAdapter.nameForState(mState)); + writer.println(" address: " + mAddress); + writer.println(" name: " + mName); + if (mEnable) { + long onDuration = SystemClock.elapsedRealtime() - mLastEnabledTime; + String onDurationString = String.format(Locale.US, "%02d:%02d:%02d.%03d", + (int) (onDuration / (1000 * 60 * 60)), + (int) ((onDuration / (1000 * 60)) % 60), (int) ((onDuration / 1000) % 60), + (int) (onDuration % 1000)); + writer.println(" time since enabled: " + onDurationString); + } - if (!protoOut) { - writer.println("Bluetooth Status"); - writer.println(" enabled: " + isEnabled()); - writer.println(" state: " + BluetoothAdapter.nameForState(mState)); - writer.println(" address: " + mAddress); - writer.println(" name: " + mName); - if (mEnable) { - long onDuration = SystemClock.elapsedRealtime() - mLastEnabledTime; - String onDurationString = String.format(Locale.US, "%02d:%02d:%02d.%03d", - (int) (onDuration / (1000 * 60 * 60)), - (int) ((onDuration / (1000 * 60)) % 60), (int) ((onDuration / 1000) % 60), - (int) (onDuration % 1000)); - writer.println(" time since enabled: " + onDurationString); + if (mActiveLogs.size() == 0) { + writer.println("\nBluetooth never enabled!"); + } else { + writer.println("\nEnable log:"); + for (ActiveLog log : mActiveLogs) { + writer.println(" " + log); } + } - if (mActiveLogs.size() == 0) { - writer.println("\nBluetooth never enabled!"); - } else { - writer.println("\nEnable log:"); - for (ActiveLog log : mActiveLogs) { - writer.println(" " + log); - } - } + writer.println( + "\nBluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s")); + if (mCrashes == CRASH_LOG_MAX_SIZE) { + writer.println("(last " + CRASH_LOG_MAX_SIZE + ")"); + } + for (Long time : mCrashTimestamps) { + writer.println(" " + timeToLog(time)); + } - writer.println( - "\nBluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s")); - if (mCrashes == CRASH_LOG_MAX_SIZE) { - writer.println("(last " + CRASH_LOG_MAX_SIZE + ")"); - } - for (Long time : mCrashTimestamps) { - writer.println(" " + timeToLog(time)); - } + writer.println("\n" + mBleApps.size() + " BLE app" + (mBleApps.size() == 1 ? "" : "s") + + " registered"); + for (ClientDeathRecipient app : mBleApps.values()) { + writer.println(" " + app.getPackageName()); + } - writer.println("\n" + mBleApps.size() + " BLE app" + (mBleApps.size() == 1 ? "" : "s") - + "registered"); - for (ClientDeathRecipient app : mBleApps.values()) { - writer.println(" " + app.getPackageName()); - } - - writer.println(""); - writer.flush(); - if (args.length == 0) { - // Add arg to produce output - args = new String[1]; - args[0] = "--print"; - } + writer.println(""); + writer.flush(); + if (args.length == 0) { + // Add arg to produce output + args = new String[1]; + args[0] = "--print"; } if (mBluetoothBinder == null) { @@ -2470,14 +2477,42 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } if (errorMsg != null) { - // Silently return if we are extracting metrics in Protobuf format - if (protoOut) { - return; - } writer.println(errorMsg); } } + private void dumpProto(FileDescriptor fd) { + final ProtoOutputStream proto = new ProtoOutputStream(fd); + proto.write(BluetoothManagerServiceDumpProto.ENABLED, isEnabled()); + proto.write(BluetoothManagerServiceDumpProto.STATE, mState); + proto.write(BluetoothManagerServiceDumpProto.STATE_NAME, + BluetoothAdapter.nameForState(mState)); + proto.write(BluetoothManagerServiceDumpProto.ADDRESS, mAddress); + proto.write(BluetoothManagerServiceDumpProto.NAME, mName); + if (mEnable) { + proto.write(BluetoothManagerServiceDumpProto.LAST_ENABLED_TIME_MS, mLastEnabledTime); + } + proto.write(BluetoothManagerServiceDumpProto.CURR_TIMESTAMP_MS, + SystemClock.elapsedRealtime()); + for (ActiveLog log : mActiveLogs) { + long token = proto.start(BluetoothManagerServiceDumpProto.ACTIVE_LOGS); + log.dump(proto); + proto.end(token); + } + proto.write(BluetoothManagerServiceDumpProto.NUM_CRASHES, mCrashes); + proto.write(BluetoothManagerServiceDumpProto.CRASH_LOG_MAXED, + mCrashes == CRASH_LOG_MAX_SIZE); + for (Long time : mCrashTimestamps) { + proto.write(BluetoothManagerServiceDumpProto.CRASH_TIMESTAMPS_MS, time); + } + proto.write(BluetoothManagerServiceDumpProto.NUM_BLE_APPS, mBleApps.size()); + for (ClientDeathRecipient app : mBleApps.values()) { + proto.write(BluetoothManagerServiceDumpProto.BLE_APP_PACKAGE_NAMES, + app.getPackageName()); + } + proto.flush(); + } + private static String getEnableDisableReasonString(int reason) { switch (reason) { case BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST: