blob: 922cf7827c9d2fa686b1d16309d2d2867a767734 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/bluetooth/bluetooth_metrics.h"
#include <stdint.h>
#include <algorithm>
#include <map>
#include <set>
#include <unordered_set>
#include "base/hash/hash.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "device/bluetooth/public/cpp/bluetooth_uuid.h"
using device::BluetoothUUID;
namespace {
// Generates a hash from a canonical UUID string suitable for
// base::UmaHistogramSparse(positive int).
//
// Hash values can be produced manually using tool: bluetooth_metrics_hash.
int HashUUID(const std::string& canonical_uuid) {
DCHECK(canonical_uuid.size() == 36) << "HashUUID requires 128 bit UUID "
"strings in canonical format to "
"ensure consistent hash results.";
// TODO(520284): Other than verifying that |uuid| contains a value, this logic
// should be migrated to a dedicated histogram macro for hashed strings.
uint32_t data = base::PersistentHash(canonical_uuid);
// Strip off the sign bit to make the hash look nicer.
return static_cast<int>(data & 0x7fffffff);
}
int HashUUID(const base::Optional<BluetoothUUID>& uuid) {
return uuid ? HashUUID(uuid->canonical_value()) : 0;
}
} // namespace
namespace content {
// General
// requestDevice()
void RecordRequestDeviceOptions(
const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options) {
std::unordered_set<std::string> union_of_services;
for (const BluetoothUUID& service : options->optional_services) {
union_of_services.insert(service.canonical_value());
}
if (options->filters) {
for (const auto& filter : options->filters.value()) {
if (!filter->services) {
continue;
}
for (const BluetoothUUID& service : filter->services.value()) {
union_of_services.insert(service.canonical_value());
}
}
}
for (const std::string& service : union_of_services) {
// TODO(ortuno): Use a macro to histogram strings.
// http://crbug.com/520284
base::UmaHistogramSparse(
"Bluetooth.Web.RequestDevice.UnionOfServices.Services",
HashUUID(service));
}
}
// GATTServer.Connect
void RecordConnectGATTOutcome(UMAConnectGATTOutcome outcome) {
UMA_HISTOGRAM_ENUMERATION("Bluetooth.Web.ConnectGATT.Outcome",
static_cast<int>(outcome),
static_cast<int>(UMAConnectGATTOutcome::COUNT));
}
void RecordConnectGATTOutcome(CacheQueryOutcome outcome) {
DCHECK(outcome == CacheQueryOutcome::NO_DEVICE);
RecordConnectGATTOutcome(UMAConnectGATTOutcome::NO_DEVICE);
}
void RecordConnectGATTTimeSuccess(const base::TimeDelta& duration) {
UMA_HISTOGRAM_MEDIUM_TIMES("Bluetooth.Web.ConnectGATT.TimeSuccess", duration);
}
void RecordConnectGATTTimeFailed(const base::TimeDelta& duration) {
UMA_HISTOGRAM_MEDIUM_TIMES("Bluetooth.Web.ConnectGATT.TimeFailed", duration);
}
// getPrimaryService & getPrimaryServices
void RecordGetPrimaryServicesOutcome(
blink::mojom::WebBluetoothGATTQueryQuantity quantity,
UMAGetPrimaryServiceOutcome outcome) {
switch (quantity) {
case blink::mojom::WebBluetoothGATTQueryQuantity::SINGLE:
UMA_HISTOGRAM_ENUMERATION(
"Bluetooth.Web.GetPrimaryService.Outcome", static_cast<int>(outcome),
static_cast<int>(UMAGetPrimaryServiceOutcome::COUNT));
return;
case blink::mojom::WebBluetoothGATTQueryQuantity::MULTIPLE:
UMA_HISTOGRAM_ENUMERATION(
"Bluetooth.Web.GetPrimaryServices.Outcome", static_cast<int>(outcome),
static_cast<int>(UMAGetPrimaryServiceOutcome::COUNT));
return;
}
}
void RecordGetPrimaryServicesOutcome(
blink::mojom::WebBluetoothGATTQueryQuantity quantity,
CacheQueryOutcome outcome) {
DCHECK(outcome == CacheQueryOutcome::NO_DEVICE);
RecordGetPrimaryServicesOutcome(quantity,
UMAGetPrimaryServiceOutcome::NO_DEVICE);
}
void RecordGetPrimaryServicesServices(
blink::mojom::WebBluetoothGATTQueryQuantity quantity,
const base::Optional<BluetoothUUID>& service) {
// TODO(ortuno): Use a macro to histogram strings.
// http://crbug.com/520284
switch (quantity) {
case blink::mojom::WebBluetoothGATTQueryQuantity::SINGLE:
base::UmaHistogramSparse("Bluetooth.Web.GetPrimaryService.Services",
HashUUID(service));
return;
case blink::mojom::WebBluetoothGATTQueryQuantity::MULTIPLE:
base::UmaHistogramSparse("Bluetooth.Web.GetPrimaryServices.Services",
HashUUID(service));
return;
}
}
void RecordGetCharacteristicsCharacteristic(
blink::mojom::WebBluetoothGATTQueryQuantity quantity,
const base::Optional<BluetoothUUID>& characteristic) {
switch (quantity) {
case blink::mojom::WebBluetoothGATTQueryQuantity::SINGLE:
base::UmaHistogramSparse("Bluetooth.Web.GetCharacteristic.Characteristic",
HashUUID(characteristic));
return;
case blink::mojom::WebBluetoothGATTQueryQuantity::MULTIPLE:
base::UmaHistogramSparse(
"Bluetooth.Web.GetCharacteristics.Characteristic",
HashUUID(characteristic));
return;
}
}
void RecordRSSISignalStrength(int rssi) {
base::UmaHistogramSparse("Bluetooth.Web.RequestDevice.RSSISignalStrength",
rssi);
}
void RecordRSSISignalStrengthLevel(UMARSSISignalStrengthLevel level) {
UMA_HISTOGRAM_ENUMERATION(
"Bluetooth.Web.RequestDevice.RSSISignalStrengthLevel",
static_cast<int>(level),
static_cast<int>(UMARSSISignalStrengthLevel::COUNT));
}
} // namespace content