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 paired C++ | |
armansito
2015/06/30 20:37:22
I'd say "coupled" or "associated" rather than pair
scheib
2015/06/30 21:02:14
Done.
| |
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 private 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 public 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 return true; | |
138 } else { | |
armansito
2015/06/30 20:37:22
No need for else since you have an early return
scheib
2015/06/30 21:02:14
Done.
| |
139 mNumDiscoverySessions--; | |
140 return false; | |
141 } | |
142 } | |
143 | |
144 // Implements BluetoothAdapterAndroid::RemoveDiscoverySession. | |
145 @CalledByNative | |
146 private boolean removeDiscoverySession() { | |
147 if (mNumDiscoverySessions == 0) { | |
148 assert false; | |
149 Log.w(TAG, "removeDiscoverySession: No scan in progress."); | |
150 return false; | |
151 } | |
152 | |
153 --mNumDiscoverySessions; | |
154 | |
155 if (mNumDiscoverySessions == 0) { | |
156 Log.d(TAG, "removeDiscoverySession: Now 0 sessions. Stopping scan.") ; | |
157 return stopScan(); | |
armansito
2015/06/30 20:37:22
no need for else
scheib
2015/06/30 21:02:14
Done.
| |
158 } else { | |
159 Log.d(TAG, "removeDiscoverySession: Now %d sessions.", mNumDiscovery Sessions); | |
160 } | |
161 return true; | |
162 } | |
163 | |
164 // ------------------------------------------------------------------------- -------------------- | |
165 // Implementation details: | |
166 | |
167 /** | |
168 * Starts a Low Energy scan. | |
169 * @return True on success. | |
170 */ | |
171 private boolean startScan() { | |
172 // ScanSettings Note: SCAN_FAILED_FEATURE_UNSUPPORTED is caused (at leas t on some devices) | |
173 // if setReportDelay() is used or if SCAN_MODE_LOW_LATENCY isn't used. | |
174 ScanSettings scanSettings = | |
175 new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LO W_LATENCY).build(); | |
176 | |
177 assert mScanCallback == null; | |
178 mScanCallback = new ScanCallback(); | |
179 | |
180 try { | |
181 mAdapter.getBluetoothLeScanner().startScan( | |
182 null /* filters */, scanSettings, mScanCallback); | |
183 } catch (IllegalArgumentException e) { | |
184 Log.e(TAG, "Cannot start scan: " + e); | |
185 return false; | |
186 } | |
187 return true; | |
188 } | |
189 | |
190 /** | |
191 * Stops the Low Energy scan. | |
192 * @return True if a scan was in progress. | |
193 */ | |
194 private boolean stopScan() { | |
195 if (mScanCallback == null) { | |
196 return false; | |
197 } | |
198 try { | |
199 mAdapter.getBluetoothLeScanner().stopScan(mScanCallback); | |
200 } catch (IllegalArgumentException e) { | |
201 Log.e(TAG, "Cannot stop scan: " + e); | |
202 mScanCallback = null; | |
203 return false; | |
204 } | |
205 mScanCallback = null; | |
206 return true; | |
207 } | |
208 | |
209 /** | |
210 * Implements callbacks used during a Low Energy scan by notifying upon | |
211 * devices discovered or detecting a scan failure. | |
212 */ | |
213 private class ScanCallback extends Wrappers.ScanCallbackWrapper { | |
214 @Override | |
215 public void onBatchScanResultWrappers(List<Wrappers.ScanResultWrapper> r esults) { | |
216 Log.v(TAG, "onBatchScanResults"); | |
217 } | |
218 | |
219 @Override | |
220 public void onScanResultWrapper(int callbackType, Wrappers.ScanResultWra pper result) { | |
221 Log.v(TAG, "onScanResult %d %s %s", callbackType, result.getDevice() .getAddress(), | |
222 result.getDevice().getName()); | |
223 } | |
224 | |
225 @Override | |
226 public void onScanFailed(int errorCode) { | |
227 Log.w(TAG, "onScanFailed: %d", errorCode); | |
228 nativeOnScanFailed(mNativeBluetoothAdapterAndroid); | |
229 mNumDiscoverySessions = 0; | |
230 } | |
231 } | |
232 | |
233 // ------------------------------------------------------------------------- -------------------- | |
234 // BluetoothAdapterAndroid C++ methods declared for access from java: | |
235 | |
236 // Binds to BluetoothAdapterAndroid::OnScanFailed. | |
237 private native void nativeOnScanFailed(long nativeBluetoothAdapterAndroid); | |
94 } | 238 } |
OLD | NEW |