diff options
author | scheib <scheib@chromium.org> | 2015-05-11 17:09:38 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-05-12 00:10:39 +0000 |
commit | 4261538f2e98c39395931e9e79fc5a3a4ddbf23f (patch) | |
tree | 84904cca6f6c715e83f0af4e41e8df57f263c28a | |
parent | 7cdcf50b4ae3858f5132a1bb0d4cb5e104527b42 (diff) | |
download | chromium_src-4261538f2e98c39395931e9e79fc5a3a4ddbf23f.zip chromium_src-4261538f2e98c39395931e9e79fc5a3a4ddbf23f.tar.gz chromium_src-4261538f2e98c39395931e9e79fc5a3a4ddbf23f.tar.bz2 |
bluetooth: Android adapter can be created with and without Bluetooth permission.
This enables unit tests to run with Bluetooth permission,
by adding the Bluetooth permission to native_test.
Non-test applications will not have the Bluetooth permission,
and unit tests should also verify behavior
when the permission is not given. To enable this
createWithoutPermissionForTesting is added and
results in a state equivalent to when the permission
is not available.
Unit tests will be built in parallel for both when Bluetooth
permission exists and doesn't.
BUG=471536
Committed: https://crrev.com/30e81472dc168ea1c331a8779b3f6a14f684c54b
Cr-Commit-Position: refs/heads/master@{#329212}
Review URL: https://codereview.chromium.org/1129683002
Cr-Commit-Position: refs/heads/master@{#329286}
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"/> |