Migrate BluetoothPbap GTS tests to CTS
Bug: 227548535
Test: atest BluetoothPbapTest
Change-Id: I3b2c8f680b66cca842f31f5b89353314cd420437
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPbapTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPbapTest.java
new file mode 100644
index 0000000..382a292
--- /dev/null
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPbapTest.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth.cts;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+
+import android.app.UiAutomation;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothPbap;
+import android.bluetooth.BluetoothProfile;
+import android.content.pm.PackageManager;
+import android.sysprop.BluetoothProperties;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class BluetoothPbapTest extends AndroidTestCase {
+ private static final String TAG = BluetoothPbapTest.class.getSimpleName();
+
+ private static final int PROXY_CONNECTION_TIMEOUT_MS = 500; // ms timeout for Proxy Connect
+
+ private boolean mHasBluetooth;
+ private BluetoothAdapter mAdapter;
+ private UiAutomation mUiAutomation;
+
+ private BluetoothPbap mBluetoothPbap;
+ private boolean mIsPbapSupported;
+ private boolean mIsProfileReady;
+ private Condition mConditionProfileIsConnected;
+ private ReentrantLock mProfileConnectedlock;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mHasBluetooth = getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_BLUETOOTH);
+
+ if (!mHasBluetooth) return;
+
+ mIsPbapSupported = BluetoothProperties.isProfilePbapServerEnabled().orElse(false);
+ if (!mIsPbapSupported) return;
+
+ mUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED);
+
+ BluetoothManager manager = getContext().getSystemService(BluetoothManager.class);
+ mAdapter = manager.getAdapter();
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+ mProfileConnectedlock = new ReentrantLock();
+ mConditionProfileIsConnected = mProfileConnectedlock.newCondition();
+ mIsProfileReady = false;
+ mBluetoothPbap = null;
+
+ mAdapter.getProfileProxy(getContext(), new BluetoothPbapServiceListener(),
+ BluetoothProfile.PBAP);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ if (!(mHasBluetooth && mIsPbapSupported)) {
+ return;
+ }
+ if (mAdapter != null && mBluetoothPbap != null) {
+ mAdapter.closeProfileProxy(BluetoothProfile.PBAP,
+ mBluetoothPbap);
+ mBluetoothPbap = null;
+ mIsProfileReady = false;
+ }
+ if (mAdapter != null) {
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ }
+ mAdapter = null;
+ }
+
+ public void test_getConnectedDevices() {
+ if (!(mHasBluetooth && mIsPbapSupported)) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothPbap);
+
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+
+ // Verify returns empty list if bluetooth is not enabled
+ List<BluetoothDevice> connectedDevices = mBluetoothPbap.getConnectedDevices();
+ assertTrue(connectedDevices.isEmpty());
+ }
+
+ public void test_getConnectionState() {
+ if (!(mHasBluetooth && mIsPbapSupported)) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothPbap);
+
+ BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
+
+ // Verify returns false when invalid input is given
+ assertEquals(BluetoothProfile.STATE_DISCONNECTED,
+ mBluetoothPbap.getConnectionState(null));
+
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+
+ // Verify returns false if bluetooth is not enabled
+ assertEquals(BluetoothProfile.STATE_DISCONNECTED,
+ mBluetoothPbap.getConnectionState(testDevice));
+ }
+
+ public void test_getDevicesMatchingConnectionStates() {
+ if (!(mHasBluetooth && mIsPbapSupported)) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothPbap);
+
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+
+ // Verify returns empty list if bluetooth is not enabled
+ List<BluetoothDevice> connectedDevices =
+ mBluetoothPbap.getDevicesMatchingConnectionStates(new int[]{});
+ assertTrue(connectedDevices.isEmpty());
+ }
+
+ public void test_setConnectionPolicy() {
+ if (!(mHasBluetooth && mIsPbapSupported)) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothPbap);
+
+ BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
+
+ // Verify returns false when invalid input is given
+ assertFalse(mBluetoothPbap.setConnectionPolicy(
+ testDevice, BluetoothProfile.CONNECTION_POLICY_UNKNOWN));
+ assertFalse(mBluetoothPbap.setConnectionPolicy(
+ null, BluetoothProfile.CONNECTION_POLICY_ALLOWED));
+
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+
+ // Verify returns false if bluetooth is not enabled
+ assertFalse(mBluetoothPbap.setConnectionPolicy(
+ testDevice, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN));
+ }
+
+ private boolean waitForProfileConnect() {
+ mProfileConnectedlock.lock();
+ try {
+ // Wait for the Adapter to be disabled
+ while (!mIsProfileReady) {
+ if (!mConditionProfileIsConnected.await(
+ PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+ // Timeout
+ Log.e(TAG, "Timeout while waiting for Profile Connect");
+ break;
+ } // else spurious wakeups
+ }
+ } catch (InterruptedException e) {
+ Log.e(TAG, "waitForProfileConnect: interrupted");
+ } finally {
+ mProfileConnectedlock.unlock();
+ }
+ return mIsProfileReady;
+ }
+
+ private final class BluetoothPbapServiceListener implements
+ BluetoothProfile.ServiceListener {
+
+ @Override
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ mProfileConnectedlock.lock();
+ try {
+ mBluetoothPbap = (BluetoothPbap) proxy;
+ mIsProfileReady = true;
+ mConditionProfileIsConnected.signal();
+ } finally {
+ mProfileConnectedlock.unlock();
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(int profile) {
+ }
+ }
+}