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