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 SubscriptionManager.disableCaching(); 73 TelephonyManager.disableServiceHandleCaching(); 74 // Mock SubscriptionManager.getDefaultSubscriptionId() to return a valid value 75 when(mISub.getDefaultSubId()).thenReturn(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); 76 when(mISubBinder.queryLocalInterface(anyString())).thenReturn(mISub); 77 mServiceManagerMockedServices.put("isub", mISubBinder); 78 mServiceManagerOriginalServices = 79 TestUtils.replaceField(ServiceManager.class, "sCache", null, 80 mServiceManagerMockedServices); 81 // Stub other methods 82 when(mHeadsetService.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn( 83 mTelephonyManager); 84 when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager); 85 when(mHeadsetService.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)).thenReturn( 86 mSubscriptionManager); 87 mHandlerThread = new HandlerThread("HeadsetStateMachineTestHandlerThread"); 88 mHandlerThread.start(); 89 when(mHeadsetService.getStateMachinesThreadLooper()).thenReturn(mHandlerThread.getLooper()); 90 mHeadsetPhoneState = new HeadsetPhoneState(mHeadsetService); 91 } 92 93 @After tearDown()94 public void tearDown() throws Exception { 95 mHeadsetPhoneState.cleanup(); 96 mHandlerThread.quit(); 97 if (mServiceManagerOriginalServices != null) { 98 TestUtils.replaceField(ServiceManager.class, "sCache", null, 99 mServiceManagerOriginalServices); 100 mServiceManagerOriginalServices = null; 101 } 102 TelephonyManager.enableServiceHandleCaching(); 103 } 104 105 /** 106 * Verify that {@link PhoneStateListener#LISTEN_NONE} should result in no subscription 107 */ 108 @Test testListenForPhoneState_NoneResultsNoListen()109 public void testListenForPhoneState_NoneResultsNoListen() { 110 BluetoothDevice device1 = TestUtils.getTestDevice(mAdapter, 1); 111 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_NONE); 112 verifyZeroInteractions(mTelephonyManager); 113 } 114 115 /** 116 * Verify that {@link PhoneStateListener#LISTEN_SERVICE_STATE} should result in corresponding 117 * subscription 118 */ 119 @Test testListenForPhoneState_ServiceOnly()120 public void testListenForPhoneState_ServiceOnly() { 121 BluetoothDevice device1 = TestUtils.getTestDevice(mAdapter, 1); 122 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_SERVICE_STATE); 123 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE)); 124 verifyNoMoreInteractions(mTelephonyManager); 125 } 126 127 /** 128 * Verify that {@link PhoneStateListener#LISTEN_SERVICE_STATE} and 129 * {@link PhoneStateListener#LISTEN_SIGNAL_STRENGTHS} should result in corresponding 130 * subscription 131 */ 132 @Test testListenForPhoneState_ServiceAndSignalStrength()133 public void testListenForPhoneState_ServiceAndSignalStrength() { 134 BluetoothDevice device1 = TestUtils.getTestDevice(mAdapter, 1); 135 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_SERVICE_STATE 136 | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH); 137 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE 138 | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)); 139 } 140 141 /** 142 * Verify that partially turnning off {@link PhoneStateListener#LISTEN_SIGNAL_STRENGTHS} update 143 * should only unsubscribe signal strength update 144 */ 145 @Test testListenForPhoneState_ServiceAndSignalStrengthUpdateTurnOffSignalStrengh()146 public void testListenForPhoneState_ServiceAndSignalStrengthUpdateTurnOffSignalStrengh() { 147 BluetoothDevice device1 = TestUtils.getTestDevice(mAdapter, 1); 148 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_SERVICE_STATE 149 | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH); 150 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE 151 | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)); 152 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_SERVICE_STATE); 153 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_NONE)); 154 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE)); 155 } 156 157 /** 158 * Verify that completely disabling all updates should unsubscribe from everything 159 */ 160 @Test testListenForPhoneState_ServiceAndSignalStrengthUpdateTurnOffAll()161 public void testListenForPhoneState_ServiceAndSignalStrengthUpdateTurnOffAll() { 162 BluetoothDevice device1 = TestUtils.getTestDevice(mAdapter, 1); 163 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_SERVICE_STATE 164 | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH); 165 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE 166 | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)); 167 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_NONE); 168 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_NONE)); 169 } 170 171 /** 172 * Verify that when multiple devices tries to subscribe to the same indicator, the same 173 * subscription is not triggered twice. Also, when one of the device is unsubsidised from an 174 * indicator, the other device still remain subscribed. 175 */ 176 @Test testListenForPhoneState_MultiDevice_AllUpAllDown()177 public void testListenForPhoneState_MultiDevice_AllUpAllDown() { 178 BluetoothDevice device1 = TestUtils.getTestDevice(mAdapter, 1); 179 BluetoothDevice device2 = TestUtils.getTestDevice(mAdapter, 2); 180 // Enabling updates from first device should trigger subscription 181 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_SERVICE_STATE 182 | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH); 183 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE 184 | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)); 185 // Enabling updates from second device should not trigger the same subscription 186 mHeadsetPhoneState.listenForPhoneState(device2, PhoneStateListener.LISTEN_SERVICE_STATE 187 | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH); 188 // Disabling updates from first device should not cancel subscription 189 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_NONE); 190 // Disabling updates from second device should cancel subscription 191 mHeadsetPhoneState.listenForPhoneState(device2, PhoneStateListener.LISTEN_NONE); 192 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_NONE)); 193 } 194 195 /** 196 * Verity that two device each partially subscribe to an indicator result in subscription to 197 * both indicators. Also unsubscribing from one indicator from one device will not cause 198 * unrelated indicator from other device from being unsubscribed. 199 */ 200 @Test testListenForPhoneState_MultiDevice_PartialUpPartialDown()201 public void testListenForPhoneState_MultiDevice_PartialUpPartialDown() { 202 BluetoothDevice device1 = TestUtils.getTestDevice(mAdapter, 1); 203 BluetoothDevice device2 = TestUtils.getTestDevice(mAdapter, 2); 204 // Partially enabling updates from first device should trigger partial subscription 205 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_SERVICE_STATE); 206 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE)); 207 verifyNoMoreInteractions(mTelephonyManager); 208 // Partially enabling updates from second device should trigger partial subscription 209 mHeadsetPhoneState.listenForPhoneState(device2, 210 PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH); 211 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_NONE)); 212 verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE 213 | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)); 214 // Partially disabling updates from first device should not cancel all subscription 215 mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_NONE); 216 verify(mTelephonyManager, times(2)).listen(any(), eq(PhoneStateListener.LISTEN_NONE)); 217 verify(mTelephonyManager).listen( 218 any(), eq(PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)); 219 // Partially disabling updates from second device should cancel subscription 220 mHeadsetPhoneState.listenForPhoneState(device2, PhoneStateListener.LISTEN_NONE); 221 verify(mTelephonyManager, times(3)).listen(any(), eq(PhoneStateListener.LISTEN_NONE)); 222 } 223 } 224