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 package org.chromium.device.bluetooth; | 5 package org.chromium.device.bluetooth; |
| 6 | 6 |
| 7 import android.Manifest; | 7 import android.Manifest; |
| 8 import android.bluetooth.le.ScanCallback; | |
| 9 import android.bluetooth.le.ScanResult; | |
| 10 import android.bluetooth.le.ScanSettings; | |
| 8 import android.content.Context; | 11 import android.content.Context; |
| 9 import android.content.ContextWrapper; | 12 import android.content.ContextWrapper; |
| 10 import android.content.pm.PackageManager; | 13 import android.content.pm.PackageManager; |
| 14 import android.os.Build; | |
| 11 | 15 |
| 12 import org.chromium.base.CalledByNative; | 16 import org.chromium.base.CalledByNative; |
| 13 import org.chromium.base.JNINamespace; | 17 import org.chromium.base.JNINamespace; |
| 14 import org.chromium.base.Log; | 18 import org.chromium.base.Log; |
| 15 | 19 |
| 20 import java.util.List; | |
| 21 | |
| 16 /** | 22 /** |
| 17 * Exposes android.bluetooth.BluetoothAdapter as necessary for C++ | 23 * Exposes android.bluetooth.BluetoothAdapter as necessary for C++ |
| 18 * device::BluetoothAdapterAndroid. | 24 * device::BluetoothAdapterAndroid. |
| 19 */ | 25 */ |
| 20 @JNINamespace("device") | 26 @JNINamespace("device") |
| 21 final class BluetoothAdapter { | 27 final class BluetoothAdapter { |
| 22 private static final String TAG = Log.makeTag("Bluetooth"); | 28 private static final String TAG = Log.makeTag("Bluetooth"); |
| 23 | 29 |
| 24 private final boolean mHasBluetoothPermission; | 30 private final boolean mHasBluetoothCapability; |
| 25 private android.bluetooth.BluetoothAdapter mAdapter; | 31 private android.bluetooth.BluetoothAdapter mAdapter; |
| 32 private int mNumDiscoverySessions = 0; | |
| 33 private ScanCallback mLeScanCallback; | |
| 34 | |
| 35 // ------------------------------------------------------------------------- -------------------- | |
| 36 // Construction: | |
| 26 | 37 |
| 27 @CalledByNative | 38 @CalledByNative |
| 28 private static BluetoothAdapter create(Context context) { | 39 private static BluetoothAdapter create(Context context) { |
| 29 return new BluetoothAdapter(context); | 40 return new BluetoothAdapter(context); |
| 30 } | 41 } |
| 31 | 42 |
| 32 @CalledByNative | 43 @CalledByNative |
| 33 private static BluetoothAdapter createWithoutPermissionForTesting(Context co ntext) { | 44 private static BluetoothAdapter createWithoutPermissionForTesting(Context co ntext) { |
| 34 Context contextWithoutPermission = new ContextWrapper(context) { | 45 Context contextWithoutPermission = new ContextWrapper(context) { |
| 35 @Override | 46 @Override |
| 36 public int checkCallingOrSelfPermission(String permission) { | 47 public int checkCallingOrSelfPermission(String permission) { |
| 37 return PackageManager.PERMISSION_DENIED; | 48 return PackageManager.PERMISSION_DENIED; |
| 38 } | 49 } |
| 39 }; | 50 }; |
| 40 return new BluetoothAdapter(contextWithoutPermission); | 51 return new BluetoothAdapter(contextWithoutPermission); |
| 41 } | 52 } |
| 42 | 53 |
| 43 // Constructs a BluetoothAdapter. | 54 // Constructs a BluetoothAdapter. |
| 44 private BluetoothAdapter(Context context) { | 55 private BluetoothAdapter(Context context) { |
| 45 mHasBluetoothPermission = | 56 final boolean hasMinAPI = Build.VERSION.SDK_INT >= Build.VERSION_CODES.L OLLIPOP; |
| 57 final boolean hasPermissions = | |
| 46 context.checkCallingOrSelfPermission(Manifest.permission.BLUETOO TH) | 58 context.checkCallingOrSelfPermission(Manifest.permission.BLUETOO TH) |
| 47 == PackageManager.PERMISSION_GRANTED | 59 == PackageManager.PERMISSION_GRANTED |
| 48 && context.checkCallingOrSelfPermission(Manifest.permission.BLUE TOOTH_ADMIN) | 60 && context.checkCallingOrSelfPermission(Manifest.permission.BLUE TOOTH_ADMIN) |
| 49 == PackageManager.PERMISSION_GRANTED; | 61 == PackageManager.PERMISSION_GRANTED; |
| 50 if (!mHasBluetoothPermission) { | 62 final boolean hasLowEnergyFeature = |
| 51 Log.w(TAG, | 63 context.getPackageManager().hasSystemFeature(PackageManager.FEAT URE_BLUETOOTH_LE); |
| 52 "Bluetooth API disabled; BLUETOOTH and BLUETOOTH_ADMIN permi ssions required."); | 64 mHasBluetoothCapability = hasMinAPI && hasPermissions && hasLowEnergyFea ture; |
| 65 if (!mHasBluetoothCapability) { | |
| 66 if (!hasMinAPI) { | |
| 67 Log.i(TAG, "Bluetooth API disabled; SDK version (%d) too low.", | |
|
ortuno
2015/05/21 16:48:53
You are logging a lot of stuff. We should probably
scheib
2015/05/22 01:26:46
I've moved the verbose bits to .d and .v, which ar
| |
| 68 Build.VERSION.SDK_INT); | |
| 69 } else if (!hasPermissions) { | |
| 70 Log.w(TAG, "Bluetooth API disabled; BLUETOOTH and BLUETOOTH_ADMI N permissions " | |
| 71 + "required."); | |
| 72 } else if (!hasLowEnergyFeature) { | |
| 73 Log.i(TAG, "Bluetooth API disabled; Low Energy not supported on system."); | |
| 74 } | |
| 53 return; | 75 return; |
| 54 } | 76 } |
| 55 | 77 |
| 56 mAdapter = android.bluetooth.BluetoothAdapter.getDefaultAdapter(); | 78 mAdapter = android.bluetooth.BluetoothAdapter.getDefaultAdapter(); |
| 57 if (mAdapter == null) Log.i(TAG, "No adapter found."); | 79 if (mAdapter == null) { |
| 58 } | 80 Log.i(TAG, "No adapter found."); |
| 59 | 81 } else { |
| 60 @CalledByNative | 82 Log.i(TAG, "BluetoothAdapter successfully constructed."); |
| 61 private boolean hasBluetoothPermission() { | 83 } |
| 62 return mHasBluetoothPermission; | |
| 63 } | 84 } |
| 64 | 85 |
| 65 // ------------------------------------------------------------------------- -------------------- | 86 // ------------------------------------------------------------------------- -------------------- |
| 66 // BluetoothAdapterAndroid.h interface: | 87 // Accessors @CalledByNative for BluetoothAdapterAndroid: |
| 88 | |
| 89 @CalledByNative | |
| 90 private boolean hasBluetoothCapability() { | |
| 91 return mHasBluetoothCapability; | |
| 92 } | |
| 93 | |
| 94 // ------------------------------------------------------------------------- -------------------- | |
| 95 // BluetoothAdapterAndroid interface @CalledByNative for BluetoothAdapterAnd roid: | |
| 67 | 96 |
| 68 @CalledByNative | 97 @CalledByNative |
| 69 private String getAddress() { | 98 private String getAddress() { |
| 70 if (isPresent()) { | 99 if (isPresent()) { |
| 71 return mAdapter.getAddress(); | 100 return mAdapter.getAddress(); |
| 72 } else { | 101 } else { |
| 73 return ""; | 102 return ""; |
| 74 } | 103 } |
| 75 } | 104 } |
| 76 | 105 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 97 private boolean isDiscoverable() { | 126 private boolean isDiscoverable() { |
| 98 return isPresent() | 127 return isPresent() |
| 99 && mAdapter.getScanMode() | 128 && mAdapter.getScanMode() |
| 100 == android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISC OVERABLE; | 129 == android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISC OVERABLE; |
| 101 } | 130 } |
| 102 | 131 |
| 103 @CalledByNative | 132 @CalledByNative |
| 104 private boolean isDiscovering() { | 133 private boolean isDiscovering() { |
| 105 return isPresent() && mAdapter.isDiscovering(); | 134 return isPresent() && mAdapter.isDiscovering(); |
| 106 } | 135 } |
| 136 | |
| 137 @CalledByNative | |
| 138 private boolean addDiscoverySession() { | |
|
ortuno
2015/05/21 16:48:53
nit: Add a comment for this function.
scheib
2015/05/22 01:26:46
Done.
| |
| 139 if (!isPowered()) { | |
| 140 Log.i(TAG, "addDiscoverySession: Fails: !isPowered"); | |
| 141 return false; | |
| 142 } | |
| 143 | |
| 144 if (mNumDiscoverySessions > 0) { | |
| 145 Log.i(TAG, "addDiscoverySession: Already scanning."); | |
| 146 return true; | |
| 147 } | |
| 148 Log.i(TAG, "addDiscoverySession"); | |
| 149 mNumDiscoverySessions++; | |
| 150 | |
| 151 ScanSettings.Builder scanSettingsBuilder = new ScanSettings.Builder(); | |
|
ortuno
2015/05/21 16:48:53
I would refactor this a bit:
ScanSettings scanSet
scheib
2015/05/22 01:26:46
Done.
scheib
2015/05/22 01:26:46
Done.
| |
| 152 // Note: SCAN_FAILED_FEATURE_UNSUPPORTED is caused (at least on some | |
| 153 // devices) if scanSettingsBuilder.setReportDelay() is set or if | |
| 154 // SCAN_MODE_LOW_LATENCY isn't used. | |
| 155 scanSettingsBuilder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY); | |
| 156 | |
| 157 if (mLeScanCallback == null) mLeScanCallback = new DiscoveryScanCallback (); | |
|
ortuno
2015/05/21 16:48:53
I think you need braces here:
https://google-styl
scheib
2015/05/22 01:26:45
Done.
| |
| 158 mAdapter.getBluetoothLeScanner().startScan( | |
| 159 null /* filters */, scanSettingsBuilder.build(), mLeScanCallback ); | |
| 160 return true; | |
| 161 } | |
| 162 | |
| 163 @CalledByNative | |
| 164 private boolean removeDiscoverySession() { | |
| 165 Log.i(TAG, "removeDiscoverySession"); | |
| 166 switch (--mNumDiscoverySessions) { | |
|
ortuno
2015/05/21 16:48:53
nit: I think it would be clearer this way:
if (mN
scheib
2015/05/22 01:26:46
Done.
| |
| 167 case -1: | |
| 168 assert false; | |
| 169 Log.w(TAG, "removeDiscoverySession: No scan in progress."); | |
| 170 mNumDiscoverySessions = 0; | |
| 171 return false; | |
| 172 case 0: | |
| 173 mAdapter.getBluetoothLeScanner().stopScan(mLeScanCallback); | |
| 174 } | |
| 175 return true; | |
| 176 } | |
| 177 | |
| 178 // ------------------------------------------------------------------------- -------------------- | |
| 179 // Implementation details: | |
| 180 | |
| 181 private class DiscoveryScanCallback extends ScanCallback { | |
| 182 @Override | |
| 183 public void onBatchScanResults(List<ScanResult> results) { | |
| 184 Log.i(TAG, "onBatchScanResults"); | |
| 185 } | |
| 186 | |
| 187 @Override | |
| 188 public void onScanResult(int callbackType, ScanResult result) { | |
| 189 Log.i(TAG, "onScanResult %s %s", result.getDevice().getAddress(), | |
| 190 result.getDevice().getName()); | |
| 191 } | |
| 192 | |
| 193 @Override | |
| 194 public void onScanFailed(int errorCode) { | |
| 195 Log.w(TAG, "onScanFailed: %d", errorCode); | |
| 196 // DISCUSS IN CODE REVIEW. | |
| 197 // | |
| 198 // TODO(scheib): Current device/bluetooth API doesn't support a way to communicate | |
| 199 // this asynchronous failure. If there was a way to communicate asyn chronous | |
| 200 // success, then the response to AddDiscoverySession would be delaye d until then or | |
| 201 // this error. But without only the error we must presume success. | |
| 202 // | |
| 203 // NEED ISSUE NUMBER. | |
| 204 } | |
| 205 } | |
| 107 } | 206 } |
| OLD | NEW |