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 if (IsDiscovering()) { | |
221 RemoveTimedOutDevices(); | |
ortuno
2016/06/22 17:23:11
nit: We always want to purge timed out devices, so
perja
2016/06/23 14:31:25
Done.
| |
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 |