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: