blob: 1b9bca0042383250172751f94e56f29140f682b9 [file] [log] [blame]
/*
* Copyright 2022 The Android Open Source Project
*
* 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.
*/
#define LOG_TAG "BluetoothMetrics"
#include "metrics/metrics.h"
#include <metrics/structured_events.h>
#include "common/time_util.h"
#include "metrics/chromeos/metrics_allowlist.h"
#include "metrics/chromeos/metrics_event.h"
#include "metrics/utils.h"
#include "os/log.h"
namespace bluetooth {
namespace metrics {
static constexpr uint32_t DEVICE_MAJOR_CLASS_MASK = 0x1F00;
static constexpr uint32_t DEVICE_MAJOR_CLASS_BIT_OFFSET = 8;
static constexpr uint32_t DEVICE_CATEGORY_MASK = 0xFFC0;
static constexpr uint32_t DEVICE_CATEGORY_BIT_OFFSET = 6;
void LogMetricsAdapterStateChanged(uint32_t state) {
int64_t adapter_state;
int64_t boot_time;
std::string boot_id;
if (!GetBootId(&boot_id)) return;
adapter_state = (int64_t)ToAdapterState(state);
boot_time = bluetooth::common::time_get_os_boottime_us();
LOG_DEBUG("AdapterStateChanged: %s, %d, %d", boot_id.c_str(), boot_time, adapter_state);
::metrics::structured::events::bluetooth::BluetoothAdapterStateChanged()
.SetBootId(boot_id)
.SetSystemTime(boot_time)
.SetIsFloss(true)
.SetAdapterState(adapter_state)
.Record();
LogMetricsChipsetInfoReport();
}
void LogMetricsBondCreateAttempt(RawAddress* addr, uint32_t device_type) {
ConnectionType connection_type;
int64_t boot_time;
std::string addr_string;
std::string boot_id;
if (!GetBootId(&boot_id)) return;
addr_string = addr->ToString();
boot_time = bluetooth::common::time_get_os_boottime_us();
connection_type = ToPairingDeviceType(addr_string, device_type);
LOG_DEBUG(
"PairingStateChanged: %s, %d, %s, %d, %d",
boot_id.c_str(),
(int)boot_time,
addr_string.c_str(),
(int)connection_type,
(int)PairingState::PAIR_STARTING);
::metrics::structured::events::bluetooth::BluetoothPairingStateChanged()
.SetBootId(boot_id)
.SetSystemTime(boot_time)
.SetDeviceId(addr_string)
.SetDeviceType((int64_t)connection_type)
.SetPairingState((int64_t)PairingState::PAIR_STARTING)
.Record();
}
void LogMetricsBondStateChanged(
RawAddress* addr, uint32_t device_type, uint32_t status, uint32_t bond_state, int32_t fail_reason) {
ConnectionType connection_type;
int64_t boot_time;
PairingState pairing_state;
std::string addr_string;
std::string boot_id;
if (!GetBootId(&boot_id)) return;
addr_string = addr->ToString();
boot_time = bluetooth::common::time_get_os_boottime_us();
connection_type = ToPairingDeviceType(addr_string, device_type);
pairing_state = ToPairingState(status, bond_state, fail_reason);
// Ignore the start of pairing event as its logged separated above.
if (pairing_state == PairingState::PAIR_STARTING) return;
// Ignore absurd state.
if (pairing_state == PairingState::PAIR_FAIL_END) return;
LOG_DEBUG(
"PairingStateChanged: %s, %d, %s, %d, %d",
boot_id.c_str(),
(int)boot_time,
addr_string.c_str(),
(int)connection_type,
(int)pairing_state);
::metrics::structured::events::bluetooth::BluetoothPairingStateChanged()
.SetBootId(boot_id)
.SetSystemTime(boot_time)
.SetDeviceId(addr_string)
.SetDeviceType((int64_t)connection_type)
.SetPairingState((int64_t)pairing_state)
.Record();
}
void LogMetricsDeviceInfoReport(
RawAddress* addr,
uint32_t device_type,
uint32_t class_of_device,
uint32_t appearance,
uint32_t vendor_id,
uint32_t vendor_id_src,
uint32_t product_id,
uint32_t version) {
int64_t boot_time;
std::string addr_string;
std::string boot_id;
uint32_t major_class;
uint32_t category;
if (!GetBootId(&boot_id)) return;
addr_string = addr->ToString();
boot_time = bluetooth::common::time_get_os_boottime_us();
major_class = (class_of_device & DEVICE_MAJOR_CLASS_MASK) >> DEVICE_MAJOR_CLASS_BIT_OFFSET;
category = (appearance & DEVICE_CATEGORY_MASK) >> DEVICE_CATEGORY_BIT_OFFSET;
LOG_DEBUG(
"DeviceInfoReport %s %d %s %d %d %d %d %d %d %d",
boot_id.c_str(),
(int)boot_time,
addr_string.c_str(),
(int)device_type,
(int)major_class,
(int)category,
(int)vendor_id,
(int)vendor_id_src,
(int)product_id,
(int)version);
if (!IsDeviceInfoInAllowlist(vendor_id_src, vendor_id, product_id)) {
vendor_id_src = 0;
vendor_id = 0;
product_id = 0;
version = 0;
}
::metrics::structured::events::bluetooth::BluetoothDeviceInfoReport()
.SetBootId(boot_id)
.SetSystemTime(boot_time)
.SetDeviceId(addr_string)
.SetDeviceType(device_type)
.SetDeviceClass(major_class)
.SetDeviceCategory(category)
.SetVendorId(vendor_id)
.SetVendorIdSource(vendor_id_src)
.SetProductId(product_id)
.SetProductVersion(version)
.Record();
}
void LogMetricsProfileConnectionStateChanged(RawAddress* addr, uint32_t profile, uint32_t status, uint32_t state) {
int64_t boot_time;
std::string addr_string;
std::string boot_id;
if (!GetBootId(&boot_id)) return;
addr_string = addr->ToString();
boot_time = bluetooth::common::time_get_os_boottime_us();
ProfileConnectionEvent event = ToProfileConnectionEvent(addr_string, profile, status, state);
if (Profile::UNKNOWN == (Profile)event.profile) return;
LOG_DEBUG(
"ProfileConnectionStateChanged: %s, %d, %s, %d, %d, %d",
boot_id.c_str(),
(int)boot_time,
addr_string.c_str(),
(int)event.type,
(int)event.profile,
(int)event.state);
::metrics::structured::events::bluetooth::BluetoothProfileConnectionStateChanged()
.SetBootId(boot_id)
.SetSystemTime(boot_time)
.SetDeviceId(addr_string)
.SetStateChangeType((int64_t)event.type)
.SetProfile((int64_t)event.profile)
.SetProfileConnectionState((int64_t)event.state)
.Record();
}
void LogMetricsAclConnectAttempt(RawAddress* addr, uint32_t acl_state) {
int64_t boot_time = bluetooth::common::time_get_os_boottime_us();
std::string addr_string = addr->ToString();
// At this time we don't know the transport layer, therefore pending on sending the event
PendingAclConnectAttemptEvent(addr_string, boot_time, acl_state);
}
void LogMetricsAclConnectionStateChanged(
RawAddress* addr,
uint32_t transport,
uint32_t acl_status,
uint32_t acl_state,
uint32_t direction,
uint32_t hci_reason) {
int64_t boot_time;
std::string addr_string;
std::string boot_id;
bool attempt_found;
AclConnectionEvent event;
boot_time = bluetooth::common::time_get_os_boottime_us();
addr_string = addr->ToString();
event = ToAclConnectionEvent(addr_string, boot_time, acl_status, acl_state, direction, hci_reason);
if (!GetBootId(&boot_id)) {
return;
}
LOG_DEBUG(
"AclConnectionStateChanged: %s, %d, %s, %d, %d, %d, %d, %d",
boot_id.c_str(),
(int)event.start_time,
addr_string.c_str(),
(int)transport,
(int)event.direction,
(int)event.initiator,
(int)event.state,
(int)event.start_status);
::metrics::structured::events::bluetooth::BluetoothAclConnectionStateChanged()
.SetBootId(boot_id)
.SetSystemTime(event.start_time)
.SetIsFloss(true)
.SetDeviceId(addr_string)
.SetDeviceType(transport)
.SetConnectionDirection(event.direction)
.SetConnectionInitiator(event.initiator)
.SetStateChangeType(event.state)
.SetAclConnectionState(event.start_status)
.Record();
LOG_DEBUG(
"AclConnectionStateChanged: %s, %d, %s, %d, %d, %d, %d, %d",
boot_id.c_str(),
(int)boot_time,
addr_string.c_str(),
(int)transport,
(int)event.direction,
(int)event.initiator,
(int)event.state,
(int)event.status);
::metrics::structured::events::bluetooth::BluetoothAclConnectionStateChanged()
.SetBootId(boot_id)
.SetSystemTime(boot_time)
.SetIsFloss(true)
.SetDeviceId(addr_string)
.SetDeviceType(transport)
.SetConnectionDirection(event.direction)
.SetConnectionInitiator(event.initiator)
.SetStateChangeType(event.state)
.SetAclConnectionState(event.status)
.Record();
LogMetricsChipsetInfoReport();
}
void LogMetricsChipsetInfoReport() {
static MetricsChipsetInfo* info = NULL;
uint64_t chipset_string_hval = 0;
std::string boot_id;
if (!info) {
info = (MetricsChipsetInfo*)calloc(1, sizeof(MetricsChipsetInfo));
*info = GetMetricsChipsetInfo();
}
if (!GetBootId(&boot_id)) {
return;
}
LOG_DEBUG("ChipsetInfoReport: 0x%x 0x%x %d %s", info->vid, info->pid, info->transport, info->chipset_string.c_str());
if (IsChipsetInfoInAllowList(
info->vid, info->pid, info->transport, info->chipset_string.c_str(), &chipset_string_hval)) {
::metrics::structured::events::bluetooth::BluetoothChipsetInfoReport()
.SetBootId(boot_id.c_str())
.SetVendorId(info->vid)
.SetProductId(info->pid)
.SetTransport(info->transport)
.SetChipsetStringHashValue(chipset_string_hval);
}
}
void LogMetricsSuspendIdState(uint32_t state) {
int64_t suspend_id_state = 0;
int64_t boot_time;
std::string boot_id;
if (!GetBootId(&boot_id)) return;
boot_time = bluetooth::common::time_get_os_boottime_us();
suspend_id_state = (int64_t)ToSuspendIdState(state);
LOG_DEBUG("SuspendIdState: %s, %d, %d", boot_id.c_str(), boot_time, suspend_id_state);
::metrics::structured::events::bluetooth::BluetoothSuspendIdStateChanged()
.SetBootId(boot_id)
.SetSystemTime(boot_time)
.SetSuspendIdState(suspend_id_state)
.Record();
}
} // namespace metrics
} // namespace bluetooth