1 /* 2 * Copyright 2018 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 package com.android.bluetooth.hfp; 17 18 import static org.mockito.ArgumentMatchers.any; 19 import static org.mockito.Mockito.*; 20 21 import android.app.PropertyInvalidatedCache; 22 import android.bluetooth.BluetoothAdapter; 23 import android.bluetooth.BluetoothDevice; 24 import android.content.Context; 25 import android.os.HandlerThread; 26 import android.os.IBinder; 27 import android.os.Looper; 28 import android.os.ServiceManager; 29 import android.telephony.PhoneStateListener; 30 import android.telephony.SubscriptionManager; 31 import android.telephony.TelephonyManager; 32 33 import androidx.test.filters.MediumTest; 34 import androidx.test.runner.AndroidJUnit4; 35 36 import com.android.bluetooth.TestUtils; 37 import com.android.internal.telephony.ISub; 38 39 import org.junit.After; 40 import org.junit.Before; 41 import org.junit.Test; 42 import org.junit.runner.RunWith; 43 import org.mockito.Mock; 44 import org.mockito.MockitoAnnotations; 45 46 import java.util.HashMap; 47 48 /** 49 * Unit test to verify various methods in {@link HeadsetPhoneState} 50 */ 51 @MediumTest 52 @RunWith(AndroidJUnit4.class) 53 public class HeadsetPhoneStateTest { 54 @Mock private ISub mISub; 55 @Mock private IBinder mISubBinder; 56 @Mock private HeadsetService mHeadsetService; 57 @Mock private TelephonyManager mTelephonyManager; 58 @Mock private SubscriptionManager mSubscriptionManager; 59 private HeadsetPhoneState mHeadsetPhoneState; 60 private BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); 61 private HandlerThread mHandlerThread; 62 private HashMap<String, IBinder> mServiceManagerMockedServices = new HashMap<>(); 63 private Object mServiceManagerOriginalServices; 64 65 @Before setUp()66 public void setUp() throws Exception { 67 if (Looper.myLooper() == null) { 68 Looper.prepare(); 69 } 70 PropertyInvalidatedCache.disableForTestMode(); 71 MockitoAnnotations.initMocks(this); 72 TelephonyManager.disableServiceHandleCaching(); 73 // Mock SubscriptionManager.getDefaultSubscriptionId() to return a valid value 74 when(mISub.getDefaultSubId()).thenReturn(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); 75 when(mISubBinder.queryLocalInterface(anyString())).thenReturn(mISub); 76 mServiceManagerMockedServices.put("isub", mISubBinder); 77 mServiceManagerOriginalServices = 78 TestUtils.replaceField(ServiceManager.class, "sCache", null, 79 mServiceManagerMockedServices); 80 // Stub other methods 81 when(mHeadsetService.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn( 82 mTelephonyManager); 83 when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager); 84 when(mHeadsetService.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)).thenReturn( 85 mSubscriptionManager); 86 mHandlerThread = new HandlerThread("HeadsetStateMachineTestHandlerThread"); 87 mHandlerThread.start(); 88 when(mHeadsetService.getStateMachinesThreadLooper()).thenReturn(mHandlerThread.getLooper()); 89 mHeadsetPhoneState = new HeadsetPhoneState(mHeadsetService); 90 } 91 92 @After tearDown()93 public void tearDown() throws Exception { 94 mHeadsetPhoneState.cleanup(); 95 mHandlerThread.quit(); 96 if (mServiceManagerOriginalServices != null) { 97 TestUtils.replaceField(ServiceManager.class, "sCache", null, 98 mServiceManagerOriginalServices); 99 mServiceManagerOriginalServices = null; 100 } 101 TelephonyManager.enableServiceHandleCaching(); 102 } 103 104 /** 105 * Verify that {@link PhoneStateListener#LISTEN_NONE} should result in no subscription 106 */ 107 @Test testListenForPhoneState_NoneResultsNoListen()108 public void testListenForPhoneState_NoneResultsNoListen() { 109 BluetoothDevice device1 = TestUtils.getTestDevice(mAdapter, 1); 110 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_NONE); 111 verifyZeroInteractions(mTelephonyManager); 112 } 113 114 /** 115 * Verify that {@link PhoneStateListener#LISTEN_SERVICE_STATE} should result in corresponding 116 * subscription 117 */ 118 @Test testListenForPhoneState_ServiceOnly()119 public void testListenForPhoneState_ServiceOnly() { 120 BluetoothDevice device1 = TestUtils.getTestDevice(mAdapter, 1); 121 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_SERVICE_STATE); 122 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE)); 123 verifyNoMoreInteractions(mTelephonyManager); 124 } 125 126 /** 127 * Verify that {@link PhoneStateListener#LISTEN_SERVICE_STATE} and 128 * {@link PhoneStateListener#LISTEN_SIGNAL_STRENGTHS} should result in corresponding 129 * subscription 130 */ 131 @Test testListenForPhoneState_ServiceAndSignalStrength()132 public void testListenForPhoneState_ServiceAndSignalStrength() { 133 BluetoothDevice device1 = TestUtils.getTestDevice(mAdapter, 1); 134 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_SERVICE_STATE 135 | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH); 136 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE 137 | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)); 138 } 139 140 /** 141 * Verify that partially turnning off {@link PhoneStateListener#LISTEN_SIGNAL_STRENGTHS} update 142 * should only unsubscribe signal strength update 143 */ 144 @Test testListenForPhoneState_ServiceAndSignalStrengthUpdateTurnOffSignalStrengh()145 public void testListenForPhoneState_ServiceAndSignalStrengthUpdateTurnOffSignalStrengh() { 146 BluetoothDevice device1 = TestUtils.getTestDevice(mAdapter, 1); 147 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_SERVICE_STATE 148 | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH); 149 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE 150 | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)); 151 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_SERVICE_STATE); 152 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_NONE)); 153 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE)); 154 } 155 156 /** 157 * Verify that completely disabling all updates should unsubscribe from everything 158 */ 159 @Test testListenForPhoneState_ServiceAndSignalStrengthUpdateTurnOffAll()160 public void testListenForPhoneState_ServiceAndSignalStrengthUpdateTurnOffAll() { 161 BluetoothDevice device1 = TestUtils.getTestDevice(mAdapter, 1); 162 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_SERVICE_STATE 163 | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH); 164 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE 165 | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)); 166 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_NONE); 167 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_NONE)); 168 } 169 170 /** 171 * Verify that when multiple devices tries to subscribe to the same indicator, the same 172 * subscription is not triggered twice. Also, when one of the device is unsubsidised from an 173 * indicator, the other device still remain subscribed. 174 */ 175 @Test testListenForPhoneState_MultiDevice_AllUpAllDown()176 public void testListenForPhoneState_MultiDevice_AllUpAllDown() { 177 BluetoothDevice device1 = TestUtils.getTestDevice(mAdapter, 1); 178 BluetoothDevice device2 = TestUtils.getTestDevice(mAdapter, 2); 179 // Enabling updates from first device should trigger subscription 180 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_SERVICE_STATE 181 | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH); 182 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE 183 | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)); 184 // Enabling updates from second device should not trigger the same subscription 185 mHeadsetPhoneState.listenForPhoneState(device2, PhoneStateListener.LISTEN_SERVICE_STATE 186 | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH); 187 // Disabling updates from first device should not cancel subscription 188 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_NONE); 189 // Disabling updates from second device should cancel subscription 190 mHeadsetPhoneState.listenForPhoneState(device2, PhoneStateListener.LISTEN_NONE); 191 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_NONE)); 192 } 193 194 /** 195 * Verity that two device each partially subscribe to an indicator result in subscription to 196 * both indicators. Also unsubscribing from one indicator from one device will not cause 197 * unrelated indicator from other device from being unsubscribed. 198 */ 199 @Test testListenForPhoneState_MultiDevice_PartialUpPartialDown()200 public void testListenForPhoneState_MultiDevice_PartialUpPartialDown() { 201 BluetoothDevice device1 = TestUtils.getTestDevice(mAdapter, 1); 202 BluetoothDevice device2 = TestUtils.getTestDevice(mAdapter, 2); 203 // Partially enabling updates from first device should trigger partial subscription 204 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_SERVICE_STATE); 205 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE)); 206 verifyNoMoreInteractions(mTelephonyManager); 207 // Partially enabling updates from second device should trigger partial subscription 208 mHeadsetPhoneState.listenForPhoneState(device2, 209 PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH); 210 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_NONE)); 211 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE 212 | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)); 213 // Partially disabling updates from first device should not cancel all subscription 214 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_NONE); 215 verify(mTelephonyManager, times(2)).listen(any(), eq(PhoneStateListener.LISTEN_NONE)); 216 verify(mTelephonyManager).listen( 217 any(), eq(PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)); 218 // Partially disabling updates from second device should cancel subscription 219 mHeadsetPhoneState.listenForPhoneState(device2, PhoneStateListener.LISTEN_NONE); 220 verify(mTelephonyManager, times(3)).listen(any(), eq(PhoneStateListener.LISTEN_NONE)); 221 } 222 } 223