diff options
author | perja <perja@opera.com> | 2016-02-26 13:37:50 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-02-26 21:39:08 +0000 |
commit | 3a38a463d379e27cb72a3c0334f76ecf4f8de8c4 (patch) | |
tree | 22eece87bf34bdc0a6c143fa7068c2d701733760 /device | |
parent | 1369d7387a6e858a4be98e9dde29d2811fa95e31 (diff) | |
download | chromium_src-3a38a463d379e27cb72a3c0334f76ecf4f8de8c4.zip chromium_src-3a38a463d379e27cb72a3c0334f76ecf4f8de8c4.tar.gz chromium_src-3a38a463d379e27cb72a3c0334f76ecf4f8de8c4.tar.bz2 |
bluetooth: android: register for adapter on/off events.
Register for BluetoothAdapter.ACTION_STATE_CHANGED and reflect the
state changes in the device chooser dialog.
BUG=543060
Review URL: https://codereview.chromium.org/1711393002
Cr-Commit-Position: refs/heads/master@{#377982}
Diffstat (limited to 'device')
10 files changed, 134 insertions, 3 deletions
diff --git a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothAdapter.java b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothAdapter.java index 0a54a0b..54a8eb9 100644 --- a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothAdapter.java +++ b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothAdapter.java @@ -8,6 +8,10 @@ import android.Manifest; import android.annotation.TargetApi; import android.bluetooth.BluetoothAdapter; import android.bluetooth.le.ScanSettings; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.os.Build; import android.os.ParcelUuid; @@ -26,7 +30,7 @@ import java.util.List; */ @JNINamespace("device") @TargetApi(Build.VERSION_CODES.LOLLIPOP) -final class ChromeBluetoothAdapter { +final class ChromeBluetoothAdapter extends BroadcastReceiver { private static final String TAG = "Bluetooth"; private long mNativeBluetoothAdapterAndroid; @@ -49,6 +53,7 @@ final class ChromeBluetoothAdapter { long nativeBluetoothAdapterAndroid, Wrappers.BluetoothAdapterWrapper adapterWrapper) { mNativeBluetoothAdapterAndroid = nativeBluetoothAdapterAndroid; mAdapter = adapterWrapper; + registerBroadcastReceiver(); if (adapterWrapper == null) { Log.i(TAG, "ChromeBluetoothAdapter created with no adapterWrapper."); } else { @@ -63,6 +68,7 @@ final class ChromeBluetoothAdapter { private void onBluetoothAdapterAndroidDestruction() { stopScan(); mNativeBluetoothAdapterAndroid = 0; + unregisterBroadcastReceiver(); } // --------------------------------------------------------------------------------------------- @@ -187,6 +193,19 @@ final class ChromeBluetoothAdapter { || context.checkPermission(Manifest.permission.ACCESS_FINE_LOCATION); } + private void registerBroadcastReceiver() { + if (mAdapter != null) { + mAdapter.getContext().registerReceiver( + this, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)); + } + } + + private void unregisterBroadcastReceiver() { + if (mAdapter != null) { + mAdapter.getContext().unregisterReceiver(this); + } + } + /** * Starts a Low Energy scan. * @return True on success. @@ -275,6 +294,45 @@ final class ChromeBluetoothAdapter { } } + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + + if (isPresent() && BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) { + int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); + + Log.w(TAG, "onReceive: BluetoothAdapter.ACTION_STATE_CHANGED: %s", + getBluetoothStateString(state)); + + switch (state) { + case BluetoothAdapter.STATE_ON: + nativeOnAdapterStateChanged(mNativeBluetoothAdapterAndroid, true); + break; + case BluetoothAdapter.STATE_OFF: + nativeOnAdapterStateChanged(mNativeBluetoothAdapterAndroid, false); + break; + default: + // do nothing + } + } + } + + private String getBluetoothStateString(int state) { + switch (state) { + case BluetoothAdapter.STATE_OFF: + return "STATE_OFF"; + case BluetoothAdapter.STATE_ON: + return "STATE_ON"; + case BluetoothAdapter.STATE_TURNING_OFF: + return "STATE_TURNING_OFF"; + case BluetoothAdapter.STATE_TURNING_ON: + return "STATE_TURNING_ON"; + default: + assert false; + return "illegal state: " + state; + } + } + // --------------------------------------------------------------------------------------------- // BluetoothAdapterAndroid C++ methods declared for access from java: @@ -287,4 +345,8 @@ final class ChromeBluetoothAdapter { // http://crbug.com/505554 private native void nativeCreateOrUpdateDeviceOnScan(long nativeBluetoothAdapterAndroid, String address, Object bluetoothDeviceWrapper, List<ParcelUuid> advertisedUuids); + + // Binds to BluetoothAdapterAndroid::nativeOnAdapterStateChanged + private native void nativeOnAdapterStateChanged( + long nativeBluetoothAdapterAndroid, boolean powered); } diff --git a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java index 9287f85..96634b3 100644 --- a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java +++ b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java @@ -18,7 +18,10 @@ import android.bluetooth.le.ScanCallback; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanResult; import android.bluetooth.le.ScanSettings; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageManager; import android.os.Build; import android.os.ParcelUuid; @@ -163,6 +166,14 @@ class Wrappers { return mContext.checkPermission(permission, Process.myPid(), Process.myUid()) == PackageManager.PERMISSION_GRANTED; } + + public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { + return mContext.registerReceiver(receiver, filter); + } + + public void unregisterReceiver(BroadcastReceiver receiver) { + mContext.unregisterReceiver(receiver); + } } /** diff --git a/device/bluetooth/bluetooth_adapter.cc b/device/bluetooth/bluetooth_adapter.cc index 390bb93..dea3593 100644 --- a/device/bluetooth/bluetooth_adapter.cc +++ b/device/bluetooth/bluetooth_adapter.cc @@ -158,6 +158,11 @@ BluetoothDevice::PairingDelegate* BluetoothAdapter::DefaultPairingDelegate() { return pairing_delegates_.front().first; } +void BluetoothAdapter::NotifyAdapterStateChanged(bool powered) { + FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, + AdapterPoweredChanged(this, powered)); +} + void BluetoothAdapter::NotifyGattServiceAdded(BluetoothGattService* service) { DCHECK_EQ(service->GetDevice()->GetAdapter(), this); diff --git a/device/bluetooth/bluetooth_adapter.h b/device/bluetooth/bluetooth_adapter.h index e099e32..5dcf12f 100644 --- a/device/bluetooth/bluetooth_adapter.h +++ b/device/bluetooth/bluetooth_adapter.h @@ -398,8 +398,8 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothAdapter const CreateAdvertisementCallback& callback, const CreateAdvertisementErrorCallback& error_callback) = 0; - // The following methods are used to send various GATT observer events to - // observers. + // The following methods are used to send various events to observers. + void NotifyAdapterStateChanged(bool powered); void NotifyGattServiceAdded(BluetoothGattService* service); void NotifyGattServiceRemoved(BluetoothGattService* service); void NotifyGattServiceChanged(BluetoothGattService* service); diff --git a/device/bluetooth/bluetooth_adapter_android.cc b/device/bluetooth/bluetooth_adapter_android.cc index 00cead7..fc19a81 100644 --- a/device/bluetooth/bluetooth_adapter_android.cc +++ b/device/bluetooth/bluetooth_adapter_android.cc @@ -134,6 +134,13 @@ void BluetoothAdapterAndroid::RegisterAdvertisement( error_callback.Run(BluetoothAdvertisement::ERROR_UNSUPPORTED_PLATFORM); } +void BluetoothAdapterAndroid::OnAdapterStateChanged( + JNIEnv* env, + const JavaParamRef<jobject>& caller, + const bool powered) { + NotifyAdapterStateChanged(powered); +} + void BluetoothAdapterAndroid::OnScanFailed( JNIEnv* env, const JavaParamRef<jobject>& caller) { diff --git a/device/bluetooth/bluetooth_adapter_android.h b/device/bluetooth/bluetooth_adapter_android.h index 3612602..8ebb49c 100644 --- a/device/bluetooth/bluetooth_adapter_android.h +++ b/device/bluetooth/bluetooth_adapter_android.h @@ -83,6 +83,11 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterAndroid final const CreateAdvertisementCallback& callback, const CreateAdvertisementErrorCallback& error_callback) override; + // Called when adapter state changes. + void OnAdapterStateChanged(JNIEnv* env, + const base::android::JavaParamRef<jobject>& caller, + const bool powered); + // Handles a scan error event by invalidating all discovery sessions. void OnScanFailed(JNIEnv* env, const base::android::JavaParamRef<jobject>& caller); diff --git a/device/bluetooth/bluetooth_adapter_unittest.cc b/device/bluetooth/bluetooth_adapter_unittest.cc index a40af0e..55bffb7 100644 --- a/device/bluetooth/bluetooth_adapter_unittest.cc +++ b/device/bluetooth/bluetooth_adapter_unittest.cc @@ -660,31 +660,40 @@ TEST_F(BluetoothTest, DiscoverMultipleLowEnergyDevices) { #if defined(OS_ANDROID) TEST_F(BluetoothTest, TogglePowerFakeAdapter) { InitWithFakeAdapter(); + TestBluetoothAdapterObserver observer(adapter_); + ASSERT_TRUE(adapter_->IsPresent()); ASSERT_TRUE(adapter_->IsPowered()); + EXPECT_EQ(0, observer.powered_changed_count()); // Check if power can be turned off. adapter_->SetPowered(false, GetCallback(Call::EXPECTED), GetErrorCallback(Call::NOT_EXPECTED)); EXPECT_FALSE(adapter_->IsPowered()); + EXPECT_EQ(1, observer.powered_changed_count()); // Check if power can be turned on again. adapter_->SetPowered(true, GetCallback(Call::EXPECTED), GetErrorCallback(Call::NOT_EXPECTED)); EXPECT_TRUE(adapter_->IsPowered()); + EXPECT_EQ(2, observer.powered_changed_count()); } #endif // defined(OS_ANDROID) #if defined(OS_ANDROID) TEST_F(BluetoothTest, TogglePowerBeforeScan) { InitWithFakeAdapter(); + TestBluetoothAdapterObserver observer(adapter_); + ASSERT_TRUE(adapter_->IsPresent()); ASSERT_TRUE(adapter_->IsPowered()); + EXPECT_EQ(0, observer.powered_changed_count()); // Turn off adapter. adapter_->SetPowered(false, GetCallback(Call::EXPECTED), GetErrorCallback(Call::NOT_EXPECTED)); ASSERT_FALSE(adapter_->IsPowered()); + EXPECT_EQ(1, observer.powered_changed_count()); // Try to perform a scan. StartLowEnergyDiscoverySessionExpectedToFail(); @@ -693,6 +702,7 @@ TEST_F(BluetoothTest, TogglePowerBeforeScan) { adapter_->SetPowered(true, GetCallback(Call::EXPECTED), GetErrorCallback(Call::NOT_EXPECTED)); ASSERT_TRUE(adapter_->IsPowered()); + EXPECT_EQ(2, observer.powered_changed_count()); // Try to perform a scan again. ResetEventCounts(); diff --git a/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java b/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java index 538f618..46f9c66 100644 --- a/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java +++ b/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java @@ -9,7 +9,11 @@ import android.annotation.TargetApi; import android.bluetooth.BluetoothDevice; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanSettings; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; + import android.os.Build; import android.os.ParcelUuid; @@ -133,12 +137,14 @@ class Fakes { @Override public boolean disable() { mPowered = false; + nativeOnFakeAdapterStateChanged(mNativeBluetoothTestAndroid, false); return true; } @Override public boolean enable() { mPowered = true; + nativeOnFakeAdapterStateChanged(mNativeBluetoothTestAndroid, true); return true; } @@ -191,6 +197,14 @@ class Fakes { public boolean checkPermission(String permission) { return mPermissions.contains(permission); } + + @Override + public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { + return null; + } + + @Override + public void unregisterReceiver(BroadcastReceiver receiver) {} } /** @@ -715,6 +729,10 @@ class Fakes { // --------------------------------------------------------------------------------------------- // BluetoothTestAndroid C++ methods declared for access from java: + // Binds to BluetoothTestAndroid::OnFakeAdapterStateChanged. + private static native void nativeOnFakeAdapterStateChanged( + long nativeBluetoothTestAndroid, boolean powered); + // Binds to BluetoothTestAndroid::OnFakeBluetoothDeviceConnectGattCalled. private static native void nativeOnFakeBluetoothDeviceConnectGattCalled( long nativeBluetoothTestAndroid); diff --git a/device/bluetooth/test/bluetooth_test_android.cc b/device/bluetooth/test/bluetooth_test_android.cc index 43299bc..522cd61 100644 --- a/device/bluetooth/test/bluetooth_test_android.cc +++ b/device/bluetooth/test/bluetooth_test_android.cc @@ -356,4 +356,11 @@ void BluetoothTestAndroid::OnFakeBluetoothGattWriteDescriptor( base::android::JavaByteArrayToByteVector(env, value, &last_write_value_); } +void BluetoothTestAndroid::OnFakeAdapterStateChanged( + JNIEnv* env, + const JavaParamRef<jobject>& caller, + const bool powered) { + adapter_->NotifyAdapterStateChanged(powered); +} + } // namespace device diff --git a/device/bluetooth/test/bluetooth_test_android.h b/device/bluetooth/test/bluetooth_test_android.h index 3fb3a33..b855eca 100644 --- a/device/bluetooth/test/bluetooth_test_android.h +++ b/device/bluetooth/test/bluetooth_test_android.h @@ -118,6 +118,12 @@ class BluetoothTestAndroid : public BluetoothTestBase { const base::android::JavaParamRef<jobject>& caller, const base::android::JavaParamRef<jbyteArray>& value); + // Records that Java FakeBluetoothAdapter onAdapterStateChanged was called. + void OnFakeAdapterStateChanged( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& caller, + const bool powered); + base::android::ScopedJavaGlobalRef<jobject> j_fake_bluetooth_adapter_; int gatt_open_connections_ = 0; |