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 package org.chromium.device.bluetooth; | 5 package org.chromium.device.bluetooth; |
6 | 6 |
7 import android.Manifest; | 7 import android.Manifest; |
8 import android.annotation.TargetApi; | 8 import android.annotation.TargetApi; |
9 import android.bluetooth.BluetoothAdapter; | 9 import android.bluetooth.BluetoothAdapter; |
10 import android.bluetooth.le.ScanSettings; | 10 import android.bluetooth.le.ScanSettings; |
(...skipping 18 matching lines...) Expand all Loading... |
29 * Lifetime is controlled by device::BluetoothAdapterAndroid. | 29 * Lifetime is controlled by device::BluetoothAdapterAndroid. |
30 */ | 30 */ |
31 @JNINamespace("device") | 31 @JNINamespace("device") |
32 @TargetApi(Build.VERSION_CODES.LOLLIPOP) | 32 @TargetApi(Build.VERSION_CODES.LOLLIPOP) |
33 final class ChromeBluetoothAdapter extends BroadcastReceiver { | 33 final class ChromeBluetoothAdapter extends BroadcastReceiver { |
34 private static final String TAG = "Bluetooth"; | 34 private static final String TAG = "Bluetooth"; |
35 | 35 |
36 private long mNativeBluetoothAdapterAndroid; | 36 private long mNativeBluetoothAdapterAndroid; |
37 // mAdapter is final to ensure registerReceiver is followed by unregisterRec
eiver. | 37 // mAdapter is final to ensure registerReceiver is followed by unregisterRec
eiver. |
38 private final Wrappers.BluetoothAdapterWrapper mAdapter; | 38 private final Wrappers.BluetoothAdapterWrapper mAdapter; |
39 private int mNumDiscoverySessions; | |
40 private ScanCallback mScanCallback; | 39 private ScanCallback mScanCallback; |
41 | 40 |
42 // -------------------------------------------------------------------------
-------------------- | 41 // -------------------------------------------------------------------------
-------------------- |
43 // Construction and handler for C++ object destruction. | 42 // Construction and handler for C++ object destruction. |
44 | 43 |
45 /** | 44 /** |
46 * Constructs a ChromeBluetoothAdapter. | 45 * Constructs a ChromeBluetoothAdapter. |
47 * @param nativeBluetoothAdapterAndroid Is the associated C++ | 46 * @param nativeBluetoothAdapterAndroid Is the associated C++ |
48 * BluetoothAdapterAndroid pointer valu
e. | 47 * BluetoothAdapterAndroid pointer valu
e. |
49 * @param adapterWrapper Wraps the default android.bluetooth.BluetoothAdapte
r, | 48 * @param adapterWrapper Wraps the default android.bluetooth.BluetoothAdapte
r, |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 return isPresent() | 133 return isPresent() |
135 && mAdapter.getScanMode() == BluetoothAdapter.SCAN_MODE_CONNECTA
BLE_DISCOVERABLE; | 134 && mAdapter.getScanMode() == BluetoothAdapter.SCAN_MODE_CONNECTA
BLE_DISCOVERABLE; |
136 } | 135 } |
137 | 136 |
138 // Implements BluetoothAdapterAndroid::IsDiscovering. | 137 // Implements BluetoothAdapterAndroid::IsDiscovering. |
139 @CalledByNative | 138 @CalledByNative |
140 private boolean isDiscovering() { | 139 private boolean isDiscovering() { |
141 return isPresent() && (mAdapter.isDiscovering() || mScanCallback != null
); | 140 return isPresent() && (mAdapter.isDiscovering() || mScanCallback != null
); |
142 } | 141 } |
143 | 142 |
144 // Implements BluetoothAdapterAndroid::AddDiscoverySession. | |
145 @CalledByNative | |
146 private boolean addDiscoverySession() { | |
147 if (!isPowered()) { | |
148 Log.d(TAG, "addDiscoverySession: Fails: !isPowered"); | |
149 return false; | |
150 } | |
151 | |
152 mNumDiscoverySessions++; | |
153 Log.d(TAG, "addDiscoverySession: Now %d sessions.", mNumDiscoverySession
s); | |
154 if (mNumDiscoverySessions > 1) { | |
155 return true; | |
156 } | |
157 | |
158 if (!startScan()) { | |
159 mNumDiscoverySessions--; | |
160 return false; | |
161 } | |
162 return true; | |
163 } | |
164 | |
165 // Implements BluetoothAdapterAndroid::RemoveDiscoverySession. | |
166 @CalledByNative | |
167 private boolean removeDiscoverySession() { | |
168 if (mNumDiscoverySessions == 0) { | |
169 assert false; | |
170 Log.w(TAG, "removeDiscoverySession: No scan in progress."); | |
171 return false; | |
172 } | |
173 | |
174 --mNumDiscoverySessions; | |
175 | |
176 if (mNumDiscoverySessions == 0) { | |
177 Log.d(TAG, "removeDiscoverySession: Now 0 sessions. Stopping scan.")
; | |
178 return stopScan(); | |
179 } | |
180 | |
181 Log.d(TAG, "removeDiscoverySession: Now %d sessions.", mNumDiscoverySess
ions); | |
182 return true; | |
183 } | |
184 | |
185 // -------------------------------------------------------------------------
-------------------- | |
186 // Implementation details: | |
187 | |
188 /** | |
189 * @return true if Chromium has permission to scan for Bluetooth devices. | |
190 */ | |
191 private boolean canScan() { | |
192 Wrappers.ContextWrapper context = mAdapter.getContext(); | |
193 return context.checkPermission(Manifest.permission.ACCESS_COARSE_LOCATIO
N) | |
194 || context.checkPermission(Manifest.permission.ACCESS_FINE_LOCAT
ION); | |
195 } | |
196 | |
197 private void registerBroadcastReceiver() { | |
198 if (mAdapter != null) { | |
199 mAdapter.getContext().registerReceiver( | |
200 this, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED
)); | |
201 } | |
202 } | |
203 | |
204 private void unregisterBroadcastReceiver() { | |
205 if (mAdapter != null) { | |
206 mAdapter.getContext().unregisterReceiver(this); | |
207 } | |
208 } | |
209 | |
210 /** | 143 /** |
211 * Starts a Low Energy scan. | 144 * Starts a Low Energy scan. |
212 * @return True on success. | 145 * @return True on success. |
213 */ | 146 */ |
| 147 @CalledByNative |
214 private boolean startScan() { | 148 private boolean startScan() { |
215 Wrappers.BluetoothLeScannerWrapper scanner = mAdapter.getBluetoothLeScan
ner(); | 149 Wrappers.BluetoothLeScannerWrapper scanner = mAdapter.getBluetoothLeScan
ner(); |
216 | 150 |
217 if (scanner == null) { | 151 if (scanner == null) { |
218 return false; | 152 return false; |
219 } | 153 } |
220 | 154 |
221 if (!canScan()) { | 155 if (!canScan()) { |
222 return false; | 156 return false; |
223 } | 157 } |
(...skipping 16 matching lines...) Expand all Loading... |
240 mScanCallback = null; | 174 mScanCallback = null; |
241 return false; | 175 return false; |
242 } | 176 } |
243 return true; | 177 return true; |
244 } | 178 } |
245 | 179 |
246 /** | 180 /** |
247 * Stops the Low Energy scan. | 181 * Stops the Low Energy scan. |
248 * @return True if a scan was in progress. | 182 * @return True if a scan was in progress. |
249 */ | 183 */ |
| 184 @CalledByNative |
250 private boolean stopScan() { | 185 private boolean stopScan() { |
251 if (mScanCallback == null) { | 186 if (mScanCallback == null) { |
252 return false; | 187 return false; |
253 } | 188 } |
254 | 189 |
255 try { | 190 try { |
256 Wrappers.BluetoothLeScannerWrapper scanner = mAdapter.getBluetoothLe
Scanner(); | 191 Wrappers.BluetoothLeScannerWrapper scanner = mAdapter.getBluetoothLe
Scanner(); |
257 if (scanner != null) { | 192 if (scanner != null) { |
258 scanner.stopScan(mScanCallback); | 193 scanner.stopScan(mScanCallback); |
259 } | 194 } |
260 } catch (IllegalArgumentException e) { | 195 } catch (IllegalArgumentException e) { |
261 Log.e(TAG, "Cannot stop scan: " + e); | 196 Log.e(TAG, "Cannot stop scan: " + e); |
262 } catch (IllegalStateException e) { | 197 } catch (IllegalStateException e) { |
263 Log.e(TAG, "Adapter is off. Cannot stop scan: " + e); | 198 Log.e(TAG, "Adapter is off. Cannot stop scan: " + e); |
264 } | 199 } |
265 mScanCallback = null; | 200 mScanCallback = null; |
266 return true; | 201 return true; |
267 } | 202 } |
268 | 203 |
| 204 // -------------------------------------------------------------------------
-------------------- |
| 205 // Implementation details: |
| 206 |
| 207 /** |
| 208 * @return true if Chromium has permission to scan for Bluetooth devices. |
| 209 */ |
| 210 private boolean canScan() { |
| 211 Wrappers.ContextWrapper context = mAdapter.getContext(); |
| 212 return context.checkPermission(Manifest.permission.ACCESS_COARSE_LOCATIO
N) |
| 213 || context.checkPermission(Manifest.permission.ACCESS_FINE_LOCAT
ION); |
| 214 } |
| 215 |
| 216 private void registerBroadcastReceiver() { |
| 217 if (mAdapter != null) { |
| 218 mAdapter.getContext().registerReceiver( |
| 219 this, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED
)); |
| 220 } |
| 221 } |
| 222 |
| 223 private void unregisterBroadcastReceiver() { |
| 224 if (mAdapter != null) { |
| 225 mAdapter.getContext().unregisterReceiver(this); |
| 226 } |
| 227 } |
| 228 |
269 /** | 229 /** |
270 * Implements callbacks used during a Low Energy scan by notifying upon | 230 * Implements callbacks used during a Low Energy scan by notifying upon |
271 * devices discovered or detecting a scan failure. | 231 * devices discovered or detecting a scan failure. |
272 */ | 232 */ |
273 private class ScanCallback extends Wrappers.ScanCallbackWrapper { | 233 private class ScanCallback extends Wrappers.ScanCallbackWrapper { |
274 @Override | 234 @Override |
275 public void onBatchScanResult(List<Wrappers.ScanResultWrapper> results)
{ | 235 public void onBatchScanResult(List<Wrappers.ScanResultWrapper> results)
{ |
276 Log.v(TAG, "onBatchScanResults"); | 236 Log.v(TAG, "onBatchScanResults"); |
277 } | 237 } |
278 | 238 |
279 @Override | 239 @Override |
280 public void onScanResult(int callbackType, Wrappers.ScanResultWrapper re
sult) { | 240 public void onScanResult(int callbackType, Wrappers.ScanResultWrapper re
sult) { |
281 Log.v(TAG, "onScanResult %d %s %s", callbackType, result.getDevice()
.getAddress(), | 241 Log.v(TAG, "onScanResult %d %s %s", callbackType, result.getDevice()
.getAddress(), |
282 result.getDevice().getName()); | 242 result.getDevice().getName()); |
283 | 243 |
284 List<ParcelUuid> uuids = result.getScanRecord_getServiceUuids(); | 244 List<ParcelUuid> uuids = result.getScanRecord_getServiceUuids(); |
285 | 245 |
286 nativeCreateOrUpdateDeviceOnScan(mNativeBluetoothAdapterAndroid, | 246 nativeCreateOrUpdateDeviceOnScan(mNativeBluetoothAdapterAndroid, |
287 result.getDevice().getAddress(), result.getDevice(), uuids); | 247 result.getDevice().getAddress(), result.getDevice(), uuids); |
288 } | 248 } |
289 | 249 |
290 @Override | 250 @Override |
291 public void onScanFailed(int errorCode) { | 251 public void onScanFailed(int errorCode) { |
292 Log.w(TAG, "onScanFailed: %d", errorCode); | 252 Log.w(TAG, "onScanFailed: %d", errorCode); |
293 nativeOnScanFailed(mNativeBluetoothAdapterAndroid); | 253 nativeOnScanFailed(mNativeBluetoothAdapterAndroid); |
294 mNumDiscoverySessions = 0; | |
295 } | 254 } |
296 } | 255 } |
297 | 256 |
298 @Override | 257 @Override |
299 public void onReceive(Context context, Intent intent) { | 258 public void onReceive(Context context, Intent intent) { |
300 String action = intent.getAction(); | 259 String action = intent.getAction(); |
301 | 260 |
302 if (isPresent() && BluetoothAdapter.ACTION_STATE_CHANGED.equals(action))
{ | 261 if (isPresent() && BluetoothAdapter.ACTION_STATE_CHANGED.equals(action))
{ |
303 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, Bluetoo
thAdapter.ERROR); | 262 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, Bluetoo
thAdapter.ERROR); |
304 | 263 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 // 'Object' type must be used for |bluetoothDeviceWrapper| because inner cla
ss | 303 // 'Object' type must be used for |bluetoothDeviceWrapper| because inner cla
ss |
345 // Wrappers.BluetoothDeviceWrapper reference is not handled by jni_generator
.py JavaToJni. | 304 // Wrappers.BluetoothDeviceWrapper reference is not handled by jni_generator
.py JavaToJni. |
346 // http://crbug.com/505554 | 305 // http://crbug.com/505554 |
347 private native void nativeCreateOrUpdateDeviceOnScan(long nativeBluetoothAda
pterAndroid, | 306 private native void nativeCreateOrUpdateDeviceOnScan(long nativeBluetoothAda
pterAndroid, |
348 String address, Object bluetoothDeviceWrapper, List<ParcelUuid> adve
rtisedUuids); | 307 String address, Object bluetoothDeviceWrapper, List<ParcelUuid> adve
rtisedUuids); |
349 | 308 |
350 // Binds to BluetoothAdapterAndroid::nativeOnAdapterStateChanged | 309 // Binds to BluetoothAdapterAndroid::nativeOnAdapterStateChanged |
351 private native void nativeOnAdapterStateChanged( | 310 private native void nativeOnAdapterStateChanged( |
352 long nativeBluetoothAdapterAndroid, boolean powered); | 311 long nativeBluetoothAdapterAndroid, boolean powered); |
353 } | 312 } |
OLD | NEW |