Chromium Code Reviews| 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 |