1 /*
2  * Copyright (C) 2019 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.internal.telephony;
18 
19 import static android.telephony.TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED;
20 import static android.telephony.TelephonyManager.EXTRA_ACTIVE_SIM_SUPPORTED_COUNT;
21 
22 import static org.junit.Assert.assertEquals;
23 import static org.mockito.ArgumentMatchers.any;
24 import static org.mockito.ArgumentMatchers.anyInt;
25 import static org.mockito.ArgumentMatchers.anyLong;
26 import static org.mockito.ArgumentMatchers.eq;
27 import static org.mockito.Mockito.clearInvocations;
28 import static org.mockito.Mockito.doReturn;
29 import static org.mockito.Mockito.never;
30 import static org.mockito.Mockito.verify;
31 
32 import android.content.Intent;
33 import android.os.AsyncResult;
34 import android.os.Handler;
35 import android.os.Message;
36 import android.telephony.PhoneCapability;
37 import android.test.suitebuilder.annotation.SmallTest;
38 import android.testing.AndroidTestingRunner;
39 import android.testing.TestableLooper;
40 
41 import org.junit.After;
42 import org.junit.Before;
43 import org.junit.Test;
44 import org.junit.runner.RunWith;
45 import org.mockito.ArgumentCaptor;
46 import org.mockito.Mock;
47 
48 @RunWith(AndroidTestingRunner.class)
49 @TestableLooper.RunWithLooper
50 public class PhoneConfigurationManagerTest extends TelephonyTest {
51     @Mock
52     Handler mHandler;
53     @Mock
54     CommandsInterface mMockCi;
55     @Mock
56     PhoneConfigurationManager.MockableInterface mMi;
57 
58     private static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 1;
59     PhoneConfigurationManager mPcm;
60 
61     @Before
setUp()62     public void setUp() throws Exception {
63         super.setUp(getClass().getSimpleName());
64         mPhone.mCi = mMockCi;
65         mCT.mCi = mMockCi;
66     }
67 
68     @After
tearDown()69     public void tearDown() throws Exception {
70         // Restore system properties.
71         super.tearDown();
72     }
73 
setRebootRequiredForConfigSwitch(boolean rebootRequired)74     private void setRebootRequiredForConfigSwitch(boolean rebootRequired) {
75         doReturn(rebootRequired).when(mMi).isRebootRequiredForModemConfigChange();
76     }
77 
init(int numOfSim)78     private void init(int numOfSim) throws Exception {
79         doReturn(numOfSim).when(mTelephonyManager).getActiveModemCount();
80         replaceInstance(PhoneConfigurationManager.class, "sInstance", null, null);
81         mPcm = PhoneConfigurationManager.init(mContext);
82         replaceInstance(PhoneConfigurationManager.class, "mMi", mPcm, mMi);
83         processAllMessages();
84     }
85 
86     /**
87      * Test that a single phone case results in our phone being active and the RIL called
88      */
89     @Test
90     @SmallTest
testGetPhoneCount()91     public void testGetPhoneCount() throws Exception {
92         init(1);
93         doReturn(1).when(mTelephonyManager).getActiveModemCount();
94         assertEquals(1, mPcm.getPhoneCount());
95         doReturn(2).when(mTelephonyManager).getActiveModemCount();
96         assertEquals(2, mPcm.getPhoneCount());
97     }
98 
99     @Test
100     @SmallTest
testEnablePhone()101     public void testEnablePhone() throws Exception {
102         init(1);
103         // Phone is null. No crash.
104         mPcm.enablePhone(null, true, null);
105 
106         Message message = new Message();
107         mPcm.enablePhone(mPhone, false, message);
108         verify(mMockCi).enableModem(eq(false), eq(message));
109     }
110 
111     @Test
112     @SmallTest
testGetDsdsCapability()113     public void testGetDsdsCapability() throws Exception {
114         init(1);
115         assertEquals(PhoneCapability.DEFAULT_SSSS_CAPABILITY, mPcm.getStaticPhoneCapability());
116 
117         ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
118         verify(mMockRadioConfig).getPhoneCapability(captor.capture());
119         Message msg = captor.getValue();
120         AsyncResult.forMessage(msg, PhoneCapability.DEFAULT_DSDS_CAPABILITY, null);
121         msg.sendToTarget();
122         processAllMessages();
123 
124         // Not static capability should indicate DSDS capable.
125         assertEquals(PhoneCapability.DEFAULT_DSDS_CAPABILITY, mPcm.getStaticPhoneCapability());
126     }
127 
128     @Test
129     @SmallTest
testSwitchMultiSimConfig_notDsdsCapable_shouldFail()130     public void testSwitchMultiSimConfig_notDsdsCapable_shouldFail() throws Exception {
131         init(1);
132         assertEquals(PhoneCapability.DEFAULT_SSSS_CAPABILITY, mPcm.getStaticPhoneCapability());
133 
134         // Try switching to dual SIM. Shouldn't work as we haven't indicated DSDS is supported.
135         mPcm.switchMultiSimConfig(2);
136         verify(mMockRadioConfig, never()).setModemsConfig(anyInt(), any());
137     }
138 
139     @Test
140     @SmallTest
testSwitchMultiSimConfig_dsdsCapable_noRebootRequired()141     public void testSwitchMultiSimConfig_dsdsCapable_noRebootRequired() throws Exception {
142         init(1);
143         // Register for multi SIM config change.
144         mPcm.registerForMultiSimConfigChange(mHandler, EVENT_MULTI_SIM_CONFIG_CHANGED, null);
145         verify(mHandler, never()).sendMessageAtTime(any(), anyLong());
146 
147         // Try switching to dual SIM. Shouldn't work as we haven't indicated DSDS is supported.
148         mPcm.switchMultiSimConfig(2);
149         verify(mMockRadioConfig, never()).setModemsConfig(anyInt(), any());
150 
151         // Send static capability back to indicate DSDS is supported.
152         clearInvocations(mMockRadioConfig);
153         testGetDsdsCapability();
154 
155         // Try to switch to DSDS.
156         setRebootRequiredForConfigSwitch(false);
157         mPcm.switchMultiSimConfig(2);
158         ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
159         verify(mMockRadioConfig).setModemsConfig(eq(2), captor.capture());
160 
161         // Send message back to indicate switch success.
162         Message message = captor.getValue();
163         AsyncResult.forMessage(message, null, null);
164         message.sendToTarget();
165         processAllMessages();
166 
167         // Verify set system property being called.
168         verify(mMi).setMultiSimProperties(2);
169         verify(mMi).notifyPhoneFactoryOnMultiSimConfigChanged(any(), eq(2));
170 
171         // Capture and verify registration notification.
172         verify(mHandler).sendMessageAtTime(captor.capture(), anyLong());
173         message = captor.getValue();
174         assertEquals(EVENT_MULTI_SIM_CONFIG_CHANGED, message.what);
175         assertEquals(2, ((AsyncResult) message.obj).result);
176 
177         // Capture and verify broadcast.
178         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
179         verify(mContext).sendBroadcast(intentCaptor.capture());
180         Intent intent = intentCaptor.getValue();
181         assertEquals(ACTION_MULTI_SIM_CONFIG_CHANGED, intent.getAction());
182         assertEquals(2, intent.getIntExtra(
183                 EXTRA_ACTIVE_SIM_SUPPORTED_COUNT, 0));
184 
185         // Verify RIL notification.
186         verify(mMockCi).onSlotActiveStatusChange(true);
187     }
188 }
189