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 } | |
33 | |
23 namespace device { | 34 namespace device { |
24 | 35 |
25 // static | 36 // static |
26 base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter( | 37 base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter( |
27 const InitCallback& init_callback) { | 38 const InitCallback& init_callback) { |
28 return BluetoothAdapterAndroid::Create( | 39 return BluetoothAdapterAndroid::Create( |
29 BluetoothAdapterWrapper_CreateWithDefaultAdapter().obj()); | 40 BluetoothAdapterWrapper_CreateWithDefaultAdapter().obj()); |
30 } | 41 } |
31 | 42 |
32 // static | 43 // static |
33 base::WeakPtr<BluetoothAdapterAndroid> BluetoothAdapterAndroid::Create( | 44 base::WeakPtr<BluetoothAdapterAndroid> BluetoothAdapterAndroid::Create( |
34 jobject bluetooth_adapter_wrapper) { // Java Type: bluetoothAdapterWrapper | 45 jobject bluetooth_adapter_wrapper) { // Java Type: bluetoothAdapterWrapper |
35 BluetoothAdapterAndroid* adapter = new BluetoothAdapterAndroid(); | 46 BluetoothAdapterAndroid* adapter = new BluetoothAdapterAndroid(); |
36 | 47 |
37 adapter->j_adapter_.Reset(Java_ChromeBluetoothAdapter_create( | 48 adapter->j_adapter_.Reset(Java_ChromeBluetoothAdapter_create( |
38 AttachCurrentThread(), reinterpret_cast<intptr_t>(adapter), | 49 AttachCurrentThread(), reinterpret_cast<intptr_t>(adapter), |
39 bluetooth_adapter_wrapper)); | 50 bluetooth_adapter_wrapper)); |
40 | 51 |
52 adapter->ui_task_runner_ = base::ThreadTaskRunnerHandle::Get(); | |
53 | |
41 return adapter->weak_ptr_factory_.GetWeakPtr(); | 54 return adapter->weak_ptr_factory_.GetWeakPtr(); |
42 } | 55 } |
43 | 56 |
44 // static | 57 // static |
45 bool BluetoothAdapterAndroid::RegisterJNI(JNIEnv* env) { | 58 bool BluetoothAdapterAndroid::RegisterJNI(JNIEnv* env) { |
46 return RegisterNativesImpl(env); // Generated in BluetoothAdapter_jni.h | 59 return RegisterNativesImpl(env); // Generated in BluetoothAdapter_jni.h |
47 } | 60 } |
48 | 61 |
49 std::string BluetoothAdapterAndroid::GetAddress() const { | 62 std::string BluetoothAdapterAndroid::GetAddress() const { |
50 return ConvertJavaStringToUTF8(Java_ChromeBluetoothAdapter_getAddress( | 63 return ConvertJavaStringToUTF8(Java_ChromeBluetoothAdapter_getAddress( |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
149 void BluetoothAdapterAndroid::OnAdapterStateChanged( | 162 void BluetoothAdapterAndroid::OnAdapterStateChanged( |
150 JNIEnv* env, | 163 JNIEnv* env, |
151 const JavaParamRef<jobject>& caller, | 164 const JavaParamRef<jobject>& caller, |
152 const bool powered) { | 165 const bool powered) { |
153 NotifyAdapterPoweredChanged(powered); | 166 NotifyAdapterPoweredChanged(powered); |
154 } | 167 } |
155 | 168 |
156 void BluetoothAdapterAndroid::OnScanFailed( | 169 void BluetoothAdapterAndroid::OnScanFailed( |
157 JNIEnv* env, | 170 JNIEnv* env, |
158 const JavaParamRef<jobject>& caller) { | 171 const JavaParamRef<jobject>& caller) { |
172 numDiscoverySessions = 0; | |
159 MarkDiscoverySessionsAsInactive(); | 173 MarkDiscoverySessionsAsInactive(); |
160 } | 174 } |
161 | 175 |
162 void BluetoothAdapterAndroid::CreateOrUpdateDeviceOnScan( | 176 void BluetoothAdapterAndroid::CreateOrUpdateDeviceOnScan( |
163 JNIEnv* env, | 177 JNIEnv* env, |
164 const JavaParamRef<jobject>& caller, | 178 const JavaParamRef<jobject>& caller, |
165 const JavaParamRef<jstring>& address, | 179 const JavaParamRef<jstring>& address, |
166 const JavaParamRef<jobject>& | 180 const JavaParamRef<jobject>& |
167 bluetooth_device_wrapper, // Java Type: bluetoothDeviceWrapper | 181 bluetooth_device_wrapper, // Java Type: bluetoothDeviceWrapper |
168 const JavaParamRef<jobject>& | 182 const JavaParamRef<jobject>& |
169 advertised_uuids) { // Java Type: List<ParcelUuid> | 183 advertised_uuids) { // Java Type: List<ParcelUuid> |
170 std::string device_address = ConvertJavaStringToUTF8(env, address); | 184 std::string device_address = ConvertJavaStringToUTF8(env, address); |
171 DevicesMap::const_iterator iter = devices_.find(device_address); | 185 DevicesMap::const_iterator iter = devices_.find(device_address); |
172 | 186 |
173 if (iter == devices_.end()) { | 187 if (iter == devices_.end()) { |
174 // New device. | 188 // New device. |
175 BluetoothDeviceAndroid* device_android = | 189 BluetoothDeviceAndroid* device_android = |
176 BluetoothDeviceAndroid::Create(this, bluetooth_device_wrapper); | 190 BluetoothDeviceAndroid::Create(this, bluetooth_device_wrapper); |
177 device_android->UpdateAdvertisedUUIDs(advertised_uuids); | 191 device_android->UpdateAdvertisedUUIDs(advertised_uuids); |
192 device_android->UpdateTimestamp(); | |
178 devices_.add(device_address, | 193 devices_.add(device_address, |
179 std::unique_ptr<BluetoothDevice>(device_android)); | 194 std::unique_ptr<BluetoothDevice>(device_android)); |
180 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, | 195 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, |
181 DeviceAdded(this, device_android)); | 196 DeviceAdded(this, device_android)); |
182 } else { | 197 } else { |
183 // Existing device. | 198 // Existing device. |
184 BluetoothDeviceAndroid* device_android = | 199 BluetoothDeviceAndroid* device_android = |
185 static_cast<BluetoothDeviceAndroid*>(iter->second); | 200 static_cast<BluetoothDeviceAndroid*>(iter->second); |
201 device_android->UpdateTimestamp(); | |
186 if (device_android->UpdateAdvertisedUUIDs(advertised_uuids)) { | 202 if (device_android->UpdateAdvertisedUUIDs(advertised_uuids)) { |
187 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, | 203 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, |
188 DeviceChanged(this, device_android)); | 204 DeviceChanged(this, device_android)); |
189 } | 205 } |
190 } | 206 } |
191 } | 207 } |
192 | 208 |
193 BluetoothAdapterAndroid::BluetoothAdapterAndroid() : weak_ptr_factory_(this) { | 209 BluetoothAdapterAndroid::BluetoothAdapterAndroid() : weak_ptr_factory_(this) { |
194 } | 210 } |
195 | 211 |
196 BluetoothAdapterAndroid::~BluetoothAdapterAndroid() { | 212 BluetoothAdapterAndroid::~BluetoothAdapterAndroid() { |
197 Java_ChromeBluetoothAdapter_onBluetoothAdapterAndroidDestruction( | 213 Java_ChromeBluetoothAdapter_onBluetoothAdapterAndroidDestruction( |
198 AttachCurrentThread(), j_adapter_.obj()); | 214 AttachCurrentThread(), j_adapter_.obj()); |
199 } | 215 } |
200 | 216 |
217 void BluetoothAdapterAndroid::PurgeTimedOutDevices() { | |
ortuno
2016/06/15 17:20:16
I'm wondering if we should post a delayed task to
perja
2016/06/17 13:39:27
Not sure I see why. It will be kept or purged duri
| |
218 if (IsDiscovering()) { | |
219 RemoveTimedOutDevices(); | |
220 ui_task_runner_->PostDelayedTask( | |
221 FROM_HERE, base::Bind(&BluetoothAdapterAndroid::PurgeTimedOutDevices, | |
222 weak_ptr_factory_.GetWeakPtr()), | |
223 base::TimeDelta::FromMilliseconds(kActivePollInterval)); | |
224 } else { | |
225 ui_task_runner_->PostDelayedTask( | |
226 FROM_HERE, base::Bind(&BluetoothAdapterAndroid::RemoveTimedOutDevices, | |
227 weak_ptr_factory_.GetWeakPtr()), | |
228 base::TimeDelta::FromMilliseconds(kPassivePollInterval)); | |
229 } | |
230 } | |
231 | |
201 void BluetoothAdapterAndroid::AddDiscoverySession( | 232 void BluetoothAdapterAndroid::AddDiscoverySession( |
202 BluetoothDiscoveryFilter* discovery_filter, | 233 BluetoothDiscoveryFilter* discovery_filter, |
203 const base::Closure& callback, | 234 const base::Closure& callback, |
204 const DiscoverySessionErrorCallback& error_callback) { | 235 const DiscoverySessionErrorCallback& error_callback) { |
205 // TODO(scheib): Support filters crbug.com/490401 | 236 // TODO(scheib): Support filters crbug.com/490401 |
206 if (Java_ChromeBluetoothAdapter_addDiscoverySession(AttachCurrentThread(), | 237 if (AddDiscoverySessionInternal()) { |
207 j_adapter_.obj())) { | |
208 callback.Run(); | 238 callback.Run(); |
209 } else { | 239 } else { |
210 // TODO(scheib): Eventually wire the SCAN_FAILED result through to here. | 240 // TODO(scheib): Eventually wire the SCAN_FAILED result through to here. |
211 error_callback.Run(UMABluetoothDiscoverySessionOutcome::UNKNOWN); | 241 error_callback.Run(UMABluetoothDiscoverySessionOutcome::UNKNOWN); |
212 } | 242 } |
213 } | 243 } |
214 | 244 |
245 bool BluetoothAdapterAndroid::AddDiscoverySessionInternal() { | |
ortuno
2016/06/15 17:20:16
optional: I think this could be moved to AddDiscov
perja
2016/06/17 13:39:27
Done.
| |
246 if (!IsPowered()) { | |
247 VLOG(1) << "AddDiscoverySession: Fails: !isPowered"; | |
248 return false; | |
249 } | |
250 | |
251 numDiscoverySessions++; | |
252 VLOG(1) << "AddDiscoverySession: Now " << unsigned(numDiscoverySessions) | |
253 << " sessions."; | |
254 if (numDiscoverySessions > 1) { | |
255 return true; | |
256 } | |
257 | |
258 if (!Java_ChromeBluetoothAdapter_addDiscoverySession(AttachCurrentThread(), | |
259 j_adapter_.obj())) { | |
260 numDiscoverySessions--; | |
261 return false; | |
262 } else { | |
263 PurgeTimedOutDevices(); | |
ortuno
2016/06/15 17:20:16
This results in mAdapter.isDiscovering() being cal
perja
2016/06/17 13:39:27
Yeah, that sounds like a good idea. I guess we can
| |
264 } | |
265 return true; | |
266 } | |
267 | |
215 void BluetoothAdapterAndroid::RemoveDiscoverySession( | 268 void BluetoothAdapterAndroid::RemoveDiscoverySession( |
216 BluetoothDiscoveryFilter* discovery_filter, | 269 BluetoothDiscoveryFilter* discovery_filter, |
217 const base::Closure& callback, | 270 const base::Closure& callback, |
218 const DiscoverySessionErrorCallback& error_callback) { | 271 const DiscoverySessionErrorCallback& error_callback) { |
219 if (Java_ChromeBluetoothAdapter_removeDiscoverySession(AttachCurrentThread(), | 272 if (RemoveDiscoverySessionInternal()) { |
220 j_adapter_.obj())) { | |
221 callback.Run(); | 273 callback.Run(); |
222 } else { | 274 } else { |
223 // TODO(scheib): Eventually wire the SCAN_FAILED result through to here. | 275 // TODO(scheib): Eventually wire the SCAN_FAILED result through to here. |
224 error_callback.Run(UMABluetoothDiscoverySessionOutcome::UNKNOWN); | 276 error_callback.Run(UMABluetoothDiscoverySessionOutcome::UNKNOWN); |
225 } | 277 } |
226 } | 278 } |
227 | 279 |
280 bool BluetoothAdapterAndroid::RemoveDiscoverySessionInternal() { | |
281 if (numDiscoverySessions == 0) { | |
282 DCHECK(false); | |
283 VLOG(1) << "RemoveDiscoverySession: No scan in progress."; | |
284 return false; | |
285 } | |
286 | |
287 --numDiscoverySessions; | |
288 | |
289 if (numDiscoverySessions == 0) { | |
290 VLOG(1) << "RemoveDiscoverySession: Now 0 sessions. Stopping scan."; | |
291 return Java_ChromeBluetoothAdapter_removeDiscoverySession( | |
292 AttachCurrentThread(), j_adapter_.obj()); | |
293 } | |
294 | |
295 VLOG(1) << "RemoveDiscoverySession: Now " << unsigned(numDiscoverySessions) | |
296 << " sessions."; | |
297 return true; | |
298 } | |
299 | |
228 void BluetoothAdapterAndroid::SetDiscoveryFilter( | 300 void BluetoothAdapterAndroid::SetDiscoveryFilter( |
229 std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter, | 301 std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter, |
230 const base::Closure& callback, | 302 const base::Closure& callback, |
231 const DiscoverySessionErrorCallback& error_callback) { | 303 const DiscoverySessionErrorCallback& error_callback) { |
232 // TODO(scheib): Support filters crbug.com/490401 | 304 // TODO(scheib): Support filters crbug.com/490401 |
233 NOTIMPLEMENTED(); | 305 NOTIMPLEMENTED(); |
234 error_callback.Run(UMABluetoothDiscoverySessionOutcome::NOT_IMPLEMENTED); | 306 error_callback.Run(UMABluetoothDiscoverySessionOutcome::NOT_IMPLEMENTED); |
235 } | 307 } |
236 | 308 |
237 void BluetoothAdapterAndroid::RemovePairingDelegateInternal( | 309 void BluetoothAdapterAndroid::RemovePairingDelegateInternal( |
238 device::BluetoothDevice::PairingDelegate* pairing_delegate) { | 310 device::BluetoothDevice::PairingDelegate* pairing_delegate) { |
239 } | 311 } |
240 | 312 |
241 } // namespace device | 313 } // namespace device |
OLD | NEW |