Home | History | Annotate | Download | only in include
      1 /******************************************************************************
      2  *
      3  *  Copyright 2016 Google, Inc.
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 #pragma once
     20 
     21 #include <bta/include/bta_api.h>
     22 #include <stdint.h>
     23 #include <memory>
     24 #include <string>
     25 
     26 namespace system_bt_osi {
     27 
     28 // Typedefs to hide protobuf definition to the rest of stack
     29 
     30 typedef enum {
     31   DEVICE_TYPE_UNKNOWN,
     32   DEVICE_TYPE_BREDR,
     33   DEVICE_TYPE_LE,
     34   DEVICE_TYPE_DUMO,
     35 } device_type_t;
     36 
     37 typedef enum {
     38   WAKE_EVENT_UNKNOWN,
     39   WAKE_EVENT_ACQUIRED,
     40   WAKE_EVENT_RELEASED,
     41 } wake_event_type_t;
     42 
     43 typedef enum {
     44   SCAN_TYPE_UNKNOWN,
     45   SCAN_TECH_TYPE_LE,
     46   SCAN_TECH_TYPE_BREDR,
     47   SCAN_TECH_TYPE_BOTH,
     48 } scan_tech_t;
     49 
     50 typedef enum {
     51   CONNECTION_TECHNOLOGY_TYPE_UNKNOWN,
     52   CONNECTION_TECHNOLOGY_TYPE_LE,
     53   CONNECTION_TECHNOLOGY_TYPE_BREDR,
     54 } connection_tech_t;
     55 
     56 typedef enum {
     57   DISCONNECT_REASON_UNKNOWN,
     58   DISCONNECT_REASON_METRICS_DUMP,
     59   DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS,
     60 } disconnect_reason_t;
     61 
     62 /* Values of A2DP metrics that we care about
     63  *
     64  *    audio_duration_ms : sum of audio duration (in milliseconds).
     65  *    device_class: device class of the paired device.
     66  *    media_timer_min_ms : minimum scheduled time (in milliseconds)
     67  *                         of the media timer.
     68  *    media_timer_max_ms: maximum scheduled time (in milliseconds)
     69  *                        of the media timer.
     70  *    media_timer_avg_ms: average scheduled time (in milliseconds)
     71  *                        of the media timer.
     72  *    buffer_overruns_max_count: TODO - not clear what this is.
     73  *    buffer_overruns_total : number of times the media buffer with
     74  *                            audio data has overrun
     75  *    buffer_underruns_average: TODO - not clear what this is.
     76  *    buffer_underruns_count: number of times there was no enough
     77  *                            audio data to add to the media buffer.
     78  * NOTE: Negative values are invalid
     79 */
     80 class A2dpSessionMetrics {
     81  public:
     82   A2dpSessionMetrics() {}
     83 
     84   /*
     85    * Update the metrics value in the current metrics object using the metrics
     86    * objects supplied
     87    */
     88   void Update(const A2dpSessionMetrics& metrics);
     89 
     90   /*
     91    * Compare whether two metrics objects are equal
     92    */
     93   bool operator==(const A2dpSessionMetrics& rhs) const;
     94 
     95   /*
     96    * Initialize all values to -1 which is invalid in order to make a distinction
     97    * between 0 and invalid values
     98    */
     99   int64_t audio_duration_ms = -1;
    100   int32_t media_timer_min_ms = -1;
    101   int32_t media_timer_max_ms = -1;
    102   int32_t media_timer_avg_ms = -1;
    103   int64_t total_scheduling_count = -1;
    104   int32_t buffer_overruns_max_count = -1;
    105   int32_t buffer_overruns_total = -1;
    106   float buffer_underruns_average = -1;
    107   int32_t buffer_underruns_count = -1;
    108 };
    109 
    110 class BluetoothMetricsLogger {
    111  public:
    112   static BluetoothMetricsLogger* GetInstance() {
    113     static BluetoothMetricsLogger* instance = new BluetoothMetricsLogger();
    114     return instance;
    115   }
    116 
    117   /*
    118    * Record a pairing event
    119    *
    120    * Parameters:
    121    *    timestamp_ms: Unix epoch time in milliseconds
    122    *    device_class: class of remote device
    123    *    device_type: type of remote device
    124    *    disconnect_reason: HCI reason for pairing disconnection.
    125    *                       See: stack/include/hcidefs.h
    126    */
    127   void LogPairEvent(uint32_t disconnect_reason, uint64_t timestamp_ms,
    128                     uint32_t device_class, device_type_t device_type);
    129 
    130   /*
    131    * Record a wake event
    132    *
    133    * Parameters:
    134    *    timestamp_ms: Unix epoch time in milliseconds
    135    *    type: whether it was acquired or released
    136    *    requestor: if provided is the service requesting the wake lock
    137    *    name: the name of the wake lock held
    138    */
    139   void LogWakeEvent(wake_event_type_t type, const std::string& requestor,
    140                     const std::string& name, uint64_t timestamp_ms);
    141 
    142   /*
    143    * Record a scan event
    144    *
    145    * Parameters
    146    *    timestamp_ms : Unix epoch time in milliseconds
    147    *    start : true if this is the beginning of the scan
    148    *    initiator: a unique ID identifying the app starting the scan
    149    *    type: whether the scan reports BR/EDR, LE, or both.
    150    *    results: number of results to be reported.
    151    */
    152   void LogScanEvent(bool start, const std::string& initator, scan_tech_t type,
    153                     uint32_t results, uint64_t timestamp_ms);
    154 
    155   /*
    156    * Start logging a Bluetooth session
    157    *
    158    * A Bluetooth session is defined a a connection between this device and
    159    * another remote device which may include multiple profiles and protocols
    160    *
    161    * Only one Bluetooth session can exist at one time. Calling this method twice
    162    * without LogBluetoothSessionEnd will result in logging a premature end of
    163    * current Bluetooth session
    164    *
    165    * Parameters:
    166    *    connection_tech_type : type of connection technology
    167    *    timestamp_ms : the timestamp for session start, 0 means now
    168    *
    169    */
    170   void LogBluetoothSessionStart(connection_tech_t connection_tech_type,
    171                                 uint64_t timestamp_ms);
    172 
    173   /*
    174    * Stop logging a Bluetooth session and pushes it to the log queue
    175    *
    176    * If no Bluetooth session exist, this method exits immediately
    177    *
    178    * Parameters:
    179    *    disconnect_reason : A string representation of disconnect reason
    180    *    timestamp_ms : the timestamp of session end, 0 means now
    181    *
    182    */
    183   void LogBluetoothSessionEnd(disconnect_reason_t disconnect_reason,
    184                               uint64_t timestamp_ms);
    185 
    186   /*
    187    * Log information about remote device in a current Bluetooth session
    188    *
    189    * If a Bluetooth session does not exist, create one with default parameter
    190    * and timestamp now
    191    *
    192    * Parameters:
    193    *    device_class : device_class defined in btm_api_types.h
    194    *    device_type : type of remote device
    195    */
    196   void LogBluetoothSessionDeviceInfo(uint32_t device_class,
    197                                      device_type_t device_type);
    198 
    199   /*
    200    * Log A2DP Audio Session Information
    201    *
    202    * - Repeated calls to this method will override previous metrics if in the
    203    *   same Bluetooth connection
    204    * - If a Bluetooth session does not exist, create one with default parameter
    205    *   and timestamp now
    206    *
    207    * Parameters:
    208    *    a2dp_session_metrics - pointer to struct holding a2dp stats
    209    *
    210    */
    211   void LogA2dpSession(const A2dpSessionMetrics& a2dp_session_metrics);
    212 
    213   /**
    214    * Log Headset profile RFCOMM connection event
    215    *
    216    * @param service_id the BTA service ID for this headset connection
    217    */
    218   void LogHeadsetProfileRfcConnection(tBTA_SERVICE_ID service_id);
    219 
    220   /*
    221    * Writes the metrics, in base64 protobuf format, into the descriptor FD,
    222    * metrics events are always cleared after dump
    223    */
    224   void WriteBase64(int fd);
    225   void WriteBase64String(std::string* serialized);
    226   void WriteString(std::string* serialized);
    227 
    228   /*
    229    * Reset the metrics logger by cleaning up its staging queues and existing
    230    * protobuf objects.
    231    */
    232   void Reset();
    233 
    234   /*
    235    * Maximum number of log entries for each session or event
    236    */
    237   static const size_t kMaxNumBluetoothSession = 50;
    238   static const size_t kMaxNumPairEvent = 50;
    239   static const size_t kMaxNumWakeEvent = 1000;
    240   static const size_t kMaxNumScanEvent = 50;
    241 
    242  private:
    243   BluetoothMetricsLogger();
    244 
    245   /*
    246    * When a Bluetooth session is on and the user initiates a metrics dump, we
    247    * need to be able to upload whatever we have first. This method breaks the
    248    * ongoing Bluetooth session into two sessions with the previous one labeled
    249    * as "METRICS_DUMP" for the disconnect reason.
    250    */
    251   void CutoffSession();
    252 
    253   /*
    254    * Build the internal metrics object using information gathered
    255    */
    256   void Build();
    257 
    258   /*
    259    * Reset objects related to current Bluetooth session
    260    */
    261   void ResetSession();
    262 
    263   /*
    264    * Reset the underlining BluetoothLog object
    265    */
    266   void ResetLog();
    267 
    268   /*
    269    * PIMPL style implementation to hide internal dependencies
    270    */
    271   struct impl;
    272   std::unique_ptr<impl> const pimpl_;
    273 };
    274 }
    275