| /* |
| * Copyright (C) 2009 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 static org.junit.Assert.assertThrows; |
| |
| import android.annotation.NonNull; |
| import android.app.UiAutomation; |
| import android.bluetooth.BluetoothActivityEnergyInfo; |
| import android.bluetooth.BluetoothAdapter; |
| import android.bluetooth.BluetoothDevice; |
| import android.bluetooth.BluetoothManager; |
| import android.bluetooth.BluetoothProfile; |
| import android.bluetooth.BluetoothServerSocket; |
| import android.bluetooth.BluetoothStatusCodes; |
| 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.test.AndroidTestCase; |
| import android.util.Log; |
| |
| import androidx.test.InstrumentationRegistry; |
| |
| import com.android.compatibility.common.util.ApiLevelUtil; |
| |
| import java.io.IOException; |
| import java.time.Duration; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.UUID; |
| import java.util.concurrent.Executor; |
| import java.util.concurrent.TimeUnit; |
| import java.util.concurrent.locks.Condition; |
| import java.util.concurrent.locks.ReentrantLock; |
| |
| /** |
| * Very basic test, just of the static methods of {@link |
| * BluetoothAdapter}. |
| */ |
| public class BluetoothAdapterTest extends AndroidTestCase { |
| private static final String TAG = "BluetoothAdapterTest"; |
| private static final int SET_NAME_TIMEOUT = 5000; // ms timeout for setting adapter name |
| |
| private boolean mHasBluetooth; |
| private ReentrantLock mAdapterNameChangedlock; |
| private Condition mConditionAdapterNameChanged; |
| private boolean mIsAdapterNameChanged; |
| |
| private BluetoothAdapter mAdapter; |
| private UiAutomation mUiAutomation; |
| |
| @Override |
| public void setUp() throws Exception { |
| super.setUp(); |
| |
| mHasBluetooth = getContext().getPackageManager().hasSystemFeature( |
| PackageManager.FEATURE_BLUETOOTH); |
| if (mHasBluetooth) { |
| mAdapter = getContext().getSystemService(BluetoothManager.class).getAdapter(); |
| assertNotNull(mAdapter); |
| mUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); |
| mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT); |
| } |
| mAdapterNameChangedlock = new ReentrantLock(); |
| mConditionAdapterNameChanged = mAdapterNameChangedlock.newCondition(); |
| mIsAdapterNameChanged = false; |
| } |
| |
| @Override |
| public void tearDown() throws Exception { |
| if (mHasBluetooth) { |
| mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT); |
| assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext)); |
| mUiAutomation.dropShellPermissionIdentity(); |
| } |
| } |
| |
| public void test_getDefaultAdapter() { |
| /* |
| * Note: If the target doesn't support Bluetooth at all, then |
| * this method should return null. |
| */ |
| if (mHasBluetooth) { |
| assertNotNull(BluetoothAdapter.getDefaultAdapter()); |
| } else { |
| assertNull(BluetoothAdapter.getDefaultAdapter()); |
| } |
| } |
| |
| public void test_checkBluetoothAddress() { |
| // Can't be null. |
| assertFalse(BluetoothAdapter.checkBluetoothAddress(null)); |
| |
| // Must be 17 characters long. |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("0")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:0")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:0")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:0")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:00")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:00:")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:00:0")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:00:00")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:00:00:")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:00:00:0")); |
| |
| // Must have colons between octets. |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00x00:00:00:00:00")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00.00:00:00:00")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00-00:00:00")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:00900:00")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:00:00?00")); |
| |
| // Hex letters must be uppercase. |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("a0:00:00:00:00:00")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("0b:00:00:00:00:00")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:c0:00:00:00:00")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:0d:00:00:00:00")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:e0:00:00:00")); |
| assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:0f:00:00:00")); |
| |
| assertTrue(BluetoothAdapter.checkBluetoothAddress("00:00:00:00:00:00")); |
| assertTrue(BluetoothAdapter.checkBluetoothAddress("12:34:56:78:9A:BC")); |
| assertTrue(BluetoothAdapter.checkBluetoothAddress("DE:F0:FE:DC:B8:76")); |
| } |
| |
| /** Checks enable(), disable(), getState(), isEnabled() */ |
| public void test_enableDisable() { |
| if (!mHasBluetooth) { |
| // Skip the test if bluetooth is not present. |
| return; |
| } |
| |
| for (int i = 0; i < 5; i++) { |
| assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext)); |
| assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext)); |
| } |
| } |
| |
| public void test_getAddress() { |
| if (!mHasBluetooth) { |
| // Skip the test if bluetooth is not present. |
| return; |
| } |
| assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext)); |
| assertTrue(BluetoothAdapter.checkBluetoothAddress(mAdapter.getAddress())); |
| |
| mUiAutomation.dropShellPermissionIdentity(); |
| assertThrows(SecurityException.class, () -> mAdapter.getAddress()); |
| |
| } |
| |
| public void test_setName_getName() { |
| if (!mHasBluetooth) { |
| // Skip the test if bluetooth is not present. |
| return; |
| } |
| assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext)); |
| |
| IntentFilter filter = new IntentFilter(); |
| filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); |
| filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); |
| mContext.registerReceiver(mAdapterNameChangeReceiver, filter); |
| |
| String name = mAdapter.getName(); |
| assertNotNull(name); |
| |
| // Check renaming the adapter |
| String genericName = "Generic Device 1"; |
| mIsAdapterNameChanged = false; |
| assertTrue(mAdapter.setName(genericName)); |
| assertTrue(waitForAdapterNameChange()); |
| mIsAdapterNameChanged = false; |
| assertEquals(genericName, mAdapter.getName()); |
| |
| // Check setting adapter back to original name |
| assertTrue(mAdapter.setName(name)); |
| assertTrue(waitForAdapterNameChange()); |
| mIsAdapterNameChanged = false; |
| assertEquals(name, mAdapter.getName()); |
| |
| mUiAutomation.dropShellPermissionIdentity(); |
| assertThrows(SecurityException.class, () -> mAdapter.setName("The name")); |
| assertThrows(SecurityException.class, () -> mAdapter.getName()); |
| } |
| |
| public void test_getBondedDevices() { |
| if (!mHasBluetooth) { |
| // Skip the test if bluetooth is not present. |
| return; |
| } |
| assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext)); |
| |
| // empty value is returned when Bluetooth is disabled |
| Set<BluetoothDevice> devices = mAdapter.getBondedDevices(); |
| assertNotNull(devices); |
| assertTrue(devices.isEmpty()); |
| |
| assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext)); |
| devices = mAdapter.getBondedDevices(); |
| assertNotNull(devices); |
| for (BluetoothDevice device : devices) { |
| assertTrue(BluetoothAdapter.checkBluetoothAddress(device.getAddress())); |
| } |
| |
| mUiAutomation.dropShellPermissionIdentity(); |
| assertThrows(SecurityException.class, () -> mAdapter.getBondedDevices()); |
| |
| } |
| |
| public void test_getRemoteDevice() { |
| if (!mHasBluetooth) { |
| // Skip the test if bluetooth is not present. |
| return; |
| } |
| // getRemoteDevice() should work even with Bluetooth disabled |
| assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext)); |
| mUiAutomation.dropShellPermissionIdentity(); |
| |
| // test bad addresses |
| assertThrows(IllegalArgumentException.class, () -> mAdapter.getRemoteDevice((String) null)); |
| assertThrows(IllegalArgumentException.class, () -> |
| mAdapter.getRemoteDevice("00:00:00:00:00:00:00:00")); |
| assertThrows(IllegalArgumentException.class, () -> mAdapter.getRemoteDevice((byte[]) null)); |
| assertThrows(IllegalArgumentException.class, () -> |
| mAdapter.getRemoteDevice(new byte[] {0x00, 0x00, 0x00, 0x00, 0x00})); |
| |
| // test success |
| BluetoothDevice device = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC"); |
| assertNotNull(device); |
| assertEquals("00:11:22:AA:BB:CC", device.getAddress()); |
| device = mAdapter.getRemoteDevice( |
| new byte[] {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}); |
| assertNotNull(device); |
| assertEquals("01:02:03:04:05:06", device.getAddress()); |
| } |
| |
| public void test_getRemoteLeDevice() { |
| if (!mHasBluetooth) { |
| // Skip the test if bluetooth is not present. |
| return; |
| } |
| // getRemoteLeDevice() should work even with Bluetooth disabled |
| assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext)); |
| mUiAutomation.dropShellPermissionIdentity(); |
| |
| // test bad addresses |
| assertThrows(IllegalArgumentException.class, |
| () -> mAdapter.getRemoteLeDevice((String) null, |
| BluetoothDevice.ADDRESS_TYPE_PUBLIC)); |
| assertThrows(IllegalArgumentException.class, |
| () -> mAdapter.getRemoteLeDevice("01:02:03:04:05:06:07:08", |
| BluetoothDevice.ADDRESS_TYPE_PUBLIC)); |
| assertThrows(IllegalArgumentException.class, |
| () -> mAdapter.getRemoteLeDevice("01:02:03:04:05", |
| BluetoothDevice.ADDRESS_TYPE_PUBLIC)); |
| assertThrows(IllegalArgumentException.class, |
| () -> mAdapter.getRemoteLeDevice("00:01:02:03:04:05", |
| BluetoothDevice.ADDRESS_TYPE_RANDOM + 1)); |
| assertThrows(IllegalArgumentException.class, |
| () -> mAdapter.getRemoteLeDevice("00:01:02:03:04:05", |
| BluetoothDevice.ADDRESS_TYPE_PUBLIC - 1)); |
| |
| // test success |
| BluetoothDevice device = mAdapter.getRemoteLeDevice("00:11:22:AA:BB:CC", |
| BluetoothDevice.ADDRESS_TYPE_PUBLIC); |
| assertNotNull(device); |
| assertEquals("00:11:22:AA:BB:CC", device.getAddress()); |
| device = mAdapter.getRemoteLeDevice("01:02:03:04:05:06", |
| BluetoothDevice.ADDRESS_TYPE_RANDOM); |
| assertNotNull(device); |
| assertEquals("01:02:03:04:05:06", device.getAddress()); |
| } |
| |
| public void test_isLeAudioSupported() throws IOException { |
| if (!mHasBluetooth) { |
| // Skip the test if bluetooth is not present. |
| return; |
| } |
| assertNotSame(BluetoothStatusCodes.ERROR_UNKNOWN, mAdapter.isLeAudioSupported()); |
| } |
| |
| public void test_isLeAudioBroadcastSourceSupported() throws IOException { |
| if (!mHasBluetooth) { |
| // Skip the test if bluetooth is not present. |
| return; |
| } |
| assertNotSame(BluetoothStatusCodes.ERROR_UNKNOWN, |
| mAdapter.isLeAudioBroadcastSourceSupported()); |
| } |
| |
| public void test_isLeAudioBroadcastAssistantSupported() throws IOException { |
| if (!mHasBluetooth) { |
| // Skip the test if bluetooth is not present. |
| return; |
| } |
| assertNotSame(BluetoothStatusCodes.ERROR_UNKNOWN, |
| mAdapter.isLeAudioBroadcastAssistantSupported()); |
| } |
| |
| public void test_getMaxConnectedAudioDevices() { |
| if (!mHasBluetooth) { |
| // Skip the test if bluetooth is not present. |
| return; |
| } |
| |
| // Defined in com.android.bluetooth.btservice.AdapterProperties |
| int maxConnectedAudioDevicesLowerBound = 1; |
| // Defined in com.android.bluetooth.btservice.AdapterProperties |
| int maxConnectedAudioDevicesUpperBound = 5; |
| |
| assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext)); |
| assertTrue(mAdapter.getMaxConnectedAudioDevices() >= maxConnectedAudioDevicesLowerBound); |
| assertTrue(mAdapter.getMaxConnectedAudioDevices() <= maxConnectedAudioDevicesUpperBound); |
| |
| mUiAutomation.dropShellPermissionIdentity(); |
| assertThrows(SecurityException.class, () -> mAdapter.getMaxConnectedAudioDevices()); |
| } |
| |
| public void test_listenUsingRfcommWithServiceRecord() throws IOException { |
| if (!mHasBluetooth) { |
| // Skip the test if bluetooth is not present. |
| return; |
| } |
| |
| assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext)); |
| BluetoothServerSocket socket = mAdapter.listenUsingRfcommWithServiceRecord( |
| "test", UUID.randomUUID()); |
| assertNotNull(socket); |
| socket.close(); |
| |
| mUiAutomation.dropShellPermissionIdentity(); |
| assertThrows(SecurityException.class, () -> mAdapter.listenUsingRfcommWithServiceRecord( |
| "test", UUID.randomUUID())); |
| } |
| |
| public void test_discoverableTimeout() { |
| if (!mHasBluetooth) { |
| // Skip the test if bluetooth is not present. |
| return; |
| } |
| |
| Duration minutes = Duration.ofMinutes(2); |
| |
| assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext)); |
| assertEquals(null, mAdapter.getDiscoverableTimeout()); |
| assertEquals(BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED, |
| mAdapter.setDiscoverableTimeout(minutes)); |
| |
| assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext)); |
| TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED); |
| assertThrows(IllegalArgumentException.class, () -> mAdapter.setDiscoverableTimeout( |
| Duration.ofDays(25000))); |
| assertEquals(BluetoothStatusCodes.SUCCESS, |
| mAdapter.setDiscoverableTimeout(minutes)); |
| assertEquals(minutes, mAdapter.getDiscoverableTimeout()); |
| } |
| |
| public void test_getConnectionState() { |
| if (!mHasBluetooth) return; |
| |
| // Verify return value if Bluetooth is not enabled |
| assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext)); |
| assertEquals(BluetoothProfile.STATE_DISCONNECTED, mAdapter.getConnectionState()); |
| } |
| |
| public void test_getMostRecentlyConnectedDevices() { |
| if (!mHasBluetooth) return; |
| |
| assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext)); |
| |
| // Verify throws SecurityException without permission.BLUETOOTH_PRIVILEGED |
| assertThrows(SecurityException.class, () -> mAdapter.getMostRecentlyConnectedDevices()); |
| |
| // Verify return value if Bluetooth is not enabled |
| assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext)); |
| List<BluetoothDevice> devices = mAdapter.getMostRecentlyConnectedDevices(); |
| assertTrue(devices.isEmpty()); |
| } |
| |
| public void test_getUuids() { |
| if (!mHasBluetooth) return; |
| |
| assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext)); |
| |
| // Verify return value without permission.BLUETOOTH_CONNECT |
| mUiAutomation.dropShellPermissionIdentity(); |
| assertThrows(SecurityException.class, () -> mAdapter.getUuidsList()); |
| mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT); |
| |
| assertNotNull(mAdapter.getUuidsList()); |
| assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext)); |
| |
| // Verify return value if Bluetooth is not enabled |
| assertEquals(0, mAdapter.getUuidsList().size()); |
| |
| } |
| |
| public void test_nameForState() { |
| assertEquals("ON", BluetoothAdapter.nameForState(BluetoothAdapter.STATE_ON)); |
| assertEquals("OFF", BluetoothAdapter.nameForState(BluetoothAdapter.STATE_OFF)); |
| assertEquals("TURNING_ON", |
| BluetoothAdapter.nameForState(BluetoothAdapter.STATE_TURNING_ON)); |
| assertEquals("TURNING_OFF", |
| BluetoothAdapter.nameForState(BluetoothAdapter.STATE_TURNING_OFF)); |
| |
| assertEquals("BLE_ON", BluetoothAdapter.nameForState(BluetoothAdapter.STATE_BLE_ON)); |
| |
| // Check value before state range |
| for (int state = 0; state < BluetoothAdapter.STATE_OFF; state++) { |
| assertEquals("?!?!? (" + state + ")", BluetoothAdapter.nameForState(state)); |
| } |
| // Check value after state range (skip TURNING_OFF) |
| for (int state = BluetoothAdapter.STATE_BLE_ON + 2; state < 100; state++) { |
| assertEquals("?!?!? (" + state + ")", BluetoothAdapter.nameForState(state)); |
| } |
| } |
| |
| public void test_BluetoothConnectionCallback_disconnectReasonText() { |
| assertEquals("Reason unknown", BluetoothAdapter.BluetoothConnectionCallback |
| .disconnectReasonToString(BluetoothStatusCodes.ERROR_UNKNOWN)); |
| } |
| |
| public void test_registerBluetoothConnectionCallback() { |
| if (!mHasBluetooth) return; |
| |
| Executor executor = mContext.getMainExecutor(); |
| BluetoothAdapter.BluetoothConnectionCallback callback = |
| new BluetoothAdapter.BluetoothConnectionCallback() { |
| @Override |
| public void onDeviceConnected(@NonNull BluetoothDevice device) {} |
| @Override |
| public void onDeviceDisconnected(BluetoothDevice device, int reason) {} |
| |
| }; |
| |
| // placeholder call for coverage |
| callback.onDeviceConnected(null); |
| callback.onDeviceDisconnected(null, BluetoothStatusCodes.ERROR_UNKNOWN); |
| |
| // Verify parameter |
| assertFalse(mAdapter.registerBluetoothConnectionCallback(null, callback)); |
| assertFalse(mAdapter.registerBluetoothConnectionCallback(executor, null)); |
| assertFalse(mAdapter.unregisterBluetoothConnectionCallback(null)); |
| |
| assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext)); |
| |
| // Verify throws SecurityException without permission.BLUETOOTH_PRIVILEGED |
| assertThrows(SecurityException.class, |
| () -> mAdapter.registerBluetoothConnectionCallback(executor, callback)); |
| |
| mUiAutomation.dropShellPermissionIdentity(); |
| // Verify throws SecurityException without permission.BLUETOOTH_CONNECT |
| assertThrows(SecurityException.class, () -> |
| mAdapter.registerBluetoothConnectionCallback(executor, callback)); |
| assertThrows(SecurityException.class, () -> |
| mAdapter.unregisterBluetoothConnectionCallback(callback)); |
| } |
| |
| public void test_requestControllerActivityEnergyInfo() { |
| if (!mHasBluetooth) return; |
| |
| BluetoothAdapter.OnBluetoothActivityEnergyInfoCallback callback = |
| new BluetoothAdapter.OnBluetoothActivityEnergyInfoCallback() { |
| @Override |
| public void onBluetoothActivityEnergyInfoAvailable( |
| BluetoothActivityEnergyInfo info) { |
| assertNotNull(info); |
| } |
| |
| @Override |
| public void onBluetoothActivityEnergyInfoError(int errorCode) {} |
| }; |
| |
| // Verify parameter |
| assertThrows(NullPointerException.class, |
| () -> mAdapter.requestControllerActivityEnergyInfo(null, callback)); |
| } |
| |
| public void test_clearBluetooth() { |
| if (!mHasBluetooth) return; |
| |
| assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext)); |
| |
| // Verify throws SecurityException without permission.BLUETOOTH_PRIVILEGED |
| assertThrows(SecurityException.class, () -> mAdapter.clearBluetooth()); |
| mUiAutomation.dropShellPermissionIdentity(); |
| // Verify throws SecurityException without permission.BLUETOOTH_CONNECT |
| assertThrows(SecurityException.class, () -> mAdapter.clearBluetooth()); |
| |
| mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT); |
| assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext)); |
| // Verify throws RuntimeException when trying to save sysprop for later (permission denied) |
| assertThrows(RuntimeException.class, () -> mAdapter.clearBluetooth()); |
| } |
| |
| public void test_BluetoothProfile_getConnectionStateName() { |
| if (!mHasBluetooth) return; |
| |
| assertEquals("STATE_DISCONNECTED", |
| BluetoothProfile.getConnectionStateName(BluetoothProfile.STATE_DISCONNECTED)); |
| assertEquals("STATE_CONNECTED", |
| BluetoothProfile.getConnectionStateName(BluetoothProfile.STATE_CONNECTED)); |
| assertEquals("STATE_CONNECTING", |
| BluetoothProfile.getConnectionStateName(BluetoothProfile.STATE_CONNECTING)); |
| assertEquals("STATE_CONNECTED", |
| BluetoothProfile.getConnectionStateName(BluetoothProfile.STATE_CONNECTED)); |
| assertEquals("STATE_DISCONNECTING", |
| BluetoothProfile.getConnectionStateName(BluetoothProfile.STATE_DISCONNECTING)); |
| assertEquals("STATE_UNKNOWN", |
| BluetoothProfile.getConnectionStateName(BluetoothProfile.STATE_DISCONNECTING + 1)); |
| } |
| |
| public void test_BluetoothProfile_getProfileName() { |
| if (!mHasBluetooth) return; |
| assertEquals("HEADSET", |
| BluetoothProfile.getProfileName(BluetoothProfile.HEADSET)); |
| assertEquals("A2DP", |
| BluetoothProfile.getProfileName(BluetoothProfile.A2DP)); |
| assertEquals("HID_HOST", |
| BluetoothProfile.getProfileName(BluetoothProfile.HID_HOST)); |
| assertEquals("PAN", |
| BluetoothProfile.getProfileName(BluetoothProfile.PAN)); |
| assertEquals("PBAP", |
| BluetoothProfile.getProfileName(BluetoothProfile.PBAP)); |
| assertEquals("GATT", |
| BluetoothProfile.getProfileName(BluetoothProfile.GATT)); |
| assertEquals("GATT_SERVER", |
| BluetoothProfile.getProfileName(BluetoothProfile.GATT_SERVER)); |
| assertEquals("MAP", |
| BluetoothProfile.getProfileName(BluetoothProfile.MAP)); |
| assertEquals("SAP", |
| BluetoothProfile.getProfileName(BluetoothProfile.SAP)); |
| assertEquals("A2DP_SINK", |
| BluetoothProfile.getProfileName(BluetoothProfile.A2DP_SINK)); |
| assertEquals("AVRCP_CONTROLLER", |
| BluetoothProfile.getProfileName(BluetoothProfile.AVRCP_CONTROLLER)); |
| // assertEquals("AVRCP", |
| // BluetoothProfile.getProfileName(BluetoothProfile.AVRCP)); |
| assertEquals("HEADSET_CLIENT", |
| BluetoothProfile.getProfileName(BluetoothProfile.HEADSET_CLIENT)); |
| assertEquals("PBAP_CLIENT", |
| BluetoothProfile.getProfileName(BluetoothProfile.PBAP_CLIENT)); |
| assertEquals("MAP_CLIENT", |
| BluetoothProfile.getProfileName(BluetoothProfile.MAP_CLIENT)); |
| assertEquals("HID_DEVICE", |
| BluetoothProfile.getProfileName(BluetoothProfile.HID_DEVICE)); |
| assertEquals("OPP", |
| BluetoothProfile.getProfileName(BluetoothProfile.OPP)); |
| assertEquals("HEARING_AID", |
| BluetoothProfile.getProfileName(BluetoothProfile.HEARING_AID)); |
| assertEquals("LE_AUDIO", |
| BluetoothProfile.getProfileName(BluetoothProfile.LE_AUDIO)); |
| assertEquals("HAP_CLIENT", |
| BluetoothProfile.getProfileName(BluetoothProfile.HAP_CLIENT)); |
| |
| if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { |
| return; |
| } |
| |
| assertEquals("VOLUME_CONTROL", |
| BluetoothProfile.getProfileName(BluetoothProfile.VOLUME_CONTROL)); |
| assertEquals("CSIP_SET_COORDINATOR", |
| BluetoothProfile.getProfileName(BluetoothProfile.CSIP_SET_COORDINATOR)); |
| assertEquals("LE_AUDIO_BROADCAST", |
| BluetoothProfile.getProfileName(BluetoothProfile.LE_AUDIO_BROADCAST)); |
| assertEquals("LE_AUDIO_BROADCAST_ASSISTANT", |
| BluetoothProfile.getProfileName(BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT)); |
| } |
| |
| public void test_getSetBluetoothHciSnoopLoggingMode() { |
| if (!mHasBluetooth) { |
| return; |
| } |
| |
| assertThrows(SecurityException.class, () -> mAdapter |
| .setBluetoothHciSnoopLoggingMode(BluetoothAdapter.BT_SNOOP_LOG_MODE_FULL)); |
| assertThrows(SecurityException.class, () -> mAdapter |
| .getBluetoothHciSnoopLoggingMode()); |
| |
| TestUtils.adoptPermissionAsShellUid(BLUETOOTH_PRIVILEGED); |
| |
| assertThrows(IllegalArgumentException.class, () -> mAdapter |
| .setBluetoothHciSnoopLoggingMode(-1)); |
| |
| assertEquals(BluetoothStatusCodes.SUCCESS, mAdapter |
| .setBluetoothHciSnoopLoggingMode(BluetoothAdapter.BT_SNOOP_LOG_MODE_FULL)); |
| assertEquals(mAdapter.getBluetoothHciSnoopLoggingMode(), |
| BluetoothAdapter.BT_SNOOP_LOG_MODE_FULL); |
| |
| assertEquals(BluetoothStatusCodes.SUCCESS, mAdapter |
| .setBluetoothHciSnoopLoggingMode(BluetoothAdapter.BT_SNOOP_LOG_MODE_FILTERED)); |
| assertEquals(mAdapter.getBluetoothHciSnoopLoggingMode(), |
| BluetoothAdapter.BT_SNOOP_LOG_MODE_FILTERED); |
| |
| assertEquals(BluetoothStatusCodes.SUCCESS, mAdapter |
| .setBluetoothHciSnoopLoggingMode(BluetoothAdapter.BT_SNOOP_LOG_MODE_DISABLED)); |
| assertEquals(mAdapter.getBluetoothHciSnoopLoggingMode(), |
| BluetoothAdapter.BT_SNOOP_LOG_MODE_DISABLED); |
| |
| } |
| |
| private static void sleep(long t) { |
| try { |
| Thread.sleep(t); |
| } catch (InterruptedException e) { } |
| } |
| |
| private boolean waitForAdapterNameChange() { |
| mAdapterNameChangedlock.lock(); |
| try { |
| // Wait for the Adapter name to be changed |
| while (!mIsAdapterNameChanged) { |
| if (!mConditionAdapterNameChanged.await( |
| SET_NAME_TIMEOUT, TimeUnit.MILLISECONDS)) { |
| Log.e(TAG, "Timeout while waiting for adapter name change"); |
| break; |
| } |
| } |
| } catch (InterruptedException e) { |
| Log.e(TAG, "waitForAdapterNameChange: interrrupted"); |
| } finally { |
| mAdapterNameChangedlock.unlock(); |
| } |
| return mIsAdapterNameChanged; |
| } |
| |
| private final BroadcastReceiver mAdapterNameChangeReceiver = new BroadcastReceiver() { |
| @Override |
| public void onReceive(Context context, Intent intent) { |
| String action = intent.getAction(); |
| if (action.equals(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED)) { |
| mAdapterNameChangedlock.lock(); |
| mIsAdapterNameChanged = true; |
| try { |
| mConditionAdapterNameChanged.signal(); |
| } catch (IllegalMonitorStateException ex) { |
| } finally { |
| mAdapterNameChangedlock.unlock(); |
| } |
| } |
| } |
| }; |
| } |