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