OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "device/bluetooth/bluetooth_adapter_android.h" | 5 #include "device/bluetooth/bluetooth_adapter_android.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "base/android/jni_android.h" | 9 #include "base/android/jni_android.h" |
10 #include "base/android/jni_string.h" | 10 #include "base/android/jni_string.h" |
| 11 #include "base/bind.h" |
| 12 #include "base/location.h" |
11 #include "base/sequenced_task_runner.h" | 13 #include "base/sequenced_task_runner.h" |
12 #include "base/single_thread_task_runner.h" | 14 #include "base/single_thread_task_runner.h" |
13 #include "base/threading/thread_task_runner_handle.h" | 15 #include "base/threading/thread_task_runner_handle.h" |
14 #include "device/bluetooth/android/wrappers.h" | 16 #include "device/bluetooth/android/wrappers.h" |
15 #include "device/bluetooth/bluetooth_advertisement.h" | 17 #include "device/bluetooth/bluetooth_advertisement.h" |
16 #include "device/bluetooth/bluetooth_device_android.h" | 18 #include "device/bluetooth/bluetooth_device_android.h" |
17 #include "device/bluetooth/bluetooth_discovery_session_outcome.h" | 19 #include "device/bluetooth/bluetooth_discovery_session_outcome.h" |
18 #include "jni/ChromeBluetoothAdapter_jni.h" | 20 #include "jni/ChromeBluetoothAdapter_jni.h" |
19 | 21 |
20 using base::android::AttachCurrentThread; | 22 using base::android::AttachCurrentThread; |
21 using base::android::ConvertJavaStringToUTF8; | 23 using base::android::ConvertJavaStringToUTF8; |
22 | 24 |
| 25 namespace { |
| 26 // The poll interval in ms when there is no active discovery. This |
| 27 // matches the max allowed advertisting interval for connectable |
| 28 // devices. |
| 29 enum { kPassivePollInterval = 11000 }; |
| 30 // The poll interval in ms when there is an active discovery. |
| 31 enum { kActivePollInterval = 1000 }; |
| 32 // The delay in ms to wait before purging devices when a scan starts. |
| 33 enum { kPurgeDelay = 500 }; |
| 34 } |
| 35 |
23 namespace device { | 36 namespace device { |
24 | 37 |
25 // static | 38 // static |
26 base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter( | 39 base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter( |
27 const InitCallback& init_callback) { | 40 const InitCallback& init_callback) { |
28 return BluetoothAdapterAndroid::Create( | 41 return BluetoothAdapterAndroid::Create( |
29 BluetoothAdapterWrapper_CreateWithDefaultAdapter().obj()); | 42 BluetoothAdapterWrapper_CreateWithDefaultAdapter().obj()); |
30 } | 43 } |
31 | 44 |
32 // static | 45 // static |
33 base::WeakPtr<BluetoothAdapterAndroid> BluetoothAdapterAndroid::Create( | 46 base::WeakPtr<BluetoothAdapterAndroid> BluetoothAdapterAndroid::Create( |
34 jobject bluetooth_adapter_wrapper) { // Java Type: bluetoothAdapterWrapper | 47 jobject bluetooth_adapter_wrapper) { // Java Type: bluetoothAdapterWrapper |
35 BluetoothAdapterAndroid* adapter = new BluetoothAdapterAndroid(); | 48 BluetoothAdapterAndroid* adapter = new BluetoothAdapterAndroid(); |
36 | 49 |
37 adapter->j_adapter_.Reset(Java_ChromeBluetoothAdapter_create( | 50 adapter->j_adapter_.Reset(Java_ChromeBluetoothAdapter_create( |
38 AttachCurrentThread(), reinterpret_cast<intptr_t>(adapter), | 51 AttachCurrentThread(), reinterpret_cast<intptr_t>(adapter), |
39 bluetooth_adapter_wrapper)); | 52 bluetooth_adapter_wrapper)); |
40 | 53 |
| 54 adapter->ui_task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
| 55 |
41 return adapter->weak_ptr_factory_.GetWeakPtr(); | 56 return adapter->weak_ptr_factory_.GetWeakPtr(); |
42 } | 57 } |
43 | 58 |
44 // static | 59 // static |
45 bool BluetoothAdapterAndroid::RegisterJNI(JNIEnv* env) { | 60 bool BluetoothAdapterAndroid::RegisterJNI(JNIEnv* env) { |
46 return RegisterNativesImpl(env); // Generated in BluetoothAdapter_jni.h | 61 return RegisterNativesImpl(env); // Generated in BluetoothAdapter_jni.h |
47 } | 62 } |
48 | 63 |
49 std::string BluetoothAdapterAndroid::GetAddress() const { | 64 std::string BluetoothAdapterAndroid::GetAddress() const { |
50 return ConvertJavaStringToUTF8(Java_ChromeBluetoothAdapter_getAddress( | 65 return ConvertJavaStringToUTF8(Java_ChromeBluetoothAdapter_getAddress( |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 void BluetoothAdapterAndroid::OnAdapterStateChanged( | 164 void BluetoothAdapterAndroid::OnAdapterStateChanged( |
150 JNIEnv* env, | 165 JNIEnv* env, |
151 const JavaParamRef<jobject>& caller, | 166 const JavaParamRef<jobject>& caller, |
152 const bool powered) { | 167 const bool powered) { |
153 NotifyAdapterPoweredChanged(powered); | 168 NotifyAdapterPoweredChanged(powered); |
154 } | 169 } |
155 | 170 |
156 void BluetoothAdapterAndroid::OnScanFailed( | 171 void BluetoothAdapterAndroid::OnScanFailed( |
157 JNIEnv* env, | 172 JNIEnv* env, |
158 const JavaParamRef<jobject>& caller) { | 173 const JavaParamRef<jobject>& caller) { |
| 174 num_discovery_sessions_ = 0; |
159 MarkDiscoverySessionsAsInactive(); | 175 MarkDiscoverySessionsAsInactive(); |
160 } | 176 } |
161 | 177 |
162 void BluetoothAdapterAndroid::CreateOrUpdateDeviceOnScan( | 178 void BluetoothAdapterAndroid::CreateOrUpdateDeviceOnScan( |
163 JNIEnv* env, | 179 JNIEnv* env, |
164 const JavaParamRef<jobject>& caller, | 180 const JavaParamRef<jobject>& caller, |
165 const JavaParamRef<jstring>& address, | 181 const JavaParamRef<jstring>& address, |
166 const JavaParamRef<jobject>& | 182 const JavaParamRef<jobject>& |
167 bluetooth_device_wrapper, // Java Type: bluetoothDeviceWrapper | 183 bluetooth_device_wrapper, // Java Type: bluetoothDeviceWrapper |
168 const JavaParamRef<jobject>& | 184 const JavaParamRef<jobject>& |
169 advertised_uuids) { // Java Type: List<ParcelUuid> | 185 advertised_uuids) { // Java Type: List<ParcelUuid> |
170 std::string device_address = ConvertJavaStringToUTF8(env, address); | 186 std::string device_address = ConvertJavaStringToUTF8(env, address); |
171 DevicesMap::const_iterator iter = devices_.find(device_address); | 187 DevicesMap::const_iterator iter = devices_.find(device_address); |
172 | 188 |
173 if (iter == devices_.end()) { | 189 if (iter == devices_.end()) { |
174 // New device. | 190 // New device. |
175 BluetoothDeviceAndroid* device_android = | 191 BluetoothDeviceAndroid* device_android = |
176 BluetoothDeviceAndroid::Create(this, bluetooth_device_wrapper); | 192 BluetoothDeviceAndroid::Create(this, bluetooth_device_wrapper); |
177 device_android->UpdateAdvertisedUUIDs(advertised_uuids); | 193 device_android->UpdateAdvertisedUUIDs(advertised_uuids); |
| 194 device_android->UpdateTimestamp(); |
178 devices_.add(device_address, | 195 devices_.add(device_address, |
179 std::unique_ptr<BluetoothDevice>(device_android)); | 196 std::unique_ptr<BluetoothDevice>(device_android)); |
180 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, | 197 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, |
181 DeviceAdded(this, device_android)); | 198 DeviceAdded(this, device_android)); |
182 } else { | 199 } else { |
183 // Existing device. | 200 // Existing device. |
184 BluetoothDeviceAndroid* device_android = | 201 BluetoothDeviceAndroid* device_android = |
185 static_cast<BluetoothDeviceAndroid*>(iter->second); | 202 static_cast<BluetoothDeviceAndroid*>(iter->second); |
| 203 device_android->UpdateTimestamp(); |
186 if (device_android->UpdateAdvertisedUUIDs(advertised_uuids)) { | 204 if (device_android->UpdateAdvertisedUUIDs(advertised_uuids)) { |
187 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, | 205 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, |
188 DeviceChanged(this, device_android)); | 206 DeviceChanged(this, device_android)); |
189 } | 207 } |
190 } | 208 } |
191 } | 209 } |
192 | 210 |
193 BluetoothAdapterAndroid::BluetoothAdapterAndroid() : weak_ptr_factory_(this) { | 211 BluetoothAdapterAndroid::BluetoothAdapterAndroid() : weak_ptr_factory_(this) { |
194 } | 212 } |
195 | 213 |
196 BluetoothAdapterAndroid::~BluetoothAdapterAndroid() { | 214 BluetoothAdapterAndroid::~BluetoothAdapterAndroid() { |
197 Java_ChromeBluetoothAdapter_onBluetoothAdapterAndroidDestruction( | 215 Java_ChromeBluetoothAdapter_onBluetoothAdapterAndroidDestruction( |
198 AttachCurrentThread(), j_adapter_.obj()); | 216 AttachCurrentThread(), j_adapter_.obj()); |
199 } | 217 } |
200 | 218 |
| 219 void BluetoothAdapterAndroid::PurgeTimedOutDevices() { |
| 220 RemoveTimedOutDevices(); |
| 221 if (IsDiscovering()) { |
| 222 ui_task_runner_->PostDelayedTask( |
| 223 FROM_HERE, base::Bind(&BluetoothAdapterAndroid::PurgeTimedOutDevices, |
| 224 weak_ptr_factory_.GetWeakPtr()), |
| 225 base::TimeDelta::FromMilliseconds(kActivePollInterval)); |
| 226 } else { |
| 227 ui_task_runner_->PostDelayedTask( |
| 228 FROM_HERE, base::Bind(&BluetoothAdapterAndroid::RemoveTimedOutDevices, |
| 229 weak_ptr_factory_.GetWeakPtr()), |
| 230 base::TimeDelta::FromMilliseconds(kPassivePollInterval)); |
| 231 } |
| 232 } |
| 233 |
201 void BluetoothAdapterAndroid::AddDiscoverySession( | 234 void BluetoothAdapterAndroid::AddDiscoverySession( |
202 BluetoothDiscoveryFilter* discovery_filter, | 235 BluetoothDiscoveryFilter* discovery_filter, |
203 const base::Closure& callback, | 236 const base::Closure& callback, |
204 const DiscoverySessionErrorCallback& error_callback) { | 237 const DiscoverySessionErrorCallback& error_callback) { |
205 // TODO(scheib): Support filters crbug.com/490401 | 238 // TODO(scheib): Support filters crbug.com/490401 |
206 if (Java_ChromeBluetoothAdapter_addDiscoverySession(AttachCurrentThread(), | 239 bool session_added = false; |
207 j_adapter_.obj())) { | 240 if (IsPowered()) { |
| 241 if (num_discovery_sessions_ > 0) { |
| 242 session_added = true; |
| 243 } else if (Java_ChromeBluetoothAdapter_startScan(AttachCurrentThread(), |
| 244 j_adapter_.obj())) { |
| 245 session_added = true; |
| 246 |
| 247 // Using a delayed task in order to give the adapter some time |
| 248 // to settle before purging devices. |
| 249 ui_task_runner_->PostDelayedTask( |
| 250 FROM_HERE, base::Bind(&BluetoothAdapterAndroid::PurgeTimedOutDevices, |
| 251 weak_ptr_factory_.GetWeakPtr()), |
| 252 base::TimeDelta::FromMilliseconds(kPurgeDelay)); |
| 253 } |
| 254 } else { |
| 255 VLOG(1) << "AddDiscoverySession: Fails: !isPowered"; |
| 256 } |
| 257 |
| 258 if (session_added) { |
| 259 num_discovery_sessions_++; |
| 260 VLOG(1) << "AddDiscoverySession: Now " << unsigned(num_discovery_sessions_) |
| 261 << " sessions."; |
208 callback.Run(); | 262 callback.Run(); |
209 } else { | 263 } else { |
210 // TODO(scheib): Eventually wire the SCAN_FAILED result through to here. | 264 // TODO(scheib): Eventually wire the SCAN_FAILED result through to here. |
211 error_callback.Run(UMABluetoothDiscoverySessionOutcome::UNKNOWN); | 265 error_callback.Run(UMABluetoothDiscoverySessionOutcome::UNKNOWN); |
212 } | 266 } |
213 } | 267 } |
214 | 268 |
215 void BluetoothAdapterAndroid::RemoveDiscoverySession( | 269 void BluetoothAdapterAndroid::RemoveDiscoverySession( |
216 BluetoothDiscoveryFilter* discovery_filter, | 270 BluetoothDiscoveryFilter* discovery_filter, |
217 const base::Closure& callback, | 271 const base::Closure& callback, |
218 const DiscoverySessionErrorCallback& error_callback) { | 272 const DiscoverySessionErrorCallback& error_callback) { |
219 if (Java_ChromeBluetoothAdapter_removeDiscoverySession(AttachCurrentThread(), | 273 bool session_removed = false; |
220 j_adapter_.obj())) { | 274 if (num_discovery_sessions_ == 0) { |
| 275 VLOG(1) << "RemoveDiscoverySession: No scan in progress."; |
| 276 NOTREACHED(); |
| 277 } else { |
| 278 --num_discovery_sessions_; |
| 279 session_removed = true; |
| 280 if (num_discovery_sessions_ == 0) { |
| 281 VLOG(1) << "RemoveDiscoverySession: Now 0 sessions. Stopping scan."; |
| 282 session_removed = Java_ChromeBluetoothAdapter_stopScan( |
| 283 AttachCurrentThread(), j_adapter_.obj()); |
| 284 } else { |
| 285 VLOG(1) << "RemoveDiscoverySession: Now " |
| 286 << unsigned(num_discovery_sessions_) << " sessions."; |
| 287 } |
| 288 } |
| 289 |
| 290 if (session_removed) { |
221 callback.Run(); | 291 callback.Run(); |
222 } else { | 292 } else { |
223 // TODO(scheib): Eventually wire the SCAN_FAILED result through to here. | 293 // TODO(scheib): Eventually wire the SCAN_FAILED result through to here. |
224 error_callback.Run(UMABluetoothDiscoverySessionOutcome::UNKNOWN); | 294 error_callback.Run(UMABluetoothDiscoverySessionOutcome::UNKNOWN); |
225 } | 295 } |
226 } | 296 } |
227 | 297 |
228 void BluetoothAdapterAndroid::SetDiscoveryFilter( | 298 void BluetoothAdapterAndroid::SetDiscoveryFilter( |
229 std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter, | 299 std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter, |
230 const base::Closure& callback, | 300 const base::Closure& callback, |
231 const DiscoverySessionErrorCallback& error_callback) { | 301 const DiscoverySessionErrorCallback& error_callback) { |
232 // TODO(scheib): Support filters crbug.com/490401 | 302 // TODO(scheib): Support filters crbug.com/490401 |
233 NOTIMPLEMENTED(); | 303 NOTIMPLEMENTED(); |
234 error_callback.Run(UMABluetoothDiscoverySessionOutcome::NOT_IMPLEMENTED); | 304 error_callback.Run(UMABluetoothDiscoverySessionOutcome::NOT_IMPLEMENTED); |
235 } | 305 } |
236 | 306 |
237 void BluetoothAdapterAndroid::RemovePairingDelegateInternal( | 307 void BluetoothAdapterAndroid::RemovePairingDelegateInternal( |
238 device::BluetoothDevice::PairingDelegate* pairing_delegate) { | 308 device::BluetoothDevice::PairingDelegate* pairing_delegate) { |
239 } | 309 } |
240 | 310 |
241 } // namespace device | 311 } // namespace device |
OLD | NEW |