diff options
author | scheib <scheib@chromium.org> | 2015-10-22 20:23:24 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-10-23 03:24:16 +0000 |
commit | 41bcc6805171e2ab23a84b95f2c7cdfb1e3e473d (patch) | |
tree | f4d421bf5d0bc60825ef1d2f221907d63b043cb9 | |
parent | 36a9ce13a885ab83e7bcc74422b6f6b1a8c1e1e8 (diff) | |
download | chromium_src-41bcc6805171e2ab23a84b95f2c7cdfb1e3e473d.zip chromium_src-41bcc6805171e2ab23a84b95f2c7cdfb1e3e473d.tar.gz chromium_src-41bcc6805171e2ab23a84b95f2c7cdfb1e3e473d.tar.bz2 |
bluetooth: android: Implement BluetoothRemoteGattServiceAndroid::GetCharacteristic{s}
Create intial C++ Stub for BluetoothRemoteGattCharacteristicAndroid.
Return Characteristic objects from
BluetoothRemoteGattServiceAndroid::GetCharacteristics()
BluetoothRemoteGattServiceAndroid::GetCharacteristic()
BUG=541400, 545682
Review URL: https://codereview.chromium.org/1406323004
Cr-Commit-Position: refs/heads/master@{#355723}
16 files changed, 460 insertions, 18 deletions
diff --git a/device/bluetooth/BUILD.gn b/device/bluetooth/BUILD.gn index a5ea564..f1b7bc9 100644 --- a/device/bluetooth/BUILD.gn +++ b/device/bluetooth/BUILD.gn @@ -98,6 +98,8 @@ component("bluetooth") { "bluetooth_low_energy_win.h", "bluetooth_pairing_chromeos.cc", "bluetooth_pairing_chromeos.h", + "bluetooth_remote_gatt_characteristic_android.cc", + "bluetooth_remote_gatt_characteristic_android.h", "bluetooth_remote_gatt_characteristic_chromeos.cc", "bluetooth_remote_gatt_characteristic_chromeos.h", "bluetooth_remote_gatt_descriptor_chromeos.cc", diff --git a/device/bluetooth/android/bluetooth_jni_registrar.cc b/device/bluetooth/android/bluetooth_jni_registrar.cc index a72ddf6..82b9894 100644 --- a/device/bluetooth/android/bluetooth_jni_registrar.cc +++ b/device/bluetooth/android/bluetooth_jni_registrar.cc @@ -9,6 +9,7 @@ #include "device/bluetooth/android/wrappers.h" #include "device/bluetooth/bluetooth_adapter_android.h" #include "device/bluetooth/bluetooth_device_android.h" +#include "device/bluetooth/bluetooth_remote_gatt_service_android.h" namespace device { namespace android { @@ -17,6 +18,8 @@ namespace { const base::android::RegistrationMethod kRegisteredMethods[] = { {"BluetoothAdapterAndroid", device::BluetoothAdapterAndroid::RegisterJNI}, {"BluetoothDeviceAndroid", device::BluetoothDeviceAndroid::RegisterJNI}, + {"BluetoothRemoteGattServiceAndroid", + device::BluetoothRemoteGattServiceAndroid::RegisterJNI}, {"Wrappers", device::WrappersRegisterJNI}, }; diff --git a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothDevice.java b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothDevice.java index c55fb45..82a7273 100644 --- a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothDevice.java +++ b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothDevice.java @@ -165,6 +165,8 @@ final class ChromeBluetoothDevice { mBluetoothGatt.getServices()) { // Create a device unique service ID. getInstanceId only differs // between service instances with the same UUID. + // TODO(scheib): Make instance IDs unique to the whole adapter. + // http://crbug.com/546747 String serviceInstanceId = service.getUuid().toString() + service.getInstanceId(); nativeCreateGattRemoteService( diff --git a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothRemoteGattService.java b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothRemoteGattService.java index 62c379a..2d9a0e4 100644 --- a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothRemoteGattService.java +++ b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothRemoteGattService.java @@ -8,6 +8,8 @@ import org.chromium.base.Log; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; +import java.util.List; + /** * Exposes android.bluetooth.BluetoothGattService as necessary * for C++ device::BluetoothRemoteGattServiceAndroid. @@ -19,13 +21,24 @@ import org.chromium.base.annotations.JNINamespace; final class ChromeBluetoothRemoteGattService { private static final String TAG = "Bluetooth"; + private long mNativeBluetoothRemoteGattServiceAndroid; final Wrappers.BluetoothGattServiceWrapper mService; - private ChromeBluetoothRemoteGattService(Wrappers.BluetoothGattServiceWrapper serviceWrapper) { + private ChromeBluetoothRemoteGattService(long nativeBluetoothRemoteGattServiceAndroid, + Wrappers.BluetoothGattServiceWrapper serviceWrapper) { + mNativeBluetoothRemoteGattServiceAndroid = nativeBluetoothRemoteGattServiceAndroid; mService = serviceWrapper; Log.v(TAG, "ChromeBluetoothRemoteGattService created."); } + /** + * Handles C++ object being destroyed. + */ + @CalledByNative + private void onBluetoothRemoteGattServiceAndroidDestruction() { + mNativeBluetoothRemoteGattServiceAndroid = 0; + } + // --------------------------------------------------------------------------------------------- // BluetoothRemoteGattServiceAndroid methods implemented in java: @@ -33,8 +46,9 @@ final class ChromeBluetoothRemoteGattService { // 'Object' type must be used because inner class Wrappers.BluetoothGattServiceWrapper reference // is not handled by jni_generator.py JavaToJni. http://crbug.com/505554 @CalledByNative - private static ChromeBluetoothRemoteGattService create(Object serviceWrapper) { - return new ChromeBluetoothRemoteGattService( + private static ChromeBluetoothRemoteGattService create( + long nativeBluetoothRemoteGattServiceAndroid, Object serviceWrapper) { + return new ChromeBluetoothRemoteGattService(nativeBluetoothRemoteGattServiceAndroid, (Wrappers.BluetoothGattServiceWrapper) serviceWrapper); } @@ -43,4 +57,31 @@ final class ChromeBluetoothRemoteGattService { private String getUUID() { return mService.getUuid().toString(); } + + // Implements BluetoothRemoteGattServiceAndroid::EnsureCharacteristicsCreated + @CalledByNative + private void ensureCharacteristicsCreated() { + List<Wrappers.BluetoothGattCharacteristicWrapper> characteristics = + mService.getCharacteristics(); + for (Wrappers.BluetoothGattCharacteristicWrapper characteristic : characteristics) { + // Create a unique characteristic ID. getInstanceId only differs between characteristic + // instances with the same UUID. + // TODO(scheib): Make instance IDs unique to the whole adapter. http://crbug.com/546747 + String characteristicInstanceId = + characteristic.getUuid().toString() + characteristic.getInstanceId(); + nativeCreateGattRemoteCharacteristic(mNativeBluetoothRemoteGattServiceAndroid, + characteristicInstanceId, characteristic); + } + } + + // --------------------------------------------------------------------------------------------- + // BluetoothAdapterDevice C++ methods declared for access from java: + // Binds to BluetoothRemoteGattServiceAndroid::CreateGattRemoteCharacteristic. + // 'Object' type must be used for |bluetoothGattCarachteristicWrapper| because inner class + // Wrappers.BluetoothGattCharacteristicWrapper reference is not handled by jni_generator.py + // JavaToJni. + // http://crbug.com/505554 + private native void nativeCreateGattRemoteCharacteristic( + long nativeBluetoothRemoteGattServiceAndroid, String instanceId, + Object bluetoothGattCarachteristicWrapper); } diff --git a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java index 9f4d35f..9bfaeda 100644 --- a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java +++ b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java @@ -10,6 +10,7 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCallback; +import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattService; import android.bluetooth.le.BluetoothLeScanner; import android.bluetooth.le.ScanCallback; @@ -331,6 +332,16 @@ class Wrappers { mService = service; } + public List<BluetoothGattCharacteristicWrapper> getCharacteristics() { + List<BluetoothGattCharacteristic> characteristics = mService.getCharacteristics(); + ArrayList<BluetoothGattCharacteristicWrapper> characteristicsWrapped = + new ArrayList<BluetoothGattCharacteristicWrapper>(characteristics.size()); + for (BluetoothGattCharacteristic characteristic : characteristics) { + characteristicsWrapped.add(new BluetoothGattCharacteristicWrapper(characteristic)); + } + return characteristicsWrapped; + } + public int getInstanceId() { return mService.getInstanceId(); } @@ -339,4 +350,23 @@ class Wrappers { return mService.getUuid(); } } + + /** + * Wraps android.bluetooth.BluetoothGattCharacteristic. + */ + static class BluetoothGattCharacteristicWrapper { + private final BluetoothGattCharacteristic mCharacteristic; + + public BluetoothGattCharacteristicWrapper(BluetoothGattCharacteristic characteristic) { + mCharacteristic = characteristic; + } + + public int getInstanceId() { + return mCharacteristic.getInstanceId(); + } + + public UUID getUuid() { + return mCharacteristic.getUuid(); + } + } } diff --git a/device/bluetooth/bluetooth.gyp b/device/bluetooth/bluetooth.gyp index f99d017..e9fa47c 100644 --- a/device/bluetooth/bluetooth.gyp +++ b/device/bluetooth/bluetooth.gyp @@ -101,6 +101,8 @@ 'bluetooth_low_energy_win.h', 'bluetooth_pairing_chromeos.cc', 'bluetooth_pairing_chromeos.h', + 'bluetooth_remote_gatt_characteristic_android.cc', + 'bluetooth_remote_gatt_characteristic_android.h', 'bluetooth_remote_gatt_characteristic_chromeos.cc', 'bluetooth_remote_gatt_characteristic_chromeos.h', 'bluetooth_remote_gatt_descriptor_chromeos.cc', diff --git a/device/bluetooth/bluetooth_device_android.h b/device/bluetooth/bluetooth_device_android.h index bed6780..2dc96c5 100644 --- a/device/bluetooth/bluetooth_device_android.h +++ b/device/bluetooth/bluetooth_device_android.h @@ -12,7 +12,7 @@ namespace device { -// BluetoothDeviceAndroid along with the Java class +// BluetoothDeviceAndroid along with its owned Java class // org.chromium.device.bluetooth.ChromeBluetoothDevice implement // BluetoothDevice. class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceAndroid final diff --git a/device/bluetooth/bluetooth_gatt_service_unittest.cc b/device/bluetooth/bluetooth_gatt_service_unittest.cc index c6b8733..595905d 100644 --- a/device/bluetooth/bluetooth_gatt_service_unittest.cc +++ b/device/bluetooth/bluetooth_gatt_service_unittest.cc @@ -4,6 +4,7 @@ #include "device/bluetooth/bluetooth_gatt_service.h" +#include "device/bluetooth/bluetooth_remote_gatt_characteristic_android.h" #include "testing/gtest/include/gtest/gtest.h" #if defined(OS_ANDROID) @@ -21,9 +22,7 @@ TEST_F(BluetoothTest, GetUUIDAndGetIdentifier) { BluetoothDevice* device = DiscoverLowEnergyDevice(3); device->CreateGattConnection(GetGattConnectionCallback(), GetConnectErrorCallback()); - ResetEventCounts(); SimulateGattConnection(device); - EXPECT_EQ(1, gatt_discovery_attempts_); // Create multiple instances with the same UUID. BluetoothUUID uuid("00000000-0000-1000-8000-00805f9b34fb"); @@ -42,4 +41,61 @@ TEST_F(BluetoothTest, GetUUIDAndGetIdentifier) { } #endif // defined(OS_ANDROID) +#if defined(OS_ANDROID) +TEST_F(BluetoothTest, GetCharacteristics_FindNone) { + InitWithFakeAdapter(); + StartLowEnergyDiscoverySession(); + BluetoothDevice* device = DiscoverLowEnergyDevice(3); + device->CreateGattConnection(GetGattConnectionCallback(), + GetConnectErrorCallback()); + SimulateGattConnection(device); + + // Simulate a service, with no Characteristics: + std::vector<std::string> services; + services.push_back("00000000-0000-1000-8000-00805f9b34fb"); + SimulateGattServicesDiscovered(device, services); + BluetoothGattService* service = device->GetGattServices()[0]; + + EXPECT_EQ(0u, service->GetCharacteristics().size()); +} +#endif // defined(OS_ANDROID) + +#if defined(OS_ANDROID) +TEST_F(BluetoothTest, GetCharacteristic_FindSeveral) { + InitWithFakeAdapter(); + StartLowEnergyDiscoverySession(); + BluetoothDevice* device = DiscoverLowEnergyDevice(3); + device->CreateGattConnection(GetGattConnectionCallback(), + GetConnectErrorCallback()); + SimulateGattConnection(device); + + // Simulate a service, with no Characteristics: + std::vector<std::string> services; + services.push_back("00000000-0000-1000-8000-00805f9b34fb"); + SimulateGattServicesDiscovered(device, services); + BluetoothGattService* service = device->GetGattServices()[0]; + + std::string characteristic_uuid1 = "00000001-0000-1000-8000-00805f9b34fb"; + std::string characteristic_uuid2 = "00000002-0000-1000-8000-00805f9b34fb"; + std::string characteristic_uuid3 = characteristic_uuid2; // Duplicate UUID. + SimulateGattCharacteristic(service, characteristic_uuid1); + SimulateGattCharacteristic(service, characteristic_uuid2); + SimulateGattCharacteristic(service, characteristic_uuid3); + + EXPECT_EQ(3u, service->GetCharacteristics().size()); + // TODO(scheib): Implement GetIdentifier. crbug.com/545682 + // std::string characteristic_id1 = + // service->GetCharacteristics()[0]->GetIdentifier(); + // ... + // EXPECT_NE(characteristic_id2, characteristic_id3); + // For now, just hard-code: + std::string characteristic_id1 = "00000001-0000-1000-8000-00805f9b34fb0"; + std::string characteristic_id2 = "00000002-0000-1000-8000-00805f9b34fb0"; + std::string characteristic_id3 = "00000002-0000-1000-8000-00805f9b34fb1"; + EXPECT_TRUE(service->GetCharacteristic(characteristic_id1)); + EXPECT_TRUE(service->GetCharacteristic(characteristic_id2)); + EXPECT_TRUE(service->GetCharacteristic(characteristic_id3)); +} +#endif // defined(OS_ANDROID) + } // namespace device diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_android.cc b/device/bluetooth/bluetooth_remote_gatt_characteristic_android.cc new file mode 100644 index 0000000..1c2a99a --- /dev/null +++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_android.cc @@ -0,0 +1,111 @@ +// 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 "device/bluetooth/bluetooth_remote_gatt_characteristic_android.h" + +#include "base/logging.h" + +namespace device { + +// static +scoped_ptr<BluetoothRemoteGattCharacteristicAndroid> +BluetoothRemoteGattCharacteristicAndroid::Create() { + return make_scoped_ptr<BluetoothRemoteGattCharacteristicAndroid>( + new BluetoothRemoteGattCharacteristicAndroid()); +} + +BluetoothRemoteGattCharacteristicAndroid:: + ~BluetoothRemoteGattCharacteristicAndroid() {} + +std::string BluetoothRemoteGattCharacteristicAndroid::GetIdentifier() const { + NOTIMPLEMENTED(); + return ""; +} + +BluetoothUUID BluetoothRemoteGattCharacteristicAndroid::GetUUID() const { + NOTIMPLEMENTED(); + return BluetoothUUID(); +} + +bool BluetoothRemoteGattCharacteristicAndroid::IsLocal() const { + return false; +} + +const std::vector<uint8>& BluetoothRemoteGattCharacteristicAndroid::GetValue() + const { + NOTIMPLEMENTED(); + return value_; +} + +BluetoothGattService* BluetoothRemoteGattCharacteristicAndroid::GetService() + const { + NOTIMPLEMENTED(); + return nullptr; +} + +BluetoothGattCharacteristic::Properties +BluetoothRemoteGattCharacteristicAndroid::GetProperties() const { + NOTIMPLEMENTED(); + return 0; +} + +BluetoothGattCharacteristic::Permissions +BluetoothRemoteGattCharacteristicAndroid::GetPermissions() const { + NOTIMPLEMENTED(); + return 0; +} + +bool BluetoothRemoteGattCharacteristicAndroid::IsNotifying() const { + NOTIMPLEMENTED(); + return false; +} + +std::vector<BluetoothGattDescriptor*> +BluetoothRemoteGattCharacteristicAndroid::GetDescriptors() const { + NOTIMPLEMENTED(); + return std::vector<BluetoothGattDescriptor*>(); +} + +BluetoothGattDescriptor* +BluetoothRemoteGattCharacteristicAndroid::GetDescriptor( + const std::string& identifier) const { + NOTIMPLEMENTED(); + return nullptr; +} + +bool BluetoothRemoteGattCharacteristicAndroid::AddDescriptor( + BluetoothGattDescriptor* descriptor) { + NOTIMPLEMENTED(); + return false; +} + +bool BluetoothRemoteGattCharacteristicAndroid::UpdateValue( + const std::vector<uint8>& value) { + NOTIMPLEMENTED(); + return false; +} + +void BluetoothRemoteGattCharacteristicAndroid::StartNotifySession( + const NotifySessionCallback& callback, + const ErrorCallback& error_callback) { + NOTIMPLEMENTED(); +} + +void BluetoothRemoteGattCharacteristicAndroid::ReadRemoteCharacteristic( + const ValueCallback& callback, + const ErrorCallback& error_callback) { + NOTIMPLEMENTED(); +} + +void BluetoothRemoteGattCharacteristicAndroid::WriteRemoteCharacteristic( + const std::vector<uint8>& new_value, + const base::Closure& callback, + const ErrorCallback& error_callback) { + NOTIMPLEMENTED(); +} + +BluetoothRemoteGattCharacteristicAndroid:: + BluetoothRemoteGattCharacteristicAndroid() {} + +} // namespace device diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_android.h b/device/bluetooth/bluetooth_remote_gatt_characteristic_android.h new file mode 100644 index 0000000..58e139d --- /dev/null +++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_android.h @@ -0,0 +1,63 @@ +// 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. + +#ifndef DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_CHARACTERISTIC_ANDROID_H_ +#define DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_CHARACTERISTIC_ANDROID_H_ + +#include "base/macros.h" +#include "device/bluetooth/bluetooth_gatt_characteristic.h" + +namespace device { + +// BluetoothRemoteGattCharacteristicAndroid along with its owned Java class +// org.chromium.device.bluetooth.ChromeBluetoothRemoteGattCharacteristic +// implement BluetootGattCharacteristic. +class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattCharacteristicAndroid + : public BluetoothGattCharacteristic { + public: + // Create a BluetoothRemoteGattServiceAndroid instance and associated Java + // ChromeBluetoothRemoteGattService using the provided + // |bluetooth_remote_gatt_service_wrapper|. + // + // The ChromeBluetoothRemoteGattService instance will hold a Java reference + // to |bluetooth_remote_gatt_service_wrapper|. + // + // TODO(scheib): Actually create the Java object. crbug.com/545682 + static scoped_ptr<BluetoothRemoteGattCharacteristicAndroid> Create(); + + ~BluetoothRemoteGattCharacteristicAndroid() override; + + // BluetoothGattCharacteristic interface: + std::string GetIdentifier() const override; + BluetoothUUID GetUUID() const override; + bool IsLocal() const override; + const std::vector<uint8>& GetValue() const override; + BluetoothGattService* GetService() const override; + Properties GetProperties() const override; + Permissions GetPermissions() const override; + bool IsNotifying() const override; + std::vector<BluetoothGattDescriptor*> GetDescriptors() const override; + BluetoothGattDescriptor* GetDescriptor( + const std::string& identifier) const override; + bool AddDescriptor(BluetoothGattDescriptor* descriptor) override; + bool UpdateValue(const std::vector<uint8>& value) override; + void StartNotifySession(const NotifySessionCallback& callback, + const ErrorCallback& error_callback) override; + void ReadRemoteCharacteristic(const ValueCallback& callback, + const ErrorCallback& error_callback) override; + void WriteRemoteCharacteristic(const std::vector<uint8>& new_value, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + + private: + BluetoothRemoteGattCharacteristicAndroid(); + + std::vector<uint8> value_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothRemoteGattCharacteristicAndroid); +}; + +} // namespace device + +#endif // DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_CHARACTERISTIC_ANDROID_H_ diff --git a/device/bluetooth/bluetooth_remote_gatt_service_android.cc b/device/bluetooth/bluetooth_remote_gatt_service_android.cc index c9caa3a..b5bc1a5 100644 --- a/device/bluetooth/bluetooth_remote_gatt_service_android.cc +++ b/device/bluetooth/bluetooth_remote_gatt_service_android.cc @@ -8,6 +8,7 @@ #include "base/android/jni_string.h" #include "device/bluetooth/bluetooth_adapter_android.h" #include "device/bluetooth/bluetooth_device_android.h" +#include "device/bluetooth/bluetooth_remote_gatt_characteristic_android.h" #include "jni/ChromeBluetoothRemoteGattService_jni.h" using base::android::AttachCurrentThread; @@ -24,7 +25,8 @@ BluetoothRemoteGattServiceAndroid* BluetoothRemoteGattServiceAndroid::Create( new BluetoothRemoteGattServiceAndroid(adapter, device, instanceId); service->j_service_.Reset(Java_ChromeBluetoothRemoteGattService_create( - AttachCurrentThread(), bluetooth_remote_gatt_service_wrapper)); + AttachCurrentThread(), reinterpret_cast<intptr_t>(service), + bluetooth_remote_gatt_service_wrapper)); return service; } @@ -35,6 +37,11 @@ bool BluetoothRemoteGattServiceAndroid::RegisterJNI(JNIEnv* env) { env); // Generated in ChromeBluetoothRemoteGattService_jni.h } +base::android::ScopedJavaLocalRef<jobject> +BluetoothRemoteGattServiceAndroid::GetJavaObject() { + return base::android::ScopedJavaLocalRef<jobject>(j_service_); +} + std::string BluetoothRemoteGattServiceAndroid::GetIdentifier() const { return instanceId_; } @@ -60,8 +67,10 @@ device::BluetoothDevice* BluetoothRemoteGattServiceAndroid::GetDevice() const { std::vector<device::BluetoothGattCharacteristic*> BluetoothRemoteGattServiceAndroid::GetCharacteristics() const { - NOTIMPLEMENTED(); + EnsureCharacteristicsCreated(); std::vector<device::BluetoothGattCharacteristic*> characteristics; + for (const auto& map_iter : characteristics_) + characteristics.push_back(map_iter.second); return characteristics; } @@ -74,8 +83,11 @@ BluetoothRemoteGattServiceAndroid::GetIncludedServices() const { device::BluetoothGattCharacteristic* BluetoothRemoteGattServiceAndroid::GetCharacteristic( const std::string& identifier) const { - NOTIMPLEMENTED(); - return nullptr; + EnsureCharacteristicsCreated(); + const auto& iter = characteristics_.find(identifier); + if (iter == characteristics_.end()) + return nullptr; + return iter->second; } bool BluetoothRemoteGattServiceAndroid::AddCharacteristic( @@ -100,12 +112,39 @@ void BluetoothRemoteGattServiceAndroid::Unregister( error_callback.Run(); } +void BluetoothRemoteGattServiceAndroid::CreateGattRemoteCharacteristic( + JNIEnv* env, + jobject caller, + const jstring& instanceId, + jobject /* BluetoothGattCharacteristicWrapper */ + bluetooth_gatt_characteristic_wrapper) { + std::string instanceIdString = + base::android::ConvertJavaStringToUTF8(env, instanceId); + + DCHECK(!characteristics_.contains(instanceIdString)); + + characteristics_.set(instanceIdString, + BluetoothRemoteGattCharacteristicAndroid::Create()); +} + BluetoothRemoteGattServiceAndroid::BluetoothRemoteGattServiceAndroid( BluetoothAdapterAndroid* adapter, BluetoothDeviceAndroid* device, std::string instanceId) : adapter_(adapter), device_(device), instanceId_(instanceId) {} -BluetoothRemoteGattServiceAndroid::~BluetoothRemoteGattServiceAndroid() {} +BluetoothRemoteGattServiceAndroid::~BluetoothRemoteGattServiceAndroid() { + Java_ChromeBluetoothRemoteGattService_onBluetoothRemoteGattServiceAndroidDestruction( + AttachCurrentThread(), j_service_.obj()); +} + +void BluetoothRemoteGattServiceAndroid::EnsureCharacteristicsCreated() const { + if (!characteristics_.empty()) + return; + + // Java call + Java_ChromeBluetoothRemoteGattService_ensureCharacteristicsCreated( + AttachCurrentThread(), j_service_.obj()); +} } // namespace device diff --git a/device/bluetooth/bluetooth_remote_gatt_service_android.h b/device/bluetooth/bluetooth_remote_gatt_service_android.h index 5bc9e3d..b1d19e0 100644 --- a/device/bluetooth/bluetooth_remote_gatt_service_android.h +++ b/device/bluetooth/bluetooth_remote_gatt_service_android.h @@ -10,20 +10,21 @@ #include <vector> #include "base/android/jni_android.h" +#include "base/containers/scoped_ptr_hash_map.h" #include "device/bluetooth/bluetooth_gatt_service.h" #include "device/bluetooth/bluetooth_uuid.h" namespace device { -class BluetoothAdapter; -class BluetoothGattCharacteristic; - class BluetoothAdapterAndroid; class BluetoothDeviceAndroid; +class BluetoothRemoteGattCharacteristicAndroid; -// The BluetoothRemoteGattServiceAndroid class implements BluetootGattService -// for remote GATT services on Android. -class BluetoothRemoteGattServiceAndroid : public device::BluetoothGattService { +// BluetoothRemoteGattServiceAndroid along with its owned Java class +// org.chromium.device.bluetooth.ChromeBluetoothRemoteGattService implement +// BluetoothGattService. +class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattServiceAndroid + : public device::BluetoothGattService { public: // Create a BluetoothRemoteGattServiceAndroid instance and associated Java // ChromeBluetoothRemoteGattService using the provided @@ -44,6 +45,9 @@ class BluetoothRemoteGattServiceAndroid : public device::BluetoothGattService { // Register C++ methods exposed to Java using JNI. static bool RegisterJNI(JNIEnv* env); + // Returns the associated ChromeBluetoothRemoteGattService Java object. + base::android::ScopedJavaLocalRef<jobject> GetJavaObject(); + // device::BluetoothGattService overrides. std::string GetIdentifier() const override; device::BluetoothUUID GetUUID() const override; @@ -64,6 +68,15 @@ class BluetoothRemoteGattServiceAndroid : public device::BluetoothGattService { void Unregister(const base::Closure& callback, const ErrorCallback& error_callback) override; + // Creates a Bluetooth GATT characteristic object and adds it to + // |characteristics_| if it is not already there. + void CreateGattRemoteCharacteristic( + JNIEnv* env, + jobject caller, + const jstring& instanceId, + jobject /* BluetoothGattCharacteristicWrapper */ + bluetooth_gatt_characteristic_wrapper); + private: friend class BluetoothDeviceAndroid; @@ -72,6 +85,9 @@ class BluetoothRemoteGattServiceAndroid : public device::BluetoothGattService { std::string instanceId); ~BluetoothRemoteGattServiceAndroid() override; + // Populates |characteristics_| from Java objects if necessary. + void EnsureCharacteristicsCreated() const; + // Java object org.chromium.device.bluetooth.ChromeBluetoothRemoteGattService. base::android::ScopedJavaGlobalRef<jobject> j_service_; @@ -86,9 +102,14 @@ class BluetoothRemoteGattServiceAndroid : public device::BluetoothGattService { // Instance ID, cached from Android object. std::string instanceId_; + // Map of characteristics, keyed by characteristic identifier. + base::ScopedPtrHashMap<std::string, + scoped_ptr<BluetoothRemoteGattCharacteristicAndroid>> + characteristics_; + DISALLOW_COPY_AND_ASSIGN(BluetoothRemoteGattServiceAndroid); }; -} // namespace android +} // namespace device #endif // DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_SERVICE_ANDROID_H_ diff --git a/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java b/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java index 2499c7b..7bf77c8 100644 --- a/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java +++ b/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java @@ -305,11 +305,65 @@ class Fakes { static class FakeBluetoothGattService extends Wrappers.BluetoothGattServiceWrapper { final int mInstanceId; final UUID mUuid; + final ArrayList<Wrappers.BluetoothGattCharacteristicWrapper> mCharacteristics; public FakeBluetoothGattService(UUID uuid, int instanceId) { super(null); mUuid = uuid; mInstanceId = instanceId; + mCharacteristics = new ArrayList<Wrappers.BluetoothGattCharacteristicWrapper>(); + } + + // Create a characteristic and add it to this service. + @CalledByNative("FakeBluetoothGattService") + private static void addCharacteristic( + ChromeBluetoothRemoteGattService chromeService, String uuidString) { + FakeBluetoothGattService fakeService = + (FakeBluetoothGattService) chromeService.mService; + UUID uuid = UUID.fromString(uuidString); + + int countOfDuplicateUUID = 0; + for (Wrappers.BluetoothGattCharacteristicWrapper characteristic : + fakeService.mCharacteristics) { + if (characteristic.getUuid().equals(uuid)) { + countOfDuplicateUUID++; + } + } + fakeService.mCharacteristics.add(new FakeBluetoothGattCharacteristic( + uuid, /* instanceId */ countOfDuplicateUUID)); + } + + // ----------------------------------------------------------------------------------------- + // Wrappers.BluetoothGattServiceWrapper overrides: + + @Override + public List<Wrappers.BluetoothGattCharacteristicWrapper> getCharacteristics() { + return mCharacteristics; + } + + @Override + public int getInstanceId() { + return mInstanceId; + } + + @Override + public UUID getUuid() { + return mUuid; + } + } + + /** + * Fakes android.bluetooth.BluetoothGattCharacteristic. + */ + static class FakeBluetoothGattCharacteristic + extends Wrappers.BluetoothGattCharacteristicWrapper { + final UUID mUuid; + final int mInstanceId; + + public FakeBluetoothGattCharacteristic(UUID uuid, int instanceId) { + super(null); + mUuid = uuid; + mInstanceId = instanceId; } @Override diff --git a/device/bluetooth/test/bluetooth_test.h b/device/bluetooth/test/bluetooth_test.h index 6271313..fa946a3 100644 --- a/device/bluetooth/test/bluetooth_test.h +++ b/device/bluetooth/test/bluetooth_test.h @@ -94,6 +94,9 @@ class BluetoothTestBase : public testing::Test { // Simulates failure to discover services. virtual void SimulateGattServicesDiscoveryError(BluetoothDevice* device) {} + virtual void SimulateGattCharacteristic(BluetoothGattService* service, + const std::string& uuid){}; + // Remove the device from the adapter and delete it. virtual void DeleteDevice(BluetoothDevice* device); diff --git a/device/bluetooth/test/bluetooth_test_android.cc b/device/bluetooth/test/bluetooth_test_android.cc index 48c2ab2..7761f56 100644 --- a/device/bluetooth/test/bluetooth_test_android.cc +++ b/device/bluetooth/test/bluetooth_test_android.cc @@ -12,6 +12,7 @@ #include "device/bluetooth/android/wrappers.h" #include "device/bluetooth/bluetooth_adapter_android.h" #include "device/bluetooth/bluetooth_device_android.h" +#include "device/bluetooth/bluetooth_remote_gatt_service_android.h" #include "device/bluetooth/test/test_bluetooth_adapter_observer.h" #include "jni/Fakes_jni.h" @@ -140,6 +141,18 @@ void BluetoothTestAndroid::SimulateGattServicesDiscoveryError( nullptr); } +void BluetoothTestAndroid::SimulateGattCharacteristic( + BluetoothGattService* service, + const std::string& uuid) { + BluetoothRemoteGattServiceAndroid* service_android = + static_cast<BluetoothRemoteGattServiceAndroid*>(service); + JNIEnv* env = base::android::AttachCurrentThread(); + + Java_FakeBluetoothGattService_addCharacteristic( + env, service_android->GetJavaObject().obj(), + base::android::ConvertUTF8ToJavaString(env, uuid).obj()); +} + void BluetoothTestAndroid::OnFakeBluetoothDeviceConnectGattCalled( JNIEnv* env, jobject caller) { diff --git a/device/bluetooth/test/bluetooth_test_android.h b/device/bluetooth/test/bluetooth_test_android.h index 306d81a..beb5e2b 100644 --- a/device/bluetooth/test/bluetooth_test_android.h +++ b/device/bluetooth/test/bluetooth_test_android.h @@ -35,6 +35,8 @@ class BluetoothTestAndroid : public BluetoothTestBase { BluetoothDevice* device, const std::vector<std::string>& uuids) override; void SimulateGattServicesDiscoveryError(BluetoothDevice* device) override; + void SimulateGattCharacteristic(BluetoothGattService* service, + const std::string& uuid) override; // Records that Java FakeBluetoothDevice connectGatt was called. void OnFakeBluetoothDeviceConnectGattCalled(JNIEnv* env, jobject caller); |