Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2923)

Unified Diff: device/bluetooth/android/java/src/org/chromium/device/bluetooth/BluetoothAdapter.java

Issue 1150833002: bluetooth: android: Initial Low Energy Discovery Sessions. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@bta-manifest-
Patch Set: addressed tedchoc's comments Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/android/shell/java/AndroidManifest.xml.jinja2 ('k') | device/bluetooth/bluetooth_adapter_android.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: device/bluetooth/android/java/src/org/chromium/device/bluetooth/BluetoothAdapter.java
diff --git a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/BluetoothAdapter.java b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/BluetoothAdapter.java
index 3c8b26521f600895c60f8deadbf46b72bfc27f73..b6dca7909f143c8f03c90672936ad38909dfe20a 100644
--- a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/BluetoothAdapter.java
+++ b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/BluetoothAdapter.java
@@ -5,66 +5,107 @@
package org.chromium.device.bluetooth;
import android.Manifest;
+import android.annotation.TargetApi;
+import android.bluetooth.le.ScanCallback;
+import android.bluetooth.le.ScanResult;
+import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.PackageManager;
+import android.os.Build;
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import org.chromium.base.Log;
+import java.util.List;
+
/**
* Exposes android.bluetooth.BluetoothAdapter as necessary for C++
* device::BluetoothAdapterAndroid.
*/
@JNINamespace("device")
+@TargetApi(Build.VERSION_CODES.LOLLIPOP)
final class BluetoothAdapter {
private static final String TAG = Log.makeTag("Bluetooth");
- private final boolean mHasBluetoothPermission;
+ private final long mNativeCPPObject;
Ted C 2015/05/27 01:13:39 Normally, we'd do mNativeBluetoothAdapter
scheib 2015/05/27 02:21:54 Done.
+ private final boolean mHasBluetoothCapability;
private android.bluetooth.BluetoothAdapter mAdapter;
+ private int mNumDiscoverySessions;
+ private ScanCallback mLeScanCallback;
+
+ // ---------------------------------------------------------------------------------------------
+ // Construction:
@CalledByNative
- private static BluetoothAdapter create(Context context) {
- return new BluetoothAdapter(context);
+ private static BluetoothAdapter create(Context context, long nativeCPPObject) {
+ return new BluetoothAdapter(context, nativeCPPObject);
}
@CalledByNative
- private static BluetoothAdapter createWithoutPermissionForTesting(Context context) {
+ private static BluetoothAdapter createWithoutPermissionForTesting(
+ Context context, long nativeCPPObject) {
Context contextWithoutPermission = new ContextWrapper(context) {
@Override
public int checkCallingOrSelfPermission(String permission) {
return PackageManager.PERMISSION_DENIED;
}
};
- return new BluetoothAdapter(contextWithoutPermission);
+ return new BluetoothAdapter(contextWithoutPermission, nativeCPPObject);
}
// Constructs a BluetoothAdapter.
- private BluetoothAdapter(Context context) {
- mHasBluetoothPermission =
+ private BluetoothAdapter(Context context, long nativeCPPObject) {
+ mNativeCPPObject = nativeCPPObject;
+ final boolean hasMinAPI = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
+ final boolean hasPermissions =
context.checkCallingOrSelfPermission(Manifest.permission.BLUETOOTH)
== PackageManager.PERMISSION_GRANTED
&& context.checkCallingOrSelfPermission(Manifest.permission.BLUETOOTH_ADMIN)
== PackageManager.PERMISSION_GRANTED;
- if (!mHasBluetoothPermission) {
- Log.w(TAG,
- "Bluetooth API disabled; BLUETOOTH and BLUETOOTH_ADMIN permissions required.");
+ final boolean hasLowEnergyFeature =
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2
+ && context.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_BLUETOOTH_LE);
+ mHasBluetoothCapability = hasMinAPI && hasPermissions && hasLowEnergyFeature;
+ if (!mHasBluetoothCapability) {
+ if (!hasMinAPI) {
+ Log.i(TAG, "Bluetooth API disabled; SDK version (%d) too low.",
+ Build.VERSION.SDK_INT);
+ } else if (!hasPermissions) {
+ Log.w(TAG, "Bluetooth API disabled; BLUETOOTH and BLUETOOTH_ADMIN permissions "
+ + "required.");
Ted C 2015/05/27 01:13:39 this is indented too much...should be 8
scheib 2015/05/27 02:21:54 This is enforced by 'git cl format', and reset if
+ } else if (!hasLowEnergyFeature) {
+ Log.i(TAG, "Bluetooth API disabled; Low Energy not supported on system.");
+ }
return;
}
mAdapter = android.bluetooth.BluetoothAdapter.getDefaultAdapter();
- if (mAdapter == null) Log.i(TAG, "No adapter found.");
+ if (mAdapter == null) {
+ Log.i(TAG, "No adapter found.");
+ } else {
+ Log.i(TAG, "BluetoothAdapter successfully constructed.");
+ }
}
- @CalledByNative
- private boolean hasBluetoothPermission() {
- return mHasBluetoothPermission;
- }
+ // ---------------------------------------------------------------------------------------------
+ // BluetoothAdapterAndroid C++ methods declared for access from java:
+
+ // Binds to BluetoothAdapterAndroid::OnScanFailed.
+ private native void nativeOnScanFailed(long nativeBluetoothAdapterAndroid);
Ted C 2015/05/27 01:13:39 We typically put native ones at the bottom since t
scheib 2015/05/27 02:21:54 Done.
// ---------------------------------------------------------------------------------------------
- // BluetoothAdapterAndroid.h interface:
+ // BluetoothAdapterAndroid methods implemented in java:
+ // Implements BluetoothAdapterAndroid::HasBluetoothCapability.
+ @CalledByNative
+ private boolean hasBluetoothCapability() {
+ return mHasBluetoothCapability;
+ }
+
+ // Implements BluetoothAdapterAndroid::GetAddress.
@CalledByNative
private String getAddress() {
if (isPresent()) {
@@ -74,6 +115,7 @@ final class BluetoothAdapter {
}
}
+ // Implements BluetoothAdapterAndroid::GetName.
@CalledByNative
private String getName() {
if (isPresent()) {
@@ -83,16 +125,19 @@ final class BluetoothAdapter {
}
}
+ // Implements BluetoothAdapterAndroid::IsPresent.
@CalledByNative
private boolean isPresent() {
return mAdapter != null;
}
+ // Implements BluetoothAdapterAndroid::IsPowered.
@CalledByNative
private boolean isPowered() {
return isPresent() && mAdapter.isEnabled();
}
+ // Implements BluetoothAdapterAndroid::IsDiscoverable.
@CalledByNative
private boolean isDiscoverable() {
return isPresent()
@@ -100,8 +145,88 @@ final class BluetoothAdapter {
== android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
}
+ // Implements BluetoothAdapterAndroid::IsDiscovering.
@CalledByNative
private boolean isDiscovering() {
return isPresent() && mAdapter.isDiscovering();
}
+
+ // Implements BluetoothAdapterAndroid::AddDiscoverySession.
+ @CalledByNative
+ private boolean addDiscoverySession() {
+ if (!isPowered()) {
+ Log.d(TAG, "addDiscoverySession: Fails: !isPowered");
+ return false;
+ }
+
+ mNumDiscoverySessions++;
+ Log.d(TAG, "addDiscoverySession: Now %d sessions", mNumDiscoverySessions);
+ if (mNumDiscoverySessions > 1) {
+ return true;
+ }
+
+ // ScanSettings Note: SCAN_FAILED_FEATURE_UNSUPPORTED is caused (at least on some devices)
+ // if setReportDelay() is used or if SCAN_MODE_LOW_LATENCY isn't used.
+ ScanSettings scanSettings =
+ new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
+
+ if (mLeScanCallback == null) {
+ mLeScanCallback = new DiscoveryScanCallback();
+ }
+ mAdapter.getBluetoothLeScanner().startScan(
+ null /* filters */, scanSettings, mLeScanCallback);
+ return true;
+ }
+
+ // Implements BluetoothAdapterAndroid::RemoveDiscoverySession.
+ @CalledByNative
+ private boolean removeDiscoverySession() {
Ted C 2015/05/27 01:13:39 is this guaranteed to be called if during the dest
scheib 2015/05/27 02:21:54 Done. The scan will now be stopped upon C++ object
+ if (mNumDiscoverySessions == 0) {
+ assert false;
+ Log.w(TAG, "removeDiscoverySession: No scan in progress.");
+ return false;
+ }
+
+ --mNumDiscoverySessions;
+
+ if (mNumDiscoverySessions == 0) {
+ Log.d(TAG, "removeDiscoverySession: Stopping scan.");
+ mAdapter.getBluetoothLeScanner().stopScan(mLeScanCallback);
+ } else {
+ Log.d(TAG, "removeDiscoverySession: Now %d sessions", mNumDiscoverySessions);
+ }
+
+ return true;
+ }
+
+ // ---------------------------------------------------------------------------------------------
+ // Implementation details:
+
+ private class DiscoveryScanCallback extends ScanCallback {
+ @Override
+ public void onBatchScanResults(List<ScanResult> results) {
+ Log.v(TAG, "onBatchScanResults");
+ }
+
+ @Override
+ public void onScanResult(int callbackType, ScanResult result) {
+ Log.v(TAG, "onScanResult %s %s", result.getDevice().getAddress(),
+ result.getDevice().getName());
+ }
+
+ @Override
+ public void onScanFailed(int errorCode) {
+ Log.w(TAG, "onScanFailed: %d", errorCode);
+ // DISCUSS IN CODE REVIEW.
+ //
+ // TODO(scheib): Current device/bluetooth API doesn't support a way to communicate
+ // this asynchronous failure. If there was a way to communicate asynchronous
+ // success, then the response to AddDiscoverySession would be delayed until then or
+ // this error. But without only the error we must presume success.
+ //
+ //
+ // NEED ISSUE NUMBER.
+ nativeOnScanFailed(mNativeCPPObject);
+ }
+ }
}
« no previous file with comments | « chrome/android/shell/java/AndroidManifest.xml.jinja2 ('k') | device/bluetooth/bluetooth_adapter_android.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698