diff options
Diffstat (limited to 'device')
-rw-r--r-- | device/bluetooth/bluetooth_adapter_bluez.cc | 1 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_bluez_unittest.cc | 112 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_classic_device_mac.h | 1 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_classic_device_mac.mm | 7 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_device.cc | 33 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_device.h | 10 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_device_android.cc | 7 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_device_android.h | 1 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_device_bluez.cc | 12 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_device_bluez.h | 1 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_device_win.cc | 7 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_device_win.h | 1 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_low_energy_device_mac.h | 1 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_low_energy_device_mac.mm | 7 | ||||
-rw-r--r-- | device/bluetooth/test/mock_bluetooth_device.h | 1 |
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()); |