Commit e088f02c authored by erikchen@chromium.org's avatar erikchen@chromium.org

mac: Add metrics to record Bluetooth availability and capabilities.

The new Handoff feature in OSX 10.10 only works with devices that support
Bluetooth LE. Record metrics to determine the percentage of Chrome users that
this affects.

BUG=392166

Review URL: https://codereview.chromium.org/374203004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@282771 0039d316-1c4b-4281-b951-d872f2087c98
parent 6bad505f
...@@ -160,6 +160,10 @@ enum CWChannelBand { ...@@ -160,6 +160,10 @@ enum CWChannelBand {
- (BluetoothHCIPowerState)powerState; - (BluetoothHCIPowerState)powerState;
@end @end
enum {
kBluetoothFeatureLESupportedController = (1 << 6L),
};
@protocol IOBluetoothDeviceInquiryDelegate @protocol IOBluetoothDeviceInquiryDelegate
- (void)deviceInquiryStarted:(IOBluetoothDeviceInquiry*)sender; - (void)deviceInquiryStarted:(IOBluetoothDeviceInquiry*)sender;
- (void)deviceInquiryDeviceFound:(IOBluetoothDeviceInquiry*)sender - (void)deviceInquiryDeviceFound:(IOBluetoothDeviceInquiry*)sender
......
// Copyright 2014 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.
#ifndef CHROME_BROWSER_MAC_BLUETOOTH_UTILITY_H_
#define CHROME_BROWSER_MAC_BLUETOOTH_UTILITY_H_
namespace bluetooth_utility {
// The enum is used in a histogram, so the values must not change.
enum BluetoothAvailability {
BLUETOOTH_AVAILABILITY_ERROR = 0, // Error determining availability.
BLUETOOTH_NOT_AVAILABLE = 1,
BLUETOOTH_AVAILABLE_WITHOUT_LE = 2,
BLUETOOTH_AVAILABLE_WITH_LE = 3,
// On OSX 10.6, if the Link Manager Protocol version supports Low Energy,
// there is no further indication of whether Low Energy is supported.
BLUETOOTH_AVAILABLE_LE_UNKNOWN = 4,
BLUETOOTH_AVAILABILITY_COUNT,
};
// Returns the bluetooth availability of the system's hardware.
BluetoothAvailability GetBluetoothAvailability();
} // namespace bluetooth_utility
#endif // CHROME_BROWSER_MAC_BLUETOOTH_UTILITY_H_
// Copyright 2014 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 "chrome/browser/mac/bluetooth_utility.h"
#import <Foundation/Foundation.h>
#include <IOKit/IOKitLib.h>
#include "base/mac/foundation_util.h"
#include "base/mac/mac_util.h"
#include "base/mac/scoped_ioobject.h"
#include "base/mac/sdk_forward_declarations.h"
namespace bluetooth_utility {
BluetoothAvailability GetBluetoothAvailability() {
base::ScopedCFTypeRef<CFMutableDictionaryRef> matching_dict(
IOServiceMatching("IOBluetoothHCIController"));
if (!matching_dict)
return BLUETOOTH_AVAILABILITY_ERROR;
// IOServiceGetMatchingServices takes ownership of matching_dict.
io_iterator_t iter;
int kr = IOServiceGetMatchingServices(
kIOMasterPortDefault, matching_dict.release(), &iter);
if (kr != KERN_SUCCESS)
return BLUETOOTH_NOT_AVAILABLE;
base::mac::ScopedIOObject<io_iterator_t> scoped_iter(iter);
int bluetooth_available = false;
base::mac::ScopedIOObject<io_service_t> device;
while (device.reset(IOIteratorNext(scoped_iter.get())), device) {
bluetooth_available = true;
CFMutableDictionaryRef dict;
kr = IORegistryEntryCreateCFProperties(
device, &dict, kCFAllocatorDefault, kNilOptions);
if (kr != KERN_SUCCESS)
continue;
base::ScopedCFTypeRef<CFMutableDictionaryRef> scoped_dict(dict);
NSDictionary* objc_dict = base::mac::CFToNSCast(scoped_dict.get());
NSNumber* lmp_version =
base::mac::ObjCCast<NSNumber>([objc_dict objectForKey:@"LMPVersion"]);
if (!lmp_version)
continue;
// The LMP version is too low to support Bluetooth LE.
if ([lmp_version intValue] < 6)
continue;
// Check the supported features registry entry for Bluetooth LE
// availability. The relevant bit has a different meaning on OSX 10.6, and
// could change again in the future.
if (base::mac::IsOSSnowLeopard())
return BLUETOOTH_AVAILABLE_LE_UNKNOWN;
NSData* data = base::mac::ObjCCast<NSData>(
[objc_dict objectForKey:@"HCISupportedFeatures"]);
NSUInteger supported_features_index = 4;
NSUInteger length = [data length];
if (length < supported_features_index + 1)
continue;
// The bytes are indexed in reverse order.
NSUInteger index = length - supported_features_index - 1;
const unsigned char* bytes =
static_cast<const unsigned char*>([data bytes]);
const unsigned char byte = bytes[index];
bool le_supported = byte & kBluetoothFeatureLESupportedController;
if (le_supported)
return BLUETOOTH_AVAILABLE_WITH_LE;
}
return bluetooth_available ? BLUETOOTH_AVAILABLE_WITHOUT_LE
: BLUETOOTH_AVAILABILITY_ERROR;
}
} // namespace bluetooth_utility
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_browser_main.h" #include "chrome/browser/chrome_browser_main.h"
#include "chrome/browser/chrome_browser_metrics_service_observer.h" #include "chrome/browser/chrome_browser_metrics_service_observer.h"
#include "chrome/browser/mac/bluetooth_utility.h"
#include "chrome/browser/pref_service_flags_storage.h" #include "chrome/browser/pref_service_flags_storage.h"
#include "chrome/browser/shell_integration.h" #include "chrome/browser/shell_integration.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
...@@ -94,6 +95,14 @@ void RecordStartupMetricsOnBlockingPool() { ...@@ -94,6 +95,14 @@ void RecordStartupMetricsOnBlockingPool() {
#if defined(OS_WIN) #if defined(OS_WIN)
GoogleUpdateSettings::RecordChromeUpdatePolicyHistograms(); GoogleUpdateSettings::RecordChromeUpdatePolicyHistograms();
#endif // defined(OS_WIN) #endif // defined(OS_WIN)
#if defined(OS_MACOSX) && !defined(OS_IOS)
bluetooth_utility::BluetoothAvailability availability =
bluetooth_utility::GetBluetoothAvailability();
UMA_HISTOGRAM_ENUMERATION("OSX.BluetoothAvailability",
availability,
bluetooth_utility::BLUETOOTH_AVAILABILITY_COUNT);
#endif // defined(OS_MACOSX) && !defined(OS_IOS)
} }
void RecordLinuxGlibcVersion() { void RecordLinuxGlibcVersion() {
......
...@@ -656,6 +656,8 @@ ...@@ -656,6 +656,8 @@
'browser/lifetime/application_lifetime_win.cc', 'browser/lifetime/application_lifetime_win.cc',
'browser/mac/dock.h', 'browser/mac/dock.h',
'browser/mac/dock.mm', 'browser/mac/dock.mm',
'browser/mac/bluetooth_utility.h',
'browser/mac/bluetooth_utility.mm',
'browser/mac/install_from_dmg.h', 'browser/mac/install_from_dmg.h',
'browser/mac/install_from_dmg.mm', 'browser/mac/install_from_dmg.mm',
'browser/mac/keystone_glue.h', 'browser/mac/keystone_glue.h',
......
...@@ -18976,6 +18976,14 @@ Therefore, the affected-histogram name has to have at least one dot in it. ...@@ -18976,6 +18976,14 @@ Therefore, the affected-histogram name has to have at least one dot in it.
<summary>The number of clicks on the origin chip.</summary> <summary>The number of clicks on the origin chip.</summary>
</histogram> </histogram>
<histogram name="OSX.BluetoothAvailability" enum="BluetoothAvailability">
<owner>erikchen@chromium.org</owner>
<summary>
The availability and capabilities of the Bluetooth driver on OSX devices.
This metric is logged on startup.
</summary>
</histogram>
<histogram name="OSX.CatSixtyFour" enum="CatSixtyFour"> <histogram name="OSX.CatSixtyFour" enum="CatSixtyFour">
<owner>mark@chromium.org</owner> <owner>mark@chromium.org</owner>
<summary>The cat's flavor and how many bits there are in it.</summary> <summary>The cat's flavor and how many bits there are in it.</summary>
...@@ -35540,6 +35548,14 @@ Therefore, the affected-histogram name has to have at least one dot in it. ...@@ -35540,6 +35548,14 @@ Therefore, the affected-histogram name has to have at least one dot in it.
<int value="5" label="Blacklist disabled."/> <int value="5" label="Blacklist disabled."/>
</enum> </enum>
<enum name="BluetoothAvailability" type="int">
<int value="0" label="Unexpected error"/>
<int value="1" label="Not available"/>
<int value="2" label="Available without LE"/>
<int value="3" label="Available with LE"/>
<int value="4" label="Available unknown LE"/>
</enum>
<enum name="BluetoothPairingMethod" type="int"> <enum name="BluetoothPairingMethod" type="int">
<int value="0" label="No user interaction required"/> <int value="0" label="No user interaction required"/>
<int value="1" label="PIN Code requested from user"/> <int value="1" label="PIN Code requested from user"/>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment