summaryrefslogtreecommitdiffstats
path: root/device
diff options
context:
space:
mode:
Diffstat (limited to 'device')
-rw-r--r--device/bluetooth/bluetooth_adapter_bluez.cc1
-rw-r--r--device/bluetooth/bluetooth_bluez_unittest.cc112
-rw-r--r--device/bluetooth/bluetooth_classic_device_mac.h1
-rw-r--r--device/bluetooth/bluetooth_classic_device_mac.mm7
-rw-r--r--device/bluetooth/bluetooth_device.cc33
-rw-r--r--device/bluetooth/bluetooth_device.h10
-rw-r--r--device/bluetooth/bluetooth_device_android.cc7
-rw-r--r--device/bluetooth/bluetooth_device_android.h1
-rw-r--r--device/bluetooth/bluetooth_device_bluez.cc12
-rw-r--r--device/bluetooth/bluetooth_device_bluez.h1
-rw-r--r--device/bluetooth/bluetooth_device_win.cc7
-rw-r--r--device/bluetooth/bluetooth_device_win.h1
-rw-r--r--device/bluetooth/bluetooth_low_energy_device_mac.h1
-rw-r--r--device/bluetooth/bluetooth_low_energy_device_mac.mm7
-rw-r--r--device/bluetooth/test/mock_bluetooth_device.h1
15 files changed, 202 insertions, 0 deletions
diff --git a/device/bluetooth/bluetooth_adapter_bluez.cc b/device/bluetooth/bluetooth_adapter_bluez.cc
index f8df754..1d22ef7 100644
--- a/device/bluetooth/bluetooth_adapter_bluez.cc
+++ b/device/bluetooth/bluetooth_adapter_bluez.cc
@@ -469,6 +469,7 @@ void BluetoothAdapterBlueZ::DevicePropertyChanged(
}
if (property_name == properties->bluetooth_class.name() ||
+ property_name == properties->appearance.name() ||
property_name == properties->address.name() ||
property_name == properties->alias.name() ||
property_name == properties->paired.name() ||
diff --git a/device/bluetooth/bluetooth_bluez_unittest.cc b/device/bluetooth/bluetooth_bluez_unittest.cc
index 309aec0..f99caab 100644
--- a/device/bluetooth/bluetooth_bluez_unittest.cc
+++ b/device/bluetooth/bluetooth_bluez_unittest.cc
@@ -2160,6 +2160,118 @@ TEST_F(BluetoothBlueZTest, DeviceClassChanged) {
EXPECT_EQ(BluetoothDevice::DEVICE_MOUSE, devices[idx]->GetDeviceType());
}
+TEST_F(BluetoothBlueZTest, DeviceAppearance) {
+ // Simulate a device with appearance.
+ GetAdapter();
+
+ BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
+ ASSERT_EQ(2U, devices.size());
+
+ int idx = GetDeviceIndexByAddress(
+ devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
+ ASSERT_NE(-1, idx);
+ ASSERT_EQ(BluetoothDevice::DEVICE_COMPUTER, devices[idx]->GetDeviceType());
+
+ // Install an observer; expect the DeviceChanged method to be called when
+ // we change the appearance of the device.
+ TestBluetoothAdapterObserver observer(adapter_);
+
+ bluez::FakeBluetoothDeviceClient::Properties* properties =
+ fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+ bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
+
+ // Let the device come without bluetooth_class.
+ properties->appearance.ReplaceValue(0); // DeviceChanged method called
+ EXPECT_EQ(1, observer.device_changed_count());
+ EXPECT_EQ(devices[idx], observer.last_device());
+
+ // Set the device appearance as keyboard (961).
+ properties->appearance.ReplaceValue(961); // DeviceChanged method called
+ properties->appearance.set_valid(true);
+ EXPECT_EQ(2, observer.device_changed_count());
+ EXPECT_EQ(devices[idx], observer.last_device());
+ EXPECT_EQ(961, devices[idx]->GetAppearance());
+ // When discovery is over, the value should be invalidated.
+ properties->appearance.set_valid(false);
+ // DeviceChanged method called by NotifyPropertyChanged()
+ properties->NotifyPropertyChanged(properties->appearance.name());
+ EXPECT_EQ(3, observer.device_changed_count());
+ EXPECT_EQ(devices[idx], observer.last_device());
+ EXPECT_EQ((int) BluetoothDevice::kAppearanceNotPresent,
+ devices[idx]->GetAppearance());
+
+ // Change the device appearance to mouse (962).
+ properties->appearance.ReplaceValue(962); // DeviceChanged method called
+ properties->appearance.set_valid(true);
+ EXPECT_EQ(4, observer.device_changed_count());
+ EXPECT_EQ(devices[idx], observer.last_device());
+ EXPECT_EQ(962, devices[idx]->GetAppearance());
+ // When discovery is over, the value should be invalidated.
+ properties->appearance.set_valid(false);
+ // DeviceChanged method called by NotifyPropertyChanged()
+ properties->NotifyPropertyChanged(properties->appearance.name());
+ EXPECT_EQ(5, observer.device_changed_count());
+ EXPECT_EQ(devices[idx], observer.last_device());
+ EXPECT_EQ((int) BluetoothDevice::kAppearanceNotPresent,
+ devices[idx]->GetAppearance());
+}
+
+TEST_F(BluetoothBlueZTest, DeviceTypebyAppearanceNotBluetoothClass) {
+ // Test device type of a device with appearance but without bluetooth class.
+ GetAdapter();
+
+ BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
+ ASSERT_EQ(2U, devices.size());
+
+ int idx = GetDeviceIndexByAddress(
+ devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
+ ASSERT_NE(-1, idx);
+ ASSERT_EQ(BluetoothDevice::DEVICE_COMPUTER, devices[idx]->GetDeviceType());
+
+ // Install an observer; expect the DeviceChanged method to be called when
+ // we change the appearance of the device.
+ TestBluetoothAdapterObserver observer(adapter_);
+
+ bluez::FakeBluetoothDeviceClient::Properties* properties =
+ fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+ bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
+
+ // Let the device come without bluetooth_class.
+ properties->bluetooth_class.ReplaceValue(0); // DeviceChanged method called
+ properties->appearance.ReplaceValue(0); // DeviceChanged method called
+ EXPECT_EQ(BluetoothDevice::DEVICE_UNKNOWN, devices[idx]->GetDeviceType());
+ EXPECT_EQ(2, observer.device_changed_count());
+ EXPECT_EQ(devices[idx], observer.last_device());
+
+ // Set the device appearance as keyboard.
+ properties->appearance.ReplaceValue(961); // DeviceChanged method called
+ properties->appearance.set_valid(true);
+ EXPECT_EQ(BluetoothDevice::DEVICE_KEYBOARD, devices[idx]->GetDeviceType());
+ EXPECT_EQ(3, observer.device_changed_count());
+ EXPECT_EQ(devices[idx], observer.last_device());
+ // When discovery is over, the value should be invalidated.
+ properties->appearance.set_valid(false);
+ // DeviceChanged method called by NotifyPropertyChanged()
+ properties->NotifyPropertyChanged(properties->appearance.name());
+ EXPECT_EQ(4, observer.device_changed_count());
+ EXPECT_EQ(devices[idx], observer.last_device());
+ EXPECT_EQ(BluetoothDevice::DEVICE_UNKNOWN, devices[idx]->GetDeviceType());
+
+ // Change the device appearance to mouse.
+ properties->appearance.ReplaceValue(962); // DeviceChanged method called
+ properties->appearance.set_valid(true);
+ EXPECT_EQ(BluetoothDevice::DEVICE_MOUSE, devices[idx]->GetDeviceType());
+ EXPECT_EQ(5, observer.device_changed_count());
+ EXPECT_EQ(devices[idx], observer.last_device());
+ // When discovery is over, the value should be invalidated.
+ properties->appearance.set_valid(false);
+ // DeviceChanged method called by NotifyPropertyChanged()
+ properties->NotifyPropertyChanged(properties->appearance.name());
+ EXPECT_EQ(6, observer.device_changed_count());
+ EXPECT_EQ(devices[idx], observer.last_device());
+ EXPECT_EQ(BluetoothDevice::DEVICE_UNKNOWN, devices[idx]->GetDeviceType());
+}
+
TEST_F(BluetoothBlueZTest, DeviceNameChanged) {
// Simulate a change of name of a device.
GetAdapter();
diff --git a/device/bluetooth/bluetooth_classic_device_mac.h b/device/bluetooth/bluetooth_classic_device_mac.h
index c582d6d..acd1dca 100644
--- a/device/bluetooth/bluetooth_classic_device_mac.h
+++ b/device/bluetooth/bluetooth_classic_device_mac.h
@@ -34,6 +34,7 @@ class BluetoothClassicDeviceMac : public BluetoothDeviceMac {
uint16_t GetVendorID() const override;
uint16_t GetProductID() const override;
uint16_t GetDeviceID() const override;
+ uint16_t GetAppearance() const override;
bool IsPaired() const override;
bool IsConnected() const override;
bool IsGattConnected() const override;
diff --git a/device/bluetooth/bluetooth_classic_device_mac.mm b/device/bluetooth/bluetooth_classic_device_mac.mm
index d1c3f63..985596e 100644
--- a/device/bluetooth/bluetooth_classic_device_mac.mm
+++ b/device/bluetooth/bluetooth_classic_device_mac.mm
@@ -102,6 +102,13 @@ uint16_t BluetoothClassicDeviceMac::GetDeviceID() const {
return 0;
}
+uint16_t BluetoothClassicDeviceMac::GetAppearance() const {
+ // TODO(crbug.com/588083): Implementing GetAppearance()
+ // on mac, win, and android platforms for chrome
+ NOTIMPLEMENTED();
+ return 0;
+}
+
bool BluetoothClassicDeviceMac::IsPaired() const {
return [device_ isPaired];
}
diff --git a/device/bluetooth/bluetooth_device.cc b/device/bluetooth/bluetooth_device.cc
index c85af11..5696632 100644
--- a/device/bluetooth/bluetooth_device.cc
+++ b/device/bluetooth/bluetooth_device.cc
@@ -171,6 +171,39 @@ BluetoothDevice::DeviceType BluetoothDevice::GetDeviceType() const {
break;
}
+ // Some bluetooth devices, e.g., Microsoft Universal Foldable Keyboard,
+ // do not expose its bluetooth class. Use its appearance as a work-around.
+ // https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml
+ uint16_t appearance = GetAppearance();
+ // appearance: 10-bit category and 6-bit sub-category
+ switch ((appearance & 0xffc0) >> 6) {
+ case 0x01:
+ // Generic phone
+ return DEVICE_PHONE;
+ case 0x02:
+ // Generic computer
+ return DEVICE_COMPUTER;
+ case 0x0f:
+ // HID subtype
+ switch (appearance & 0x3f) {
+ case 0x01:
+ // Keyboard.
+ return DEVICE_KEYBOARD;
+ case 0x02:
+ // Mouse
+ return DEVICE_MOUSE;
+ case 0x03:
+ // Joystick
+ return DEVICE_JOYSTICK;
+ case 0x04:
+ // Gamepad
+ return DEVICE_GAMEPAD;
+ case 0x05:
+ // Digitizer tablet
+ return DEVICE_TABLET;
+ }
+ }
+
return DEVICE_UNKNOWN;
}
diff --git a/device/bluetooth/bluetooth_device.h b/device/bluetooth/bluetooth_device.h
index 2bf6f35..82cc1ce 100644
--- a/device/bluetooth/bluetooth_device.h
+++ b/device/bluetooth/bluetooth_device.h
@@ -78,6 +78,8 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDevice {
// The value returned if the RSSI or transmit power cannot be read.
static const int kUnknownPower = 127;
+ // The value returned if the appearance is not present.
+ static const uint16_t kAppearanceNotPresent = 0xffc0;
struct DEVICE_BLUETOOTH_EXPORT ConnectionInfo {
int rssi;
@@ -223,6 +225,9 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDevice {
// number in BCD format, where available.
virtual uint16_t GetDeviceID() const = 0;
+ // Returns the appearance of the device.
+ virtual uint16_t GetAppearance() const = 0;
+
// Returns the name of the device suitable for displaying, this may
// be a synthesized string containing the address and localized type name
// if the device has no obtained name.
@@ -232,6 +237,11 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDevice {
// aware of, by decoding the bluetooth class information. The returned
// values are unique, and do not overlap, so DEVICE_KEYBOARD is not also
// DEVICE_PERIPHERAL.
+ //
+ // Returns the type of the device, limited to those we support or are aware
+ // of, by decoding the bluetooth class information for Classic devices or
+ // by decoding the device's appearance for LE devices. For example,
+ // Microsoft Universal Foldable Keyboard only advertises the appearance.
DeviceType GetDeviceType() const;
// Indicates whether the device is known to support pairing based on its
diff --git a/device/bluetooth/bluetooth_device_android.cc b/device/bluetooth/bluetooth_device_android.cc
index 27fdbaf..6149732 100644
--- a/device/bluetooth/bluetooth_device_android.cc
+++ b/device/bluetooth/bluetooth_device_android.cc
@@ -96,6 +96,13 @@ uint16_t BluetoothDeviceAndroid::GetDeviceID() const {
return 0;
}
+uint16_t BluetoothDeviceAndroid::GetAppearance() const {
+ // TODO(crbug.com/588083): Implementing GetAppearance()
+ // on mac, win, and android platforms for chrome
+ NOTIMPLEMENTED();
+ return 0;
+}
+
bool BluetoothDeviceAndroid::IsPaired() const {
return Java_ChromeBluetoothDevice_isPaired(AttachCurrentThread(),
j_device_.obj());
diff --git a/device/bluetooth/bluetooth_device_android.h b/device/bluetooth/bluetooth_device_android.h
index 2fc634d..84e47bb 100644
--- a/device/bluetooth/bluetooth_device_android.h
+++ b/device/bluetooth/bluetooth_device_android.h
@@ -58,6 +58,7 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceAndroid final
uint16_t GetVendorID() const override;
uint16_t GetProductID() const override;
uint16_t GetDeviceID() const override;
+ uint16_t GetAppearance() const override;
bool IsPaired() const override;
bool IsConnected() const override;
bool IsGattConnected() const override;
diff --git a/device/bluetooth/bluetooth_device_bluez.cc b/device/bluetooth/bluetooth_device_bluez.cc
index 4001f90..5ee49a4 100644
--- a/device/bluetooth/bluetooth_device_bluez.cc
+++ b/device/bluetooth/bluetooth_device_bluez.cc
@@ -244,6 +244,18 @@ uint16_t BluetoothDeviceBlueZ::GetDeviceID() const {
return device_id;
}
+uint16_t BluetoothDeviceBlueZ::GetAppearance() const {
+ bluez::BluetoothDeviceClient::Properties* properties =
+ bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
+ object_path_);
+ DCHECK(properties);
+
+ if (!properties->appearance.is_valid())
+ return kAppearanceNotPresent;
+
+ return properties->appearance.value();
+}
+
bool BluetoothDeviceBlueZ::IsPaired() const {
bluez::BluetoothDeviceClient::Properties* properties =
bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
diff --git a/device/bluetooth/bluetooth_device_bluez.h b/device/bluetooth/bluetooth_device_bluez.h
index 595bab4..4b15aea 100644
--- a/device/bluetooth/bluetooth_device_bluez.h
+++ b/device/bluetooth/bluetooth_device_bluez.h
@@ -47,6 +47,7 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceBlueZ
uint16_t GetVendorID() const override;
uint16_t GetProductID() const override;
uint16_t GetDeviceID() const override;
+ uint16_t GetAppearance() const override;
bool IsPaired() const override;
bool IsConnected() const override;
bool IsGattConnected() const override;
diff --git a/device/bluetooth/bluetooth_device_win.cc b/device/bluetooth/bluetooth_device_win.cc
index d63b9d0..310aa9d 100644
--- a/device/bluetooth/bluetooth_device_win.cc
+++ b/device/bluetooth/bluetooth_device_win.cc
@@ -70,6 +70,13 @@ uint16_t BluetoothDeviceWin::GetDeviceID() const {
return 0;
}
+uint16_t BluetoothDeviceWin::GetAppearance() const {
+ // TODO(crbug.com/588083): Implementing GetAppearance()
+ // on mac, win, and android platforms for chrome
+ NOTIMPLEMENTED();
+ return 0;
+}
+
bool BluetoothDeviceWin::IsPaired() const {
return paired_;
}
diff --git a/device/bluetooth/bluetooth_device_win.h b/device/bluetooth/bluetooth_device_win.h
index 6166032..bba7fb3 100644
--- a/device/bluetooth/bluetooth_device_win.h
+++ b/device/bluetooth/bluetooth_device_win.h
@@ -40,6 +40,7 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceWin : public BluetoothDevice {
uint16_t GetVendorID() const override;
uint16_t GetProductID() const override;
uint16_t GetDeviceID() const override;
+ uint16_t GetAppearance() const override;
bool IsPaired() const override;
bool IsConnected() const override;
bool IsGattConnected() const override;
diff --git a/device/bluetooth/bluetooth_low_energy_device_mac.h b/device/bluetooth/bluetooth_low_energy_device_mac.h
index f2517dd..ad713a5 100644
--- a/device/bluetooth/bluetooth_low_energy_device_mac.h
+++ b/device/bluetooth/bluetooth_low_energy_device_mac.h
@@ -46,6 +46,7 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothLowEnergyDeviceMac
uint16_t GetVendorID() const override;
uint16_t GetProductID() const override;
uint16_t GetDeviceID() const override;
+ uint16_t GetAppearance() const override;
bool IsPaired() const override;
bool IsConnected() const override;
bool IsGattConnected() const override;
diff --git a/device/bluetooth/bluetooth_low_energy_device_mac.mm b/device/bluetooth/bluetooth_low_energy_device_mac.mm
index ac0357e..00712ae 100644
--- a/device/bluetooth/bluetooth_low_energy_device_mac.mm
+++ b/device/bluetooth/bluetooth_low_energy_device_mac.mm
@@ -106,6 +106,13 @@ uint16_t BluetoothLowEnergyDeviceMac::GetDeviceID() const {
return 0;
}
+uint16_t BluetoothLowEnergyDeviceMac::GetAppearance() const {
+ // TODO(crbug.com/588083): Implementing GetAppearance()
+ // on mac, win, and android platforms for chrome
+ NOTIMPLEMENTED();
+ return 0;
+}
+
int BluetoothLowEnergyDeviceMac::GetRSSI() const {
return rssi_;
}
diff --git a/device/bluetooth/test/mock_bluetooth_device.h b/device/bluetooth/test/mock_bluetooth_device.h
index 5aab092..801a936 100644
--- a/device/bluetooth/test/mock_bluetooth_device.h
+++ b/device/bluetooth/test/mock_bluetooth_device.h
@@ -41,6 +41,7 @@ class MockBluetoothDevice : public BluetoothDevice {
MOCK_CONST_METHOD0(GetDeviceID, uint16_t());
MOCK_CONST_METHOD0(GetName, base::string16());
MOCK_CONST_METHOD0(GetDeviceType, BluetoothDevice::DeviceType());
+ MOCK_CONST_METHOD0(GetAppearance, uint16_t());
MOCK_CONST_METHOD0(IsPaired, bool());
MOCK_CONST_METHOD0(IsConnected, bool());
MOCK_CONST_METHOD0(IsGattConnected, bool());