You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
505 lines
18 KiB
505 lines
18 KiB
/******************************************************************************
|
|
*
|
|
* Copyright 2016 Google, Inc.
|
|
*
|
|
* 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.
|
|
*
|
|
******************************************************************************/
|
|
|
|
#pragma once
|
|
|
|
#include <bta/include/bta_api.h>
|
|
#include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h>
|
|
#include <frameworks/proto_logging/stats/enums/bluetooth/hci/enums.pb.h>
|
|
#include <stdint.h>
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
namespace bluetooth {
|
|
|
|
namespace common {
|
|
|
|
// Typedefs to hide protobuf definition to the rest of stack
|
|
|
|
typedef enum {
|
|
DEVICE_TYPE_UNKNOWN,
|
|
DEVICE_TYPE_BREDR,
|
|
DEVICE_TYPE_LE,
|
|
DEVICE_TYPE_DUMO,
|
|
} device_type_t;
|
|
|
|
typedef enum {
|
|
WAKE_EVENT_UNKNOWN,
|
|
WAKE_EVENT_ACQUIRED,
|
|
WAKE_EVENT_RELEASED,
|
|
} wake_event_type_t;
|
|
|
|
typedef enum {
|
|
SCAN_TYPE_UNKNOWN,
|
|
SCAN_TECH_TYPE_LE,
|
|
SCAN_TECH_TYPE_BREDR,
|
|
SCAN_TECH_TYPE_BOTH,
|
|
} scan_tech_t;
|
|
|
|
typedef enum {
|
|
CONNECTION_TECHNOLOGY_TYPE_UNKNOWN,
|
|
CONNECTION_TECHNOLOGY_TYPE_LE,
|
|
CONNECTION_TECHNOLOGY_TYPE_BREDR,
|
|
} connection_tech_t;
|
|
|
|
typedef enum {
|
|
DISCONNECT_REASON_UNKNOWN,
|
|
DISCONNECT_REASON_METRICS_DUMP,
|
|
DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS,
|
|
} disconnect_reason_t;
|
|
|
|
/* Values of A2DP metrics that we care about
|
|
*
|
|
* audio_duration_ms : sum of audio duration (in milliseconds).
|
|
* device_class: device class of the paired device.
|
|
* media_timer_min_ms : minimum scheduled time (in milliseconds)
|
|
* of the media timer.
|
|
* media_timer_max_ms: maximum scheduled time (in milliseconds)
|
|
* of the media timer.
|
|
* media_timer_avg_ms: average scheduled time (in milliseconds)
|
|
* of the media timer.
|
|
* buffer_overruns_max_count: TODO - not clear what this is.
|
|
* buffer_overruns_total : number of times the media buffer with
|
|
* audio data has overrun
|
|
* buffer_underruns_average: TODO - not clear what this is.
|
|
* buffer_underruns_count: number of times there was no enough
|
|
* audio data to add to the media buffer.
|
|
* NOTE: Negative values are invalid
|
|
*/
|
|
class A2dpSessionMetrics {
|
|
public:
|
|
A2dpSessionMetrics() {}
|
|
|
|
/*
|
|
* Update the metrics value in the current metrics object using the metrics
|
|
* objects supplied
|
|
*/
|
|
void Update(const A2dpSessionMetrics& metrics);
|
|
|
|
/*
|
|
* Compare whether two metrics objects are equal
|
|
*/
|
|
bool operator==(const A2dpSessionMetrics& rhs) const;
|
|
|
|
/*
|
|
* Initialize all values to -1 which is invalid in order to make a distinction
|
|
* between 0 and invalid values
|
|
*/
|
|
int64_t audio_duration_ms = -1;
|
|
int32_t media_timer_min_ms = -1;
|
|
int32_t media_timer_max_ms = -1;
|
|
int32_t media_timer_avg_ms = -1;
|
|
int64_t total_scheduling_count = -1;
|
|
int32_t buffer_overruns_max_count = -1;
|
|
int32_t buffer_overruns_total = -1;
|
|
float buffer_underruns_average = -1;
|
|
int32_t buffer_underruns_count = -1;
|
|
int64_t codec_index = -1;
|
|
bool is_a2dp_offload = false;
|
|
};
|
|
|
|
class BluetoothMetricsLogger {
|
|
public:
|
|
static BluetoothMetricsLogger* GetInstance() {
|
|
static BluetoothMetricsLogger* instance = new BluetoothMetricsLogger();
|
|
return instance;
|
|
}
|
|
|
|
/*
|
|
* Record a pairing event
|
|
*
|
|
* Parameters:
|
|
* timestamp_ms: Unix epoch time in milliseconds
|
|
* device_class: class of remote device
|
|
* device_type: type of remote device
|
|
* disconnect_reason: HCI reason for pairing disconnection.
|
|
* See: stack/include/hcidefs.h
|
|
*/
|
|
void LogPairEvent(uint32_t disconnect_reason, uint64_t timestamp_ms,
|
|
uint32_t device_class, device_type_t device_type);
|
|
|
|
/*
|
|
* Record a wake event
|
|
*
|
|
* Parameters:
|
|
* timestamp_ms: Unix epoch time in milliseconds
|
|
* type: whether it was acquired or released
|
|
* requestor: if provided is the service requesting the wake lock
|
|
* name: the name of the wake lock held
|
|
*/
|
|
void LogWakeEvent(wake_event_type_t type, const std::string& requestor,
|
|
const std::string& name, uint64_t timestamp_ms);
|
|
|
|
/*
|
|
* Record a scan event
|
|
*
|
|
* Parameters
|
|
* timestamp_ms : Unix epoch time in milliseconds
|
|
* start : true if this is the beginning of the scan
|
|
* initiator: a unique ID identifying the app starting the scan
|
|
* type: whether the scan reports BR/EDR, LE, or both.
|
|
* results: number of results to be reported.
|
|
*/
|
|
void LogScanEvent(bool start, const std::string& initator, scan_tech_t type,
|
|
uint32_t results, uint64_t timestamp_ms);
|
|
|
|
/*
|
|
* Start logging a Bluetooth session
|
|
*
|
|
* A Bluetooth session is defined a a connection between this device and
|
|
* another remote device which may include multiple profiles and protocols
|
|
*
|
|
* Only one Bluetooth session can exist at one time. Calling this method twice
|
|
* without LogBluetoothSessionEnd will result in logging a premature end of
|
|
* current Bluetooth session
|
|
*
|
|
* Parameters:
|
|
* connection_tech_type : type of connection technology
|
|
* timestamp_ms : the timestamp for session start, 0 means now
|
|
*
|
|
*/
|
|
void LogBluetoothSessionStart(connection_tech_t connection_tech_type,
|
|
uint64_t timestamp_ms);
|
|
|
|
/*
|
|
* Stop logging a Bluetooth session and pushes it to the log queue
|
|
*
|
|
* If no Bluetooth session exist, this method exits immediately
|
|
*
|
|
* Parameters:
|
|
* disconnect_reason : A string representation of disconnect reason
|
|
* timestamp_ms : the timestamp of session end, 0 means now
|
|
*
|
|
*/
|
|
void LogBluetoothSessionEnd(disconnect_reason_t disconnect_reason,
|
|
uint64_t timestamp_ms);
|
|
|
|
/*
|
|
* Log information about remote device in a current Bluetooth session
|
|
*
|
|
* If a Bluetooth session does not exist, create one with default parameter
|
|
* and timestamp now
|
|
*
|
|
* Parameters:
|
|
* device_class : device_class defined in btm_api_types.h
|
|
* device_type : type of remote device
|
|
*/
|
|
void LogBluetoothSessionDeviceInfo(uint32_t device_class,
|
|
device_type_t device_type);
|
|
|
|
/*
|
|
* Log A2DP Audio Session Information
|
|
*
|
|
* - Repeated calls to this method will override previous metrics if in the
|
|
* same Bluetooth connection
|
|
* - If a Bluetooth session does not exist, create one with default parameter
|
|
* and timestamp now
|
|
*
|
|
* Parameters:
|
|
* a2dp_session_metrics - pointer to struct holding a2dp stats
|
|
*
|
|
*/
|
|
void LogA2dpSession(const A2dpSessionMetrics& a2dp_session_metrics);
|
|
|
|
/**
|
|
* Log Headset profile RFCOMM connection event
|
|
*
|
|
* @param service_id the BTA service ID for this headset connection
|
|
*/
|
|
void LogHeadsetProfileRfcConnection(tBTA_SERVICE_ID service_id);
|
|
|
|
/*
|
|
* Writes the metrics, in base64 protobuf format, into the descriptor FD,
|
|
* metrics events are always cleared after dump
|
|
*/
|
|
void WriteBase64(int fd);
|
|
void WriteBase64String(std::string* serialized);
|
|
void WriteString(std::string* serialized);
|
|
|
|
/*
|
|
* Reset the metrics logger by cleaning up its staging queues and existing
|
|
* protobuf objects.
|
|
*/
|
|
void Reset();
|
|
|
|
/*
|
|
* Maximum number of log entries for each session or event
|
|
*/
|
|
static const size_t kMaxNumBluetoothSession = 50;
|
|
static const size_t kMaxNumPairEvent = 50;
|
|
static const size_t kMaxNumWakeEvent = 1000;
|
|
static const size_t kMaxNumScanEvent = 50;
|
|
|
|
private:
|
|
BluetoothMetricsLogger();
|
|
|
|
/*
|
|
* When a Bluetooth session is on and the user initiates a metrics dump, we
|
|
* need to be able to upload whatever we have first. This method breaks the
|
|
* ongoing Bluetooth session into two sessions with the previous one labeled
|
|
* as "METRICS_DUMP" for the disconnect reason.
|
|
*/
|
|
void CutoffSession();
|
|
|
|
/*
|
|
* Build the internal metrics object using information gathered
|
|
*/
|
|
void Build();
|
|
|
|
/*
|
|
* Reset objects related to current Bluetooth session
|
|
*/
|
|
void ResetSession();
|
|
|
|
/*
|
|
* Reset the underlining BluetoothLog object
|
|
*/
|
|
void ResetLog();
|
|
|
|
/*
|
|
* PIMPL style implementation to hide internal dependencies
|
|
*/
|
|
struct impl;
|
|
std::unique_ptr<impl> const pimpl_;
|
|
};
|
|
|
|
/**
|
|
* Unknown connection handle for metrics purpose
|
|
*/
|
|
static const uint32_t kUnknownConnectionHandle = 0xFFFF;
|
|
|
|
/**
|
|
* Log link layer connection event
|
|
*
|
|
* @param address Stack wide consistent Bluetooth address of this event,
|
|
* nullptr if unknown
|
|
* @param connection_handle connection handle of this event,
|
|
* {@link kUnknownConnectionHandle} if unknown
|
|
* @param direction direction of this connection
|
|
* @param link_type type of the link
|
|
* @param hci_cmd HCI command opecode associated with this event, if any
|
|
* @param hci_event HCI event code associated with this event, if any
|
|
* @param hci_ble_event HCI BLE event code associated with this event, if any
|
|
* @param cmd_status Command status associated with this event, if any
|
|
* @param reason_code Reason code associated with this event, if any
|
|
*/
|
|
void LogLinkLayerConnectionEvent(const RawAddress* address,
|
|
uint32_t connection_handle,
|
|
android::bluetooth::DirectionEnum direction,
|
|
uint16_t link_type, uint32_t hci_cmd,
|
|
uint16_t hci_event, uint16_t hci_ble_event,
|
|
uint16_t cmd_status, uint16_t reason_code);
|
|
|
|
/**
|
|
* Logs when Bluetooth controller failed to reply with command status within
|
|
* a timeout period after receiving an HCI command from the host
|
|
*
|
|
* @param hci_cmd opcode of HCI command that caused this timeout
|
|
*/
|
|
void LogHciTimeoutEvent(uint32_t hci_cmd);
|
|
|
|
/**
|
|
* Logs when we receive Bluetooth Read Remote Version Information Complete
|
|
* Event from the remote device, as documented by the Bluetooth Core HCI
|
|
* specification
|
|
*
|
|
* Reference: 5.0 Core Specification, Vol 2, Part E, Page 1118
|
|
*
|
|
* @param handle handle of associated ACL connection
|
|
* @param status HCI command status of this event
|
|
* @param version version code from read remote version complete event
|
|
* @param manufacturer_name manufacturer code from read remote version complete
|
|
* event
|
|
* @param subversion subversion code from read remote version complete event
|
|
*/
|
|
void LogRemoteVersionInfo(uint16_t handle, uint8_t status, uint8_t version,
|
|
uint16_t manufacturer_name, uint16_t subversion);
|
|
|
|
/**
|
|
* Log A2DP audio buffer underrun event
|
|
*
|
|
* @param address A2DP device associated with this event
|
|
* @param encoding_interval_millis encoding interval in milliseconds
|
|
* @param num_missing_pcm_bytes number of PCM bytes that cannot be read from
|
|
* the source
|
|
*/
|
|
void LogA2dpAudioUnderrunEvent(const RawAddress& address,
|
|
uint64_t encoding_interval_millis,
|
|
int num_missing_pcm_bytes);
|
|
|
|
/**
|
|
* Log A2DP audio buffer overrun event
|
|
*
|
|
* @param address A2DP device associated with this event
|
|
* @param encoding_interval_millis encoding interval in milliseconds
|
|
* @param num_dropped_buffers number of encoded buffers dropped from Tx queue
|
|
* @param num_dropped_encoded_frames number of encoded frames dropped from Tx
|
|
* queue
|
|
* @param num_dropped_encoded_bytes number of encoded bytes dropped from Tx
|
|
* queue
|
|
*/
|
|
void LogA2dpAudioOverrunEvent(const RawAddress& address,
|
|
uint64_t encoding_interval_millis,
|
|
int num_dropped_buffers,
|
|
int num_dropped_encoded_frames,
|
|
int num_dropped_encoded_bytes);
|
|
|
|
/**
|
|
* Log A2DP playback state changed event
|
|
*
|
|
* @param address A2DP device associated with this event
|
|
* @param playback_state audio playback state
|
|
* @param audio_coding_mode audio codec encoding mode
|
|
*/
|
|
void LogA2dpPlaybackEvent(const RawAddress& address, int playback_state,
|
|
int audio_coding_mode);
|
|
|
|
/**
|
|
* Log read RSSI result
|
|
*
|
|
* @param address device associated with this event
|
|
* @param handle connection handle of this event,
|
|
* {@link kUnknownConnectionHandle} if unknown
|
|
* @param cmd_status command status from read RSSI command
|
|
* @param rssi rssi value in dBm
|
|
*/
|
|
void LogReadRssiResult(const RawAddress& address, uint16_t handle,
|
|
uint32_t cmd_status, int8_t rssi);
|
|
|
|
/**
|
|
* Log failed contact counter report
|
|
*
|
|
* @param address device associated with this event
|
|
* @param handle connection handle of this event,
|
|
* {@link kUnknownConnectionHandle} if unknown
|
|
* @param cmd_status command status from read failed contact counter command
|
|
* @param failed_contact_counter Number of consecutive failed contacts for a
|
|
* connection corresponding to the Handle
|
|
*/
|
|
void LogReadFailedContactCounterResult(const RawAddress& address,
|
|
uint16_t handle, uint32_t cmd_status,
|
|
int32_t failed_contact_counter);
|
|
|
|
/**
|
|
* Log transmit power level for a particular device after read
|
|
*
|
|
* @param address device associated with this event
|
|
* @param handle connection handle of this event,
|
|
* {@link kUnknownConnectionHandle} if unknown
|
|
* @param cmd_status command status from read failed contact counter command
|
|
* @param transmit_power_level transmit power level for connection to this
|
|
* device
|
|
*/
|
|
void LogReadTxPowerLevelResult(const RawAddress& address, uint16_t handle,
|
|
uint32_t cmd_status,
|
|
int32_t transmit_power_level);
|
|
|
|
/**
|
|
* Logs when there is an event related to Bluetooth Security Manager Protocol
|
|
*
|
|
* @param address address of associated device
|
|
* @param smp_cmd SMP command code associated with this event
|
|
* @param direction direction of this SMP command
|
|
* @param smp_fail_reason SMP pairing failure reason code from SMP spec
|
|
*/
|
|
void LogSmpPairingEvent(const RawAddress& address, uint8_t smp_cmd,
|
|
android::bluetooth::DirectionEnum direction,
|
|
uint8_t smp_fail_reason);
|
|
|
|
/**
|
|
* Logs there is an event related Bluetooth classic pairing
|
|
*
|
|
* @param address address of associated device
|
|
* @param handle connection handle of this event,
|
|
* {@link kUnknownConnectionHandle} if unknown
|
|
* @param hci_cmd HCI command associated with this event
|
|
* @param hci_event HCI event associated with this event
|
|
* @param cmd_status Command status associated with this event
|
|
* @param reason_code Reason code associated with this event
|
|
* @param event_value A status value related to this specific event
|
|
*/
|
|
void LogClassicPairingEvent(const RawAddress& address, uint16_t handle, uint32_t hci_cmd, uint16_t hci_event,
|
|
uint16_t cmd_status, uint16_t reason_code, int64_t event_value);
|
|
|
|
/**
|
|
* Logs when certain Bluetooth SDP attributes are discovered
|
|
*
|
|
* @param address address of associated device
|
|
* @param protocol_uuid 16 bit protocol UUID from Bluetooth Assigned Numbers
|
|
* @param attribute_id 16 bit attribute ID from Bluetooth Assigned Numbers
|
|
* @param attribute_size size of this attribute
|
|
* @param attribute_value pointer to the attribute data, must be larger than
|
|
* attribute_size
|
|
*/
|
|
void LogSdpAttribute(const RawAddress& address, uint16_t protocol_uuid,
|
|
uint16_t attribute_id, size_t attribute_size,
|
|
const char* attribute_value);
|
|
|
|
/**
|
|
* Logs when there is a change in Bluetooth socket connection state
|
|
*
|
|
* @param address address of associated device, empty if this is a server port
|
|
* @param port port of this socket connection
|
|
* @param type type of socket
|
|
* @param connection_state socket connection state
|
|
* @param tx_bytes number of bytes transmitted
|
|
* @param rx_bytes number of bytes received
|
|
* @param server_port server port of this socket, if any. When both
|
|
* |server_port| and |port| fields are populated, |port| must be spawned
|
|
* by |server_port|
|
|
* @param socket_role role of this socket, server or connection
|
|
* @param uid socket owner's uid
|
|
*/
|
|
void LogSocketConnectionState(
|
|
const RawAddress& address, int port, int type,
|
|
android::bluetooth::SocketConnectionstateEnum connection_state,
|
|
int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port,
|
|
android::bluetooth::SocketRoleEnum socket_role);
|
|
|
|
/**
|
|
* Logs when a Bluetooth device's manufacturer information is learnt
|
|
*
|
|
* @param address address of associated device
|
|
* @param source_type where is this device info obtained from
|
|
* @param source_name name of the data source, internal or external
|
|
* @param manufacturer name of the manufacturer of this device
|
|
* @param model model of this device
|
|
* @param hardware_version hardware version of this device
|
|
* @param software_version software version of this device
|
|
*/
|
|
void LogManufacturerInfo(const RawAddress& address,
|
|
android::bluetooth::DeviceInfoSrcEnum source_type,
|
|
const std::string& source_name,
|
|
const std::string& manufacturer,
|
|
const std::string& model,
|
|
const std::string& hardware_version,
|
|
const std::string& software_version);
|
|
|
|
/**
|
|
* Logs when received Bluetooth HAL crash reason report.
|
|
*
|
|
* @param address current connected address.
|
|
* @param error_code the crash reason from bluetooth hal
|
|
* @param vendor_error_code the vendor crash reason from bluetooth Firmware
|
|
*/
|
|
void LogBluetoothHalCrashReason(const RawAddress& address, uint32_t error_code,
|
|
uint32_t vendor_error_code);
|
|
} // namespace common
|
|
|
|
} // namespace bluetooth
|