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.annotation.TargetApi; |
7 import android.bluetooth.BluetoothAdapter; | 8 import android.bluetooth.BluetoothAdapter; |
| 9 import android.bluetooth.le.ScanSettings; |
| 10 import android.os.Build; |
8 | 11 |
9 import org.chromium.base.CalledByNative; | 12 import org.chromium.base.CalledByNative; |
10 import org.chromium.base.JNINamespace; | 13 import org.chromium.base.JNINamespace; |
11 import org.chromium.base.Log; | 14 import org.chromium.base.Log; |
12 | 15 |
| 16 import java.util.List; |
| 17 |
13 /** | 18 /** |
14 * Exposes android.bluetooth.BluetoothAdapter as necessary for C++ | 19 * Exposes android.bluetooth.BluetoothAdapter as necessary for C++ |
15 * device::BluetoothAdapterAndroid, which implements the cross platform | 20 * device::BluetoothAdapterAndroid, which implements the cross platform |
16 * device::BluetoothAdapter. | 21 * device::BluetoothAdapter. |
17 */ | 22 */ |
18 @JNINamespace("device") | 23 @JNINamespace("device") |
| 24 @TargetApi(Build.VERSION_CODES.LOLLIPOP) |
19 final class ChromeBluetoothAdapter { | 25 final class ChromeBluetoothAdapter { |
20 private static final String TAG = "cr.Bluetooth"; | 26 private static final String TAG = "cr.Bluetooth"; |
21 | 27 |
| 28 private long mNativeBluetoothAdapterAndroid; |
22 private Wrappers.BluetoothAdapterWrapper mAdapter; | 29 private Wrappers.BluetoothAdapterWrapper mAdapter; |
| 30 private int mNumDiscoverySessions; |
| 31 private ScanCallback mScanCallback; |
| 32 |
| 33 // -------------------------------------------------------------------------
-------------------- |
| 34 // Construction and handler for C++ object destruction. |
23 | 35 |
24 /** | 36 /** |
25 * Constructs a ChromeBluetoothAdapter. | 37 * Constructs a ChromeBluetoothAdapter. |
| 38 * @param nativeBluetoothAdapterAndroid Is the associated C++ |
| 39 * BluetoothAdapterAndroid pointer valu
e. |
26 * @param adapterWrapper Wraps the default android.bluetooth.BluetoothAdapte
r, | 40 * @param adapterWrapper Wraps the default android.bluetooth.BluetoothAdapte
r, |
27 * but may be either null if an adapter is not availab
le | 41 * but may be either null if an adapter is not availab
le |
28 * or a fake for testing. | 42 * or a fake for testing. |
29 */ | 43 */ |
30 private ChromeBluetoothAdapter(Wrappers.BluetoothAdapterWrapper adapterWrapp
er) { | 44 public ChromeBluetoothAdapter( |
| 45 long nativeBluetoothAdapterAndroid, Wrappers.BluetoothAdapterWrapper
adapterWrapper) { |
| 46 mNativeBluetoothAdapterAndroid = nativeBluetoothAdapterAndroid; |
31 mAdapter = adapterWrapper; | 47 mAdapter = adapterWrapper; |
32 if (adapterWrapper == null) { | 48 if (adapterWrapper == null) { |
33 Log.i(TAG, "ChromeBluetoothAdapter created with no adapterWrapper.")
; | 49 Log.i(TAG, "ChromeBluetoothAdapter created with no adapterWrapper.")
; |
34 } else { | 50 } else { |
35 Log.i(TAG, "ChromeBluetoothAdapter created with provided adapterWrap
per."); | 51 Log.i(TAG, "ChromeBluetoothAdapter created with provided adapterWrap
per."); |
36 } | 52 } |
37 } | 53 } |
38 | 54 |
| 55 /** |
| 56 * Handles C++ object being destroyed. |
| 57 */ |
| 58 @CalledByNative |
| 59 private void onBluetoothAdapterAndroidDestruction() { |
| 60 stopScan(); |
| 61 mNativeBluetoothAdapterAndroid = 0; |
| 62 } |
| 63 |
39 // -------------------------------------------------------------------------
-------------------- | 64 // -------------------------------------------------------------------------
-------------------- |
40 // BluetoothAdapterAndroid methods implemented in java: | 65 // BluetoothAdapterAndroid methods implemented in java: |
41 | 66 |
42 // Implements BluetoothAdapterAndroid::Create. | 67 // Implements BluetoothAdapterAndroid::Create. |
43 // 'Object' type must be used because inner class Wrappers.BluetoothAdapterW
rapper reference is | 68 // 'Object' type must be used because inner class Wrappers.BluetoothAdapterW
rapper reference is |
44 // not handled by jni_generator.py JavaToJni. http://crbug.com/505554 | 69 // not handled by jni_generator.py JavaToJni. http://crbug.com/505554 |
45 @CalledByNative | 70 @CalledByNative |
46 public static ChromeBluetoothAdapter create(Object adapterWrapper) { | 71 private static ChromeBluetoothAdapter create( |
47 return new ChromeBluetoothAdapter((Wrappers.BluetoothAdapterWrapper) ada
pterWrapper); | 72 long nativeBluetoothAdapterAndroid, Object adapterWrapper) { |
| 73 return new ChromeBluetoothAdapter( |
| 74 nativeBluetoothAdapterAndroid, (Wrappers.BluetoothAdapterWrapper
) adapterWrapper); |
48 } | 75 } |
49 | 76 |
50 // Implements BluetoothAdapterAndroid::GetAddress. | 77 // Implements BluetoothAdapterAndroid::GetAddress. |
51 @CalledByNative | 78 @CalledByNative |
52 private String getAddress() { | 79 private String getAddress() { |
53 if (isPresent()) { | 80 if (isPresent()) { |
54 return mAdapter.getAddress(); | 81 return mAdapter.getAddress(); |
55 } else { | 82 } else { |
56 return ""; | 83 return ""; |
57 } | 84 } |
(...skipping 24 matching lines...) Expand all Loading... |
82 // Implements BluetoothAdapterAndroid::IsDiscoverable. | 109 // Implements BluetoothAdapterAndroid::IsDiscoverable. |
83 @CalledByNative | 110 @CalledByNative |
84 private boolean isDiscoverable() { | 111 private boolean isDiscoverable() { |
85 return isPresent() | 112 return isPresent() |
86 && mAdapter.getScanMode() == BluetoothAdapter.SCAN_MODE_CONNECTA
BLE_DISCOVERABLE; | 113 && mAdapter.getScanMode() == BluetoothAdapter.SCAN_MODE_CONNECTA
BLE_DISCOVERABLE; |
87 } | 114 } |
88 | 115 |
89 // Implements BluetoothAdapterAndroid::IsDiscovering. | 116 // Implements BluetoothAdapterAndroid::IsDiscovering. |
90 @CalledByNative | 117 @CalledByNative |
91 private boolean isDiscovering() { | 118 private boolean isDiscovering() { |
92 return isPresent() && mAdapter.isDiscovering(); | 119 return isPresent() && (mAdapter.isDiscovering() || mScanCallback != null
); |
93 } | 120 } |
| 121 |
| 122 // Implements BluetoothAdapterAndroid::AddDiscoverySession. |
| 123 @CalledByNative |
| 124 private boolean addDiscoverySession() { |
| 125 if (!isPowered()) { |
| 126 Log.d(TAG, "addDiscoverySession: Fails: !isPowered"); |
| 127 return false; |
| 128 } |
| 129 |
| 130 mNumDiscoverySessions++; |
| 131 Log.d(TAG, "addDiscoverySession: Now %d sessions.", mNumDiscoverySession
s); |
| 132 if (mNumDiscoverySessions > 1) { |
| 133 return true; |
| 134 } |
| 135 |
| 136 if (!startScan()) { |
| 137 mNumDiscoverySessions--; |
| 138 return false; |
| 139 } |
| 140 return true; |
| 141 } |
| 142 |
| 143 // Implements BluetoothAdapterAndroid::RemoveDiscoverySession. |
| 144 @CalledByNative |
| 145 private boolean removeDiscoverySession() { |
| 146 if (mNumDiscoverySessions == 0) { |
| 147 assert false; |
| 148 Log.w(TAG, "removeDiscoverySession: No scan in progress."); |
| 149 return false; |
| 150 } |
| 151 |
| 152 --mNumDiscoverySessions; |
| 153 |
| 154 if (mNumDiscoverySessions == 0) { |
| 155 Log.d(TAG, "removeDiscoverySession: Now 0 sessions. Stopping scan.")
; |
| 156 return stopScan(); |
| 157 } |
| 158 |
| 159 Log.d(TAG, "removeDiscoverySession: Now %d sessions.", mNumDiscoverySess
ions); |
| 160 return true; |
| 161 } |
| 162 |
| 163 // -------------------------------------------------------------------------
-------------------- |
| 164 // Implementation details: |
| 165 |
| 166 /** |
| 167 * Starts a Low Energy scan. |
| 168 * @return True on success. |
| 169 */ |
| 170 private boolean startScan() { |
| 171 // scanMode note: SCAN_FAILED_FEATURE_UNSUPPORTED is caused (at least on
some devices) if |
| 172 // setReportDelay() is used or if SCAN_MODE_LOW_LATENCY isn't used. |
| 173 int scanMode = ScanSettings.SCAN_MODE_LOW_LATENCY; |
| 174 |
| 175 assert mScanCallback == null; |
| 176 mScanCallback = new ScanCallback(); |
| 177 |
| 178 try { |
| 179 mAdapter.getBluetoothLeScanner().startScan(null /* filters */, scanM
ode, mScanCallback); |
| 180 } catch (IllegalArgumentException e) { |
| 181 Log.e(TAG, "Cannot start scan: " + e); |
| 182 return false; |
| 183 } |
| 184 return true; |
| 185 } |
| 186 |
| 187 /** |
| 188 * Stops the Low Energy scan. |
| 189 * @return True if a scan was in progress. |
| 190 */ |
| 191 private boolean stopScan() { |
| 192 if (mScanCallback == null) { |
| 193 return false; |
| 194 } |
| 195 try { |
| 196 mAdapter.getBluetoothLeScanner().stopScan(mScanCallback); |
| 197 } catch (IllegalArgumentException e) { |
| 198 Log.e(TAG, "Cannot stop scan: " + e); |
| 199 mScanCallback = null; |
| 200 return false; |
| 201 } |
| 202 mScanCallback = null; |
| 203 return true; |
| 204 } |
| 205 |
| 206 /** |
| 207 * Implements callbacks used during a Low Energy scan by notifying upon |
| 208 * devices discovered or detecting a scan failure. |
| 209 */ |
| 210 private class ScanCallback extends Wrappers.ScanCallbackWrapper { |
| 211 @Override |
| 212 public void onBatchScanResult(List<Wrappers.ScanResultWrapper> results)
{ |
| 213 Log.v(TAG, "onBatchScanResults"); |
| 214 } |
| 215 |
| 216 @Override |
| 217 public void onScanResult(int callbackType, Wrappers.ScanResultWrapper re
sult) { |
| 218 Log.v(TAG, "onScanResult %d %s %s", callbackType, result.getDevice()
.getAddress(), |
| 219 result.getDevice().getName()); |
| 220 } |
| 221 |
| 222 @Override |
| 223 public void onScanFailed(int errorCode) { |
| 224 Log.w(TAG, "onScanFailed: %d", errorCode); |
| 225 nativeOnScanFailed(mNativeBluetoothAdapterAndroid); |
| 226 mNumDiscoverySessions = 0; |
| 227 } |
| 228 } |
| 229 |
| 230 // -------------------------------------------------------------------------
-------------------- |
| 231 // BluetoothAdapterAndroid C++ methods declared for access from java: |
| 232 |
| 233 // Binds to BluetoothAdapterAndroid::OnScanFailed. |
| 234 private native void nativeOnScanFailed(long nativeBluetoothAdapterAndroid); |
94 } | 235 } |
OLD | NEW |