/****************************************************************************** * * Copyright (C) 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 #include #include namespace system_bt_osi { // 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; }; 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); /* * Writes the metrics, in base64 protobuf format, into the descriptor FD * If CLEAR is true, metrics events are cleared afterwards. */ void WriteBase64(int fd, bool clear); void WriteBase64String(std::string* serialized, bool clear); void WriteString(std::string* serialized, bool clear); /* * 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 const pimpl_; }; }