1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "device/bluetooth/bluetooth_remote_gatt_service_android.h"
6 
7 #include <memory>
8 
9 #include "base/android/jni_android.h"
10 #include "base/android/jni_string.h"
11 #include "base/stl_util.h"
12 #include "device/bluetooth/bluetooth_adapter_android.h"
13 #include "device/bluetooth/bluetooth_device_android.h"
14 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_android.h"
15 #include "device/bluetooth/jni_headers/ChromeBluetoothRemoteGattService_jni.h"
16 
17 using base::android::AttachCurrentThread;
18 using base::android::JavaParamRef;
19 using base::android::JavaRef;
20 
21 namespace device {
22 
23 // static
24 std::unique_ptr<BluetoothRemoteGattServiceAndroid>
Create(BluetoothAdapterAndroid * adapter,BluetoothDeviceAndroid * device,const JavaRef<jobject> & bluetooth_gatt_service_wrapper,const std::string & instance_id,const JavaRef<jobject> & chrome_bluetooth_device)25 BluetoothRemoteGattServiceAndroid::Create(
26     BluetoothAdapterAndroid* adapter,
27     BluetoothDeviceAndroid* device,
28     const JavaRef<jobject>&
29         bluetooth_gatt_service_wrapper,  // BluetoothGattServiceWrapper
30     const std::string& instance_id,
31     const JavaRef<jobject>& chrome_bluetooth_device) {  // ChromeBluetoothDevice
32   std::unique_ptr<BluetoothRemoteGattServiceAndroid> service(
33       new BluetoothRemoteGattServiceAndroid(adapter, device, instance_id));
34 
35   JNIEnv* env = AttachCurrentThread();
36   service->j_service_.Reset(Java_ChromeBluetoothRemoteGattService_create(
37       env, reinterpret_cast<intptr_t>(service.get()),
38       bluetooth_gatt_service_wrapper,
39       base::android::ConvertUTF8ToJavaString(env, instance_id),
40       chrome_bluetooth_device));
41 
42   return service;
43 }
44 
~BluetoothRemoteGattServiceAndroid()45 BluetoothRemoteGattServiceAndroid::~BluetoothRemoteGattServiceAndroid() {
46   Java_ChromeBluetoothRemoteGattService_onBluetoothRemoteGattServiceAndroidDestruction(
47       AttachCurrentThread(), j_service_);
48 }
49 
50 base::android::ScopedJavaLocalRef<jobject>
GetJavaObject()51 BluetoothRemoteGattServiceAndroid::GetJavaObject() {
52   return base::android::ScopedJavaLocalRef<jobject>(j_service_);
53 }
54 
55 // static
56 BluetoothRemoteGattService::GattErrorCode
GetGattErrorCode(int bluetooth_gatt_code)57 BluetoothRemoteGattServiceAndroid::GetGattErrorCode(int bluetooth_gatt_code) {
58   DCHECK(bluetooth_gatt_code != 0) << "Only errors valid. 0 == GATT_SUCCESS.";
59 
60   // TODO(scheib) Create new BluetoothRemoteGattService::GattErrorCode enums for
61   // android values not yet represented. http://crbug.com/548498
62   switch (bluetooth_gatt_code) {  // android.bluetooth.BluetoothGatt values:
63     case 0x00000101:              // GATT_FAILURE
64       return GATT_ERROR_FAILED;
65     case 0x0000000d:  // GATT_INVALID_ATTRIBUTE_LENGTH
66       return GATT_ERROR_INVALID_LENGTH;
67     case 0x00000002:  // GATT_READ_NOT_PERMITTED
68       return GATT_ERROR_NOT_PERMITTED;
69     case 0x00000006:  // GATT_REQUEST_NOT_SUPPORTED
70       return GATT_ERROR_NOT_SUPPORTED;
71     case 0x00000003:  // GATT_WRITE_NOT_PERMITTED
72       return GATT_ERROR_NOT_PERMITTED;
73     default:
74       DVLOG(1) << "Unhandled status: " << bluetooth_gatt_code;
75       return BluetoothRemoteGattService::GATT_ERROR_UNKNOWN;
76   }
77 }
78 
79 // static
GetAndroidErrorCode(BluetoothRemoteGattService::GattErrorCode error_code)80 int BluetoothRemoteGattServiceAndroid::GetAndroidErrorCode(
81     BluetoothRemoteGattService::GattErrorCode error_code) {
82   // TODO(scheib) Create new BluetoothRemoteGattService::GattErrorCode enums for
83   // android values not yet represented. http://crbug.com/548498
84   switch (error_code) {  // Return values from android.bluetooth.BluetoothGatt:
85     case GATT_ERROR_UNKNOWN:
86       return 0x00000101;  // GATT_FAILURE. No good match.
87     case GATT_ERROR_FAILED:
88       return 0x00000101;  // GATT_FAILURE
89     case GATT_ERROR_IN_PROGRESS:
90       return 0x00000101;  // GATT_FAILURE. No good match.
91     case GATT_ERROR_INVALID_LENGTH:
92       return 0x0000000d;  // GATT_INVALID_ATTRIBUTE_LENGTH
93     case GATT_ERROR_NOT_PERMITTED:
94       // Can't distinguish between:
95       // 0x00000002:  // GATT_READ_NOT_PERMITTED
96       // 0x00000003:  // GATT_WRITE_NOT_PERMITTED
97       return 0x00000101;  // GATT_FAILURE. No good match.
98     case GATT_ERROR_NOT_AUTHORIZED:
99       return 0x00000101;  // GATT_FAILURE. No good match.
100     case GATT_ERROR_NOT_PAIRED:
101       return 0x00000101;  // GATT_FAILURE. No good match.
102     case GATT_ERROR_NOT_SUPPORTED:
103       return 0x00000006;  // GATT_REQUEST_NOT_SUPPORTED
104   }
105   DVLOG(1) << "Unhandled error_code: " << error_code;
106   return 0x00000101;  // GATT_FAILURE. No good match.
107 }
108 
GetIdentifier() const109 std::string BluetoothRemoteGattServiceAndroid::GetIdentifier() const {
110   return instance_id_;
111 }
112 
GetUUID() const113 device::BluetoothUUID BluetoothRemoteGattServiceAndroid::GetUUID() const {
114   return device::BluetoothUUID(
115       ConvertJavaStringToUTF8(Java_ChromeBluetoothRemoteGattService_getUUID(
116           AttachCurrentThread(), j_service_)));
117 }
118 
IsPrimary() const119 bool BluetoothRemoteGattServiceAndroid::IsPrimary() const {
120   NOTIMPLEMENTED();
121   return true;
122 }
123 
GetDevice() const124 device::BluetoothDevice* BluetoothRemoteGattServiceAndroid::GetDevice() const {
125   return device_;
126 }
127 
128 std::vector<device::BluetoothRemoteGattCharacteristic*>
GetCharacteristics() const129 BluetoothRemoteGattServiceAndroid::GetCharacteristics() const {
130   EnsureCharacteristicsCreated();
131   return BluetoothRemoteGattService::GetCharacteristics();
132 }
133 
134 std::vector<device::BluetoothRemoteGattService*>
GetIncludedServices() const135 BluetoothRemoteGattServiceAndroid::GetIncludedServices() const {
136   NOTIMPLEMENTED();
137   return std::vector<device::BluetoothRemoteGattService*>();
138 }
139 
140 device::BluetoothRemoteGattCharacteristic*
GetCharacteristic(const std::string & identifier) const141 BluetoothRemoteGattServiceAndroid::GetCharacteristic(
142     const std::string& identifier) const {
143   EnsureCharacteristicsCreated();
144   return BluetoothRemoteGattService::GetCharacteristic(identifier);
145 }
146 
147 std::vector<BluetoothRemoteGattCharacteristic*>
GetCharacteristicsByUUID(const BluetoothUUID & characteristic_uuid) const148 BluetoothRemoteGattServiceAndroid::GetCharacteristicsByUUID(
149     const BluetoothUUID& characteristic_uuid) const {
150   EnsureCharacteristicsCreated();
151   return BluetoothRemoteGattService::GetCharacteristicsByUUID(
152       characteristic_uuid);
153 }
154 
IsDiscoveryComplete() const155 bool BluetoothRemoteGattServiceAndroid::IsDiscoveryComplete() const {
156   // Not used on Android, because Android sends an event when service discovery
157   // is complete for the entire device.
158   NOTIMPLEMENTED();
159   return true;
160 }
161 
SetDiscoveryComplete(bool complete)162 void BluetoothRemoteGattServiceAndroid::SetDiscoveryComplete(bool complete) {
163   // Not used on Android, because Android sends an event when service discovery
164   // is complete for the entire device.
165   NOTIMPLEMENTED();
166 }
167 
CreateGattRemoteCharacteristic(JNIEnv * env,const JavaParamRef<jobject> & caller,const JavaParamRef<jstring> & instance_id,const JavaParamRef<jobject> & bluetooth_gatt_characteristic_wrapper,const JavaParamRef<jobject> & chrome_bluetooth_device)168 void BluetoothRemoteGattServiceAndroid::CreateGattRemoteCharacteristic(
169     JNIEnv* env,
170     const JavaParamRef<jobject>& caller,
171     const JavaParamRef<jstring>& instance_id,
172     const JavaParamRef<jobject>& /* BluetoothGattCharacteristicWrapper */
173         bluetooth_gatt_characteristic_wrapper,
174     const JavaParamRef<jobject>& /* ChromeBluetoothDevice */
175         chrome_bluetooth_device) {
176   std::string instance_id_string =
177       base::android::ConvertJavaStringToUTF8(env, instance_id);
178 
179   DCHECK(!base::Contains(characteristics_, instance_id_string));
180   AddCharacteristic(BluetoothRemoteGattCharacteristicAndroid::Create(
181       adapter_, this, instance_id_string, bluetooth_gatt_characteristic_wrapper,
182       chrome_bluetooth_device));
183 }
184 
BluetoothRemoteGattServiceAndroid(BluetoothAdapterAndroid * adapter,BluetoothDeviceAndroid * device,const std::string & instance_id)185 BluetoothRemoteGattServiceAndroid::BluetoothRemoteGattServiceAndroid(
186     BluetoothAdapterAndroid* adapter,
187     BluetoothDeviceAndroid* device,
188     const std::string& instance_id)
189     : adapter_(adapter), device_(device), instance_id_(instance_id) {}
190 
EnsureCharacteristicsCreated() const191 void BluetoothRemoteGattServiceAndroid::EnsureCharacteristicsCreated() const {
192   if (!characteristics_.empty())
193     return;
194 
195   // Java call
196   Java_ChromeBluetoothRemoteGattService_createCharacteristics(
197       AttachCurrentThread(), j_service_);
198 }
199 
200 }  // namespace device
201