blob: dcd1a2065d751326b6baab821a603264190d7165 [file] [log] [blame]
/******************************************************************************
*
* 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 <stdint.h>
#include <memory>
#include <string>
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<impl> const pimpl_;
};
}