1 /* 2 * Copyright (C) 2017 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 com.android.bluetooth.mapclient; 18 19 import static org.mockito.Mockito.*; 20 21 import android.bluetooth.BluetoothAdapter; 22 import android.bluetooth.BluetoothDevice; 23 import android.bluetooth.BluetoothProfile; 24 import android.bluetooth.IBluetoothMapClient; 25 import android.content.Context; 26 import android.os.UserHandle; 27 28 import androidx.test.InstrumentationRegistry; 29 import androidx.test.filters.MediumTest; 30 import androidx.test.rule.ServiceTestRule; 31 import androidx.test.runner.AndroidJUnit4; 32 33 import com.android.bluetooth.R; 34 import com.android.bluetooth.TestUtils; 35 import com.android.bluetooth.Utils; 36 import com.android.bluetooth.btservice.AdapterService; 37 import com.android.bluetooth.btservice.storage.DatabaseManager; 38 39 import org.junit.After; 40 import org.junit.Assert; 41 import org.junit.Assume; 42 import org.junit.Before; 43 import org.junit.Rule; 44 import org.junit.Test; 45 import org.junit.runner.RunWith; 46 import org.mockito.Mock; 47 import org.mockito.MockitoAnnotations; 48 49 import java.util.ArrayList; 50 import java.util.List; 51 import java.util.Map; 52 53 @MediumTest 54 @RunWith(AndroidJUnit4.class) 55 public class MapClientTest { 56 private static final String TAG = MapClientTest.class.getSimpleName(); 57 private MapClientService mService = null; 58 private BluetoothAdapter mAdapter = null; 59 private Context mTargetContext; 60 61 @Mock private AdapterService mAdapterService; 62 @Mock private MnsService mMockMnsService; 63 @Mock private DatabaseManager mDatabaseManager; 64 65 @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); 66 67 @Before setUp()68 public void setUp() throws Exception { 69 mTargetContext = InstrumentationRegistry.getTargetContext(); 70 Assume.assumeTrue("Ignore test when MapClientService is not enabled", 71 mTargetContext.getResources().getBoolean(R.bool.profile_supported_mapmce)); 72 MockitoAnnotations.initMocks(this); 73 TestUtils.setAdapterService(mAdapterService); 74 when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); 75 doReturn(true, false).when(mAdapterService).isStartedProfile(anyString()); 76 MapUtils.setMnsService(mMockMnsService); 77 TestUtils.startService(mServiceRule, MapClientService.class); 78 mService = MapClientService.getMapClientService(); 79 Assert.assertNotNull(mService); 80 mAdapter = BluetoothAdapter.getDefaultAdapter(); 81 } 82 83 @After tearDown()84 public void tearDown() throws Exception { 85 if (!mTargetContext.getResources().getBoolean(R.bool.profile_supported_mapmce)) { 86 return; 87 } 88 TestUtils.stopService(mServiceRule, MapClientService.class); 89 mService = MapClientService.getMapClientService(); 90 Assert.assertNull(mService); 91 TestUtils.clearAdapterService(mAdapterService); 92 } 93 94 /** 95 * Mock the priority of a bluetooth device 96 * 97 * @param device - The bluetooth device you wish to mock the priority of 98 * @param priority - The priority value you want the device to have 99 */ mockDevicePriority(BluetoothDevice device, int priority)100 private void mockDevicePriority(BluetoothDevice device, int priority) { 101 when(mDatabaseManager.getProfileConnectionPolicy(device, BluetoothProfile.MAP_CLIENT)) 102 .thenReturn(priority); 103 } 104 105 @Test testInitialize()106 public void testInitialize() { 107 Assert.assertNotNull(MapClientService.getMapClientService()); 108 } 109 110 /** 111 * Test connection of one device. 112 */ 113 @Test testConnect()114 public void testConnect() { 115 // make sure there is no statemachine already defined for this device 116 BluetoothDevice device = makeBluetoothDevice("11:11:11:11:11:11"); 117 Assert.assertNull(mService.getInstanceMap().get(device)); 118 119 // connect a bluetooth device 120 mockDevicePriority(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 121 Assert.assertTrue(mService.connect(device)); 122 123 // is the statemachine created 124 Map<BluetoothDevice, MceStateMachine> map = mService.getInstanceMap(); 125 Assert.assertEquals(1, map.size()); 126 Assert.assertNotNull(map.get(device)); 127 TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); 128 129 Assert.assertEquals(map.get(device).getState(), BluetoothProfile.STATE_CONNECTING); 130 mService.cleanupDevice(device); 131 Assert.assertNull(mService.getInstanceMap().get(device)); 132 } 133 134 /** 135 * Test that a PRIORITY_OFF device is not connected to 136 */ 137 @Test testConnectPriorityOffDevice()138 public void testConnectPriorityOffDevice() { 139 // make sure there is no statemachine already defined for this device 140 BluetoothDevice device = makeBluetoothDevice("11:11:11:11:11:11"); 141 Assert.assertNull(mService.getInstanceMap().get(device)); 142 143 // connect a bluetooth device 144 mockDevicePriority(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); 145 Assert.assertFalse(mService.connect(device)); 146 147 // is the statemachine created 148 Map<BluetoothDevice, MceStateMachine> map = mService.getInstanceMap(); 149 Assert.assertEquals(0, map.size()); 150 Assert.assertNull(map.get(device)); 151 } 152 153 /** 154 * Test connecting MAXIMUM_CONNECTED_DEVICES devices. 155 */ 156 @Test testConnectMaxDevices()157 public void testConnectMaxDevices() { 158 // Create bluetoothdevice & mock statemachine objects to be used in this test 159 List<BluetoothDevice> list = new ArrayList<>(); 160 String address = "11:11:11:11:11:1"; 161 for (int i = 0; i < MapClientService.MAXIMUM_CONNECTED_DEVICES; ++i) { 162 list.add(makeBluetoothDevice(address + i)); 163 } 164 165 // make sure there is no statemachine already defined for the devices defined above 166 for (BluetoothDevice d : list) { 167 Assert.assertNull(mService.getInstanceMap().get(d)); 168 } 169 170 // run the test - connect all devices, set their priorities to on 171 for (BluetoothDevice d : list) { 172 mockDevicePriority(d, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 173 Assert.assertTrue(mService.connect(d)); 174 } 175 176 // verify 177 Map<BluetoothDevice, MceStateMachine> map = mService.getInstanceMap(); 178 Assert.assertEquals(MapClientService.MAXIMUM_CONNECTED_DEVICES, map.size()); 179 for (BluetoothDevice d : list) { 180 Assert.assertNotNull(map.get(d)); 181 } 182 183 // Try to connect one more device. Should fail. 184 BluetoothDevice last = makeBluetoothDevice("11:22:33:44:55:66"); 185 Assert.assertFalse(mService.connect(last)); 186 } 187 188 /** 189 * Test calling connect via Binder 190 */ 191 @Test testConnectViaBinder()192 public void testConnectViaBinder() { 193 BluetoothDevice device = makeBluetoothDevice("11:11:11:11:11:11"); 194 mockDevicePriority(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); 195 IBluetoothMapClient.Stub mapClientBinder = (IBluetoothMapClient.Stub) mService.initBinder(); 196 try { 197 Utils.setForegroundUserId(UserHandle.getCallingUserId()); 198 Assert.assertTrue(mapClientBinder.connect(device, mAdapter.getAttributionSource())); 199 } catch (Exception e) { 200 Assert.fail(e.toString()); 201 } 202 } 203 makeBluetoothDevice(String address)204 private BluetoothDevice makeBluetoothDevice(String address) { 205 return mAdapter.getRemoteDevice(address); 206 } 207 } 208