1 /* 2 * Copyright 2022 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.telephony; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.Mockito.doReturn; 22 import static org.mockito.Mockito.mock; 23 import static org.mockito.Mockito.spy; 24 import static org.mockito.Mockito.when; 25 26 import android.content.ComponentName; 27 import android.net.Uri; 28 import android.os.Process; 29 import android.telecom.Call; 30 import android.telecom.PhoneAccount; 31 import android.telecom.PhoneAccountHandle; 32 import android.telecom.TelecomManager; 33 34 import androidx.test.filters.SmallTest; 35 import androidx.test.runner.AndroidJUnit4; 36 37 import org.junit.After; 38 import org.junit.Before; 39 import org.junit.Test; 40 import org.junit.runner.RunWith; 41 import org.mockito.Mock; 42 import org.mockito.MockitoAnnotations; 43 44 import java.util.ArrayList; 45 import java.util.LinkedHashSet; 46 import java.util.List; 47 import java.util.UUID; 48 49 @SmallTest 50 @RunWith(AndroidJUnit4.class) 51 public class CallInfoTest { 52 53 private static final String TEST_ACCOUNT_ADDRESS = "https://foo.com/"; 54 private static final int TEST_ACCOUNT_INDEX = 0; 55 56 @Mock 57 private TelecomManager mMockTelecomManager; 58 59 private BluetoothInCallService mBluetoothInCallService; 60 private BluetoothInCallService.CallInfo mMockCallInfo; 61 62 @Before setUp()63 public void setUp() throws Exception { 64 MockitoAnnotations.initMocks(this); 65 66 mBluetoothInCallService = new BluetoothInCallService(); 67 mMockCallInfo = spy(mBluetoothInCallService.new CallInfo()); 68 } 69 70 @After tearDown()71 public void tearDown() throws Exception { 72 mBluetoothInCallService = null; 73 } 74 75 @Test getBluetoothCalls()76 public void getBluetoothCalls() { 77 assertThat(mMockCallInfo.getBluetoothCalls()).isEmpty(); 78 } 79 80 @Test getActiveCall()81 public void getActiveCall() { 82 BluetoothCall activeCall = getMockCall(); 83 when(activeCall.getState()).thenReturn(Call.STATE_ACTIVE); 84 ArrayList<BluetoothCall> calls = new ArrayList<>(); 85 calls.add(activeCall); 86 87 doReturn(calls).when(mMockCallInfo).getBluetoothCalls(); 88 89 assertThat(mMockCallInfo.getActiveCall()).isEqualTo(activeCall); 90 } 91 92 @Test getHeldCall()93 public void getHeldCall() { 94 BluetoothCall heldCall = getMockCall(); 95 when(heldCall.getState()).thenReturn(Call.STATE_HOLDING); 96 ArrayList<BluetoothCall> calls = new ArrayList<>(); 97 calls.add(heldCall); 98 99 doReturn(calls).when(mMockCallInfo).getBluetoothCalls(); 100 101 assertThat(mMockCallInfo.getHeldCall()).isEqualTo(heldCall); 102 assertThat(mMockCallInfo.getNumHeldCalls()).isEqualTo(1); 103 } 104 105 @Test getOutgoingCall()106 public void getOutgoingCall() { 107 BluetoothCall outgoingCall = getMockCall(); 108 when(outgoingCall.getState()).thenReturn(Call.STATE_PULLING_CALL); 109 ArrayList<BluetoothCall> calls = new ArrayList<>(); 110 calls.add(outgoingCall); 111 112 doReturn(calls).when(mMockCallInfo).getBluetoothCalls(); 113 114 assertThat(mMockCallInfo.getOutgoingCall()).isEqualTo(outgoingCall); 115 } 116 117 @Test getRingingOrSimulatedRingingCall()118 public void getRingingOrSimulatedRingingCall() { 119 BluetoothCall ringingCall = getMockCall(); 120 when(ringingCall.getState()).thenReturn(Call.STATE_SIMULATED_RINGING); 121 ArrayList<BluetoothCall> calls = new ArrayList<>(); 122 calls.add(ringingCall); 123 124 doReturn(calls).when(mMockCallInfo).getBluetoothCalls(); 125 126 assertThat(mMockCallInfo.getRingingOrSimulatedRingingCall()).isEqualTo(ringingCall); 127 } 128 129 @Test hasOnlyDisconnectedCalls_withNoCalls()130 public void hasOnlyDisconnectedCalls_withNoCalls() { 131 assertThat(mMockCallInfo.getBluetoothCalls()).isEmpty(); 132 133 assertThat(mMockCallInfo.hasOnlyDisconnectedCalls()).isFalse(); 134 } 135 136 @Test hasOnlyDisconnectedCalls_withConnectedCall()137 public void hasOnlyDisconnectedCalls_withConnectedCall() { 138 BluetoothCall activeCall = getMockCall(); 139 when(activeCall.getState()).thenReturn(Call.STATE_ACTIVE); 140 ArrayList<BluetoothCall> calls = new ArrayList<>(); 141 calls.add(activeCall); 142 143 doReturn(calls).when(mMockCallInfo).getBluetoothCalls(); 144 145 assertThat(mMockCallInfo.hasOnlyDisconnectedCalls()).isFalse(); 146 } 147 148 @Test hasOnlyDisconnectedCalls_withDisconnectedCallOnly()149 public void hasOnlyDisconnectedCalls_withDisconnectedCallOnly() { 150 BluetoothCall disconnectedCall = getMockCall(); 151 when(disconnectedCall.getState()).thenReturn(Call.STATE_DISCONNECTED); 152 ArrayList<BluetoothCall> calls = new ArrayList<>(); 153 calls.add(disconnectedCall); 154 155 doReturn(calls).when(mMockCallInfo).getBluetoothCalls(); 156 157 assertThat(mMockCallInfo.hasOnlyDisconnectedCalls()).isTrue(); 158 } 159 160 @Test getForegroundCall_withConnectingCall()161 public void getForegroundCall_withConnectingCall() { 162 BluetoothCall connectingCall = getMockCall(); 163 when(connectingCall.getState()).thenReturn(Call.STATE_CONNECTING); 164 ArrayList<BluetoothCall> calls = new ArrayList<>(); 165 calls.add(connectingCall); 166 167 doReturn(calls).when(mMockCallInfo).getBluetoothCalls(); 168 169 assertThat(mMockCallInfo.getForegroundCall()).isEqualTo(connectingCall); 170 } 171 172 @Test getForegroundCall_withPullingCall()173 public void getForegroundCall_withPullingCall() { 174 BluetoothCall pullingCall = getMockCall(); 175 when(pullingCall.getState()).thenReturn(Call.STATE_PULLING_CALL); 176 ArrayList<BluetoothCall> calls = new ArrayList<>(); 177 calls.add(pullingCall); 178 179 doReturn(calls).when(mMockCallInfo).getBluetoothCalls(); 180 181 assertThat(mMockCallInfo.getForegroundCall()).isEqualTo(pullingCall); 182 } 183 184 @Test getForegroundCall_withRingingCall()185 public void getForegroundCall_withRingingCall() { 186 BluetoothCall ringingCall = getMockCall(); 187 when(ringingCall.getState()).thenReturn(Call.STATE_CONNECTING); 188 ArrayList<BluetoothCall> calls = new ArrayList<>(); 189 calls.add(ringingCall); 190 191 doReturn(calls).when(mMockCallInfo).getBluetoothCalls(); 192 193 assertThat(mMockCallInfo.getForegroundCall()).isEqualTo(ringingCall); 194 } 195 196 @Test getForegroundCall_withNoMatchingCall()197 public void getForegroundCall_withNoMatchingCall() { 198 BluetoothCall disconnectedCall = getMockCall(); 199 when(disconnectedCall.getState()).thenReturn(Call.STATE_DISCONNECTED); 200 ArrayList<BluetoothCall> calls = new ArrayList<>(); 201 calls.add(disconnectedCall); 202 203 doReturn(calls).when(mMockCallInfo).getBluetoothCalls(); 204 205 assertThat(mMockCallInfo.getForegroundCall()).isNull(); 206 } 207 208 @Test getCallByState_withNoMatchingCall()209 public void getCallByState_withNoMatchingCall() { 210 BluetoothCall activeCall = getMockCall(); 211 when(activeCall.getState()).thenReturn(Call.STATE_ACTIVE); 212 ArrayList<BluetoothCall> calls = new ArrayList<>(); 213 calls.add(activeCall); 214 215 doReturn(calls).when(mMockCallInfo).getBluetoothCalls(); 216 217 assertThat(mMockCallInfo.getCallByState(Call.STATE_HOLDING)).isNull(); 218 } 219 220 @Test getCallByStates_withNoMatchingCall()221 public void getCallByStates_withNoMatchingCall() { 222 LinkedHashSet<Integer> states = new LinkedHashSet<>(); 223 states.add(Call.STATE_CONNECTING); 224 BluetoothCall activeCall = getMockCall(); 225 when(activeCall.getState()).thenReturn(Call.STATE_ACTIVE); 226 ArrayList<BluetoothCall> calls = new ArrayList<>(); 227 calls.add(activeCall); 228 229 doReturn(calls).when(mMockCallInfo).getBluetoothCalls(); 230 231 assertThat(mMockCallInfo.getCallByStates(states)).isNull(); 232 } 233 234 @Test getCallByCallId()235 public void getCallByCallId() { 236 BluetoothCall call = getMockCall(); 237 UUID uuid = UUID.randomUUID(); 238 when(call.getTbsCallId()).thenReturn(uuid); 239 ArrayList<BluetoothCall> calls = new ArrayList<>(); 240 calls.add(call); 241 242 doReturn(calls).when(mMockCallInfo).getBluetoothCalls(); 243 244 assertThat(mMockCallInfo.getCallByCallId(uuid)).isEqualTo(call); 245 } 246 247 @Test getCallByCallId_withNoCalls()248 public void getCallByCallId_withNoCalls() { 249 UUID uuid = UUID.randomUUID(); 250 assertThat(mMockCallInfo.getBluetoothCalls()).isEmpty(); 251 252 assertThat(mMockCallInfo.getCallByCallId(uuid)).isNull(); 253 } 254 255 @Test getBestPhoneAccount()256 public void getBestPhoneAccount() { 257 BluetoothCall foregroundCall = getMockCall(); 258 when(foregroundCall.getState()).thenReturn(Call.STATE_DIALING); 259 when(foregroundCall.getAccountHandle()).thenReturn(null); 260 261 ArrayList<BluetoothCall> calls = new ArrayList<>(); 262 calls.add(foregroundCall); 263 doReturn(calls).when(mMockCallInfo).getBluetoothCalls(); 264 265 String testId = "id0"; 266 List<PhoneAccountHandle> handles = new ArrayList<>(); 267 PhoneAccountHandle testHandle = makeQuickAccountHandle(testId); 268 handles.add(testHandle); 269 when(mMockTelecomManager.getPhoneAccountsSupportingScheme( 270 PhoneAccount.SCHEME_TEL)).thenReturn(handles); 271 272 PhoneAccount fakePhoneAccount = makeQuickAccount(testId, TEST_ACCOUNT_INDEX); 273 when(mMockTelecomManager.getPhoneAccount(testHandle)).thenReturn(fakePhoneAccount); 274 mBluetoothInCallService.mTelecomManager = mMockTelecomManager; 275 276 assertThat(mMockCallInfo.getBestPhoneAccount()).isEqualTo(fakePhoneAccount); 277 } 278 makeQuickConnectionServiceComponentName()279 private static ComponentName makeQuickConnectionServiceComponentName() { 280 return new ComponentName("com.placeholder.connectionservice.package.name", 281 "com.placeholder.connectionservice.class.name"); 282 } 283 makeQuickAccountHandle(String id)284 private static PhoneAccountHandle makeQuickAccountHandle(String id) { 285 return new PhoneAccountHandle(makeQuickConnectionServiceComponentName(), id, 286 Process.myUserHandle()); 287 } 288 makeQuickAccountBuilder(String id, int idx)289 private PhoneAccount.Builder makeQuickAccountBuilder(String id, int idx) { 290 return new PhoneAccount.Builder(makeQuickAccountHandle(id), "label" + idx); 291 } 292 makeQuickAccount(String id, int idx)293 private PhoneAccount makeQuickAccount(String id, int idx) { 294 return makeQuickAccountBuilder(id, idx) 295 .setAddress(Uri.parse(TEST_ACCOUNT_ADDRESS + idx)) 296 .setSubscriptionAddress(Uri.parse("tel:555-000" + idx)) 297 .setCapabilities(idx) 298 .setShortDescription("desc" + idx) 299 .setIsEnabled(true) 300 .build(); 301 } 302 getMockCall()303 private BluetoothCall getMockCall() { 304 return mock(BluetoothCall.class); 305 } 306 }