summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--device/bluetooth/android/java/src/org/chromium/device/bluetooth/BluetoothAdapter.java75
-rw-r--r--device/bluetooth/bluetooth_adapter_android.cc37
-rw-r--r--device/bluetooth/bluetooth_adapter_android.h4
-rw-r--r--device/bluetooth/bluetooth_adapter_android_unittest.cc33
-rw-r--r--testing/android/native_test/java/AndroidManifest.xml3
5 files changed, 133 insertions, 19 deletions
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 07f6349..3c8b265 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
@@ -4,7 +4,9 @@
package org.chromium.device.bluetooth;
+import android.Manifest;
import android.content.Context;
+import android.content.ContextWrapper;
import android.content.pm.PackageManager;
import org.chromium.base.CalledByNative;
@@ -20,6 +22,7 @@ final class BluetoothAdapter {
private static final String TAG = Log.makeTag("Bluetooth");
private final boolean mHasBluetoothPermission;
+ private android.bluetooth.BluetoothAdapter mAdapter;
@CalledByNative
private static BluetoothAdapter create(Context context) {
@@ -27,16 +30,78 @@ final class BluetoothAdapter {
}
@CalledByNative
- private boolean hasBluetoothPermission() {
- return mHasBluetoothPermission;
+ private static BluetoothAdapter createWithoutPermissionForTesting(Context context) {
+ Context contextWithoutPermission = new ContextWrapper(context) {
+ @Override
+ public int checkCallingOrSelfPermission(String permission) {
+ return PackageManager.PERMISSION_DENIED;
+ }
+ };
+ return new BluetoothAdapter(contextWithoutPermission);
}
+ // Constructs a BluetoothAdapter.
private BluetoothAdapter(Context context) {
mHasBluetoothPermission =
- context.checkCallingOrSelfPermission(android.Manifest.permission.BLUETOOTH)
- == PackageManager.PERMISSION_GRANTED;
+ context.checkCallingOrSelfPermission(Manifest.permission.BLUETOOTH)
+ == PackageManager.PERMISSION_GRANTED
+ && context.checkCallingOrSelfPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ == PackageManager.PERMISSION_GRANTED;
if (!mHasBluetoothPermission) {
- Log.w(TAG, "Can not use bluetooth API, requires BLUETOOTH permission.");
+ Log.w(TAG,
+ "Bluetooth API disabled; BLUETOOTH and BLUETOOTH_ADMIN permissions required.");
+ return;
}
+
+ mAdapter = android.bluetooth.BluetoothAdapter.getDefaultAdapter();
+ if (mAdapter == null) Log.i(TAG, "No adapter found.");
+ }
+
+ @CalledByNative
+ private boolean hasBluetoothPermission() {
+ return mHasBluetoothPermission;
+ }
+
+ // ---------------------------------------------------------------------------------------------
+ // BluetoothAdapterAndroid.h interface:
+
+ @CalledByNative
+ private String getAddress() {
+ if (isPresent()) {
+ return mAdapter.getAddress();
+ } else {
+ return "";
+ }
+ }
+
+ @CalledByNative
+ private String getName() {
+ if (isPresent()) {
+ return mAdapter.getName();
+ } else {
+ return "";
+ }
+ }
+
+ @CalledByNative
+ private boolean isPresent() {
+ return mAdapter != null;
+ }
+
+ @CalledByNative
+ private boolean isPowered() {
+ return isPresent() && mAdapter.isEnabled();
+ }
+
+ @CalledByNative
+ private boolean isDiscoverable() {
+ return isPresent()
+ && mAdapter.getScanMode()
+ == android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
+ }
+
+ @CalledByNative
+ private boolean isDiscovering() {
+ return isPresent() && mAdapter.isDiscovering();
}
}
diff --git a/device/bluetooth/bluetooth_adapter_android.cc b/device/bluetooth/bluetooth_adapter_android.cc
index 0d4f140..0b8bea3 100644
--- a/device/bluetooth/bluetooth_adapter_android.cc
+++ b/device/bluetooth/bluetooth_adapter_android.cc
@@ -5,6 +5,7 @@
#include "device/bluetooth/bluetooth_adapter_android.h"
#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
@@ -12,6 +13,7 @@
#include "jni/BluetoothAdapter_jni.h"
using base::android::AttachCurrentThread;
+using base::android::ConvertJavaStringToUTF8;
namespace device {
@@ -25,6 +27,17 @@ base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter(
base::WeakPtr<BluetoothAdapterAndroid>
BluetoothAdapterAndroid::CreateAdapter() {
BluetoothAdapterAndroid* adapter = new BluetoothAdapterAndroid();
+ adapter->j_bluetooth_adapter_.Reset(Java_BluetoothAdapter_create(
+ AttachCurrentThread(), base::android::GetApplicationContext()));
+ return adapter->weak_ptr_factory_.GetWeakPtr();
+}
+
+base::WeakPtr<BluetoothAdapterAndroid>
+BluetoothAdapterAndroid::CreateAdapterWithoutPermissionForTesting() {
+ BluetoothAdapterAndroid* adapter = new BluetoothAdapterAndroid();
+ adapter->j_bluetooth_adapter_.Reset(
+ Java_BluetoothAdapter_createWithoutPermissionForTesting(
+ AttachCurrentThread(), base::android::GetApplicationContext()));
return adapter->weak_ptr_factory_.GetWeakPtr();
}
@@ -39,11 +52,13 @@ bool BluetoothAdapterAndroid::HasBluetoothPermission() const {
}
std::string BluetoothAdapterAndroid::GetAddress() const {
- return address_;
+ return ConvertJavaStringToUTF8(Java_BluetoothAdapter_getAddress(
+ AttachCurrentThread(), j_bluetooth_adapter_.obj()));
}
std::string BluetoothAdapterAndroid::GetName() const {
- return name_;
+ return ConvertJavaStringToUTF8(Java_BluetoothAdapter_getName(
+ AttachCurrentThread(), j_bluetooth_adapter_.obj()));
}
void BluetoothAdapterAndroid::SetName(const std::string& name,
@@ -58,13 +73,13 @@ bool BluetoothAdapterAndroid::IsInitialized() const {
}
bool BluetoothAdapterAndroid::IsPresent() const {
- NOTIMPLEMENTED();
- return false;
+ return Java_BluetoothAdapter_isPresent(AttachCurrentThread(),
+ j_bluetooth_adapter_.obj());
}
bool BluetoothAdapterAndroid::IsPowered() const {
- NOTIMPLEMENTED();
- return false;
+ return Java_BluetoothAdapter_isPowered(AttachCurrentThread(),
+ j_bluetooth_adapter_.obj());
}
void BluetoothAdapterAndroid::SetPowered(bool powered,
@@ -74,8 +89,8 @@ void BluetoothAdapterAndroid::SetPowered(bool powered,
}
bool BluetoothAdapterAndroid::IsDiscoverable() const {
- NOTIMPLEMENTED();
- return false;
+ return Java_BluetoothAdapter_isDiscoverable(AttachCurrentThread(),
+ j_bluetooth_adapter_.obj());
}
void BluetoothAdapterAndroid::SetDiscoverable(
@@ -86,8 +101,8 @@ void BluetoothAdapterAndroid::SetDiscoverable(
}
bool BluetoothAdapterAndroid::IsDiscovering() const {
- NOTIMPLEMENTED();
- return false;
+ return Java_BluetoothAdapter_isDiscovering(AttachCurrentThread(),
+ j_bluetooth_adapter_.obj());
}
void BluetoothAdapterAndroid::CreateRfcommService(
@@ -123,8 +138,6 @@ void BluetoothAdapterAndroid::RegisterAdvertisement(
}
BluetoothAdapterAndroid::BluetoothAdapterAndroid() : weak_ptr_factory_(this) {
- j_bluetooth_adapter_.Reset(Java_BluetoothAdapter_create(
- AttachCurrentThread(), base::android::GetApplicationContext()));
}
BluetoothAdapterAndroid::~BluetoothAdapterAndroid() {
diff --git a/device/bluetooth/bluetooth_adapter_android.h b/device/bluetooth/bluetooth_adapter_android.h
index cfb9d31..d458bb5 100644
--- a/device/bluetooth/bluetooth_adapter_android.h
+++ b/device/bluetooth/bluetooth_adapter_android.h
@@ -23,6 +23,10 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterAndroid final
// Create a BluetoothAdapterAndroid instance.
static base::WeakPtr<BluetoothAdapterAndroid> CreateAdapter();
+ // Create a BluetoothAdapterAndroid instance without Bluetooth permission.
+ static base::WeakPtr<BluetoothAdapterAndroid>
+ CreateAdapterWithoutPermissionForTesting();
+
// Register C++ methods exposed to Java using JNI.
static bool RegisterJNI(JNIEnv* env);
diff --git a/device/bluetooth/bluetooth_adapter_android_unittest.cc b/device/bluetooth/bluetooth_adapter_android_unittest.cc
index c4d5252..fcc9516 100644
--- a/device/bluetooth/bluetooth_adapter_android_unittest.cc
+++ b/device/bluetooth/bluetooth_adapter_android_unittest.cc
@@ -10,16 +10,47 @@ namespace device {
class BluetoothAdapterAndroidTest : public testing::Test {
protected:
- BluetoothAdapterAndroidTest() {
+ void InitWithPermission() {
adapter_ = BluetoothAdapterAndroid::CreateAdapter().get();
}
+ void InitWithoutPermission() {
+ adapter_ =
+ BluetoothAdapterAndroid::CreateAdapterWithoutPermissionForTesting()
+ .get();
+ }
+
scoped_refptr<BluetoothAdapterAndroid> adapter_;
};
TEST_F(BluetoothAdapterAndroidTest, Construct) {
+ InitWithPermission();
+ ASSERT_TRUE(adapter_.get());
+ EXPECT_TRUE(adapter_->HasBluetoothPermission());
+ if (!adapter_->IsPresent()) {
+ LOG(WARNING) << "Bluetooth adapter not present; skipping unit test.";
+ return;
+ }
+ EXPECT_GT(adapter_->GetAddress().length(), 0u);
+ EXPECT_GT(adapter_->GetName().length(), 0u);
+ EXPECT_TRUE(adapter_->IsPresent());
+ // Don't know on test machines if adapter will be powered or not, but
+ // the call should be safe to make and consistent.
+ EXPECT_EQ(adapter_->IsPowered(), adapter_->IsPowered());
+ EXPECT_FALSE(adapter_->IsDiscoverable());
+ EXPECT_FALSE(adapter_->IsDiscovering());
+}
+
+TEST_F(BluetoothAdapterAndroidTest, ConstructNoPermision) {
+ InitWithoutPermission();
ASSERT_TRUE(adapter_.get());
EXPECT_FALSE(adapter_->HasBluetoothPermission());
+ EXPECT_EQ(adapter_->GetAddress().length(), 0u);
+ EXPECT_EQ(adapter_->GetName().length(), 0u);
+ EXPECT_FALSE(adapter_->IsPresent());
+ EXPECT_FALSE(adapter_->IsPowered());
+ EXPECT_FALSE(adapter_->IsDiscoverable());
+ EXPECT_FALSE(adapter_->IsDiscovering());
}
} // namespace device
diff --git a/testing/android/native_test/java/AndroidManifest.xml b/testing/android/native_test/java/AndroidManifest.xml
index a92fb5f..37cc82d 100644
--- a/testing/android/native_test/java/AndroidManifest.xml
+++ b/testing/android/native_test/java/AndroidManifest.xml
@@ -11,7 +11,8 @@ found in the LICENSE file.
android:versionName="1.0">
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="22" />
-
+ <uses-permission android:name="android.permission.BLUETOOTH"/>
+ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>