1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.bluetooth; 18 19 import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; 20 21 import static com.google.common.truth.Truth.assertThat; 22 23 import static org.mockito.Mockito.any; 24 import static org.mockito.Mockito.anyInt; 25 import static org.mockito.Mockito.eq; 26 import static org.mockito.Mockito.mock; 27 import static org.mockito.Mockito.timeout; 28 import static org.mockito.Mockito.verify; 29 30 import android.content.Context; 31 32 import androidx.test.core.app.ApplicationProvider; 33 import androidx.test.runner.AndroidJUnit4; 34 35 import com.android.compatibility.common.util.AdoptShellPermissionsRule; 36 37 import org.junit.Ignore; 38 import org.junit.Rule; 39 import org.junit.Test; 40 import org.junit.runner.RunWith; 41 42 import pandora.HostProto.AdvertiseRequest; 43 import pandora.HostProto.OwnAddressType; 44 45 /** Test cases for {@link BluetoothGattServer}. */ 46 @RunWith(AndroidJUnit4.class) 47 public class GattServerConnectWithoutScanTest { 48 private static final String TAG = GattServerConnectWithoutScanTest.class.getSimpleName(); 49 50 private static final int TIMEOUT_GATT_CONNECTION_MS = 2_000; 51 52 @Rule(order = 1) 53 public final AdoptShellPermissionsRule mPermissionRule = new AdoptShellPermissionsRule(); 54 55 @Rule(order = 0) 56 public final PandoraDevice mBumble = new PandoraDevice(); 57 58 private final Context mContext = ApplicationProvider.getApplicationContext(); 59 private final BluetoothManager mBluetoothManager = 60 mContext.getSystemService(BluetoothManager.class); 61 private final BluetoothAdapter mBluetoothAdapter = mBluetoothManager.getAdapter(); 62 63 @Test 64 @Ignore("b/343749428: Remove hidden api's dependencies to enable the test.") serverConnectToRandomAddress_withTransportAuto()65 public void serverConnectToRandomAddress_withTransportAuto() throws Exception { 66 advertiseWithBumble(OwnAddressType.RANDOM); 67 68 BluetoothGattServerCallback mockGattServerCallback = 69 mock(BluetoothGattServerCallback.class); 70 BluetoothGattServer gattServer = 71 mBluetoothManager.openGattServer( 72 mContext, mockGattServerCallback, BluetoothDevice.TRANSPORT_AUTO); 73 74 assertThat(gattServer).isNotNull(); 75 76 try { 77 BluetoothDevice device = 78 mBluetoothAdapter.getRemoteLeDevice( 79 Utils.BUMBLE_RANDOM_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM); 80 81 gattServer.connect(device, false); 82 verify(mockGattServerCallback, timeout(TIMEOUT_GATT_CONNECTION_MS)) 83 .onConnectionStateChange(any(), anyInt(), eq(STATE_CONNECTED)); 84 } finally { 85 gattServer.close(); 86 } 87 } 88 89 @Test 90 @Ignore("b/343749428: Remove hidden api's dependencies to enable the test.") serverConnectToRandomAddress_withTransportLE()91 public void serverConnectToRandomAddress_withTransportLE() throws Exception { 92 advertiseWithBumble(OwnAddressType.RANDOM); 93 94 BluetoothGattServerCallback mockGattServerCallback = 95 mock(BluetoothGattServerCallback.class); 96 BluetoothGattServer gattServer = 97 mBluetoothManager.openGattServer( 98 mContext, mockGattServerCallback, BluetoothDevice.TRANSPORT_LE); 99 100 assertThat(gattServer).isNotNull(); 101 102 try { 103 BluetoothDevice device = 104 mBluetoothAdapter.getRemoteLeDevice( 105 Utils.BUMBLE_RANDOM_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM); 106 107 gattServer.connect(device, false); 108 verify(mockGattServerCallback, timeout(TIMEOUT_GATT_CONNECTION_MS)) 109 .onConnectionStateChange(any(), anyInt(), eq(STATE_CONNECTED)); 110 } finally { 111 gattServer.close(); 112 } 113 } 114 115 @Test 116 @Ignore("b/333018293") serverConnectToPublicAddress_withTransportAuto()117 public void serverConnectToPublicAddress_withTransportAuto() throws Exception { 118 advertiseWithBumble(OwnAddressType.PUBLIC); 119 120 BluetoothGattServerCallback mockGattServerCallback = 121 mock(BluetoothGattServerCallback.class); 122 BluetoothGattServer gattServer = 123 mBluetoothManager.openGattServer( 124 mContext, mockGattServerCallback, BluetoothDevice.TRANSPORT_AUTO); 125 126 assertThat(gattServer).isNotNull(); 127 128 try { 129 gattServer.connect(mBumble.getRemoteDevice(), false); 130 verify(mockGattServerCallback, timeout(TIMEOUT_GATT_CONNECTION_MS)) 131 .onConnectionStateChange(any(), anyInt(), eq(STATE_CONNECTED)); 132 } finally { 133 gattServer.close(); 134 } 135 } 136 137 @Test 138 @Ignore("b/343749428: Remove hidden api's dependencies to enable the test.") serverConnectToPublicAddress_withTransportLE()139 public void serverConnectToPublicAddress_withTransportLE() throws Exception { 140 advertiseWithBumble(OwnAddressType.PUBLIC); 141 142 BluetoothGattServerCallback mockGattServerCallback = 143 mock(BluetoothGattServerCallback.class); 144 BluetoothGattServer gattServer = 145 mBluetoothManager.openGattServer( 146 mContext, mockGattServerCallback, BluetoothDevice.TRANSPORT_LE); 147 148 assertThat(gattServer).isNotNull(); 149 150 try { 151 gattServer.connect(mBumble.getRemoteDevice(), false); 152 verify(mockGattServerCallback, timeout(TIMEOUT_GATT_CONNECTION_MS)) 153 .onConnectionStateChange(any(), anyInt(), eq(STATE_CONNECTED)); 154 } finally { 155 gattServer.close(); 156 } 157 } 158 advertiseWithBumble(OwnAddressType ownAddressType)159 private void advertiseWithBumble(OwnAddressType ownAddressType) { 160 AdvertiseRequest request = 161 AdvertiseRequest.newBuilder() 162 .setLegacy(true) 163 .setConnectable(true) 164 .setOwnAddressType(ownAddressType) 165 .build(); 166 mBumble.hostBlocking().advertise(request); 167 } 168 } 169