1 /*
2  * Copyright (C) 2016 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.services.telephony;
18 
19 import android.content.AttributionSource;
20 import android.content.ContentResolver;
21 import android.os.Process;
22 import android.os.UserHandle;
23 import android.telephony.TelephonyManager;
24 
25 import static org.mockito.ArgumentMatchers.any;
26 import static org.mockito.ArgumentMatchers.anyInt;
27 import static org.mockito.ArgumentMatchers.anyString;
28 import static org.mockito.ArgumentMatchers.notNull;
29 import static org.mockito.Mockito.doNothing;
30 import static org.mockito.Mockito.mock;
31 import static org.mockito.Mockito.when;
32 
33 import android.content.Context;
34 import android.content.res.Resources;
35 import android.os.Bundle;
36 import android.os.PersistableBundle;
37 import android.telecom.PhoneAccountHandle;
38 import android.telecom.VideoProfile;
39 import android.telephony.CarrierConfigManager;
40 
41 import com.android.ims.ImsCall;
42 import com.android.internal.telephony.Call;
43 import com.android.internal.telephony.CallStateException;
44 import com.android.internal.telephony.Connection;
45 import com.android.internal.telephony.Phone;
46 import com.android.internal.telephony.PhoneConstants;
47 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
48 import com.android.internal.telephony.imsphone.ImsExternalConnection;
49 import com.android.internal.telephony.imsphone.ImsPhoneConnection;
50 
51 import org.mockito.Mock;
52 import org.mockito.MockitoAnnotations;
53 import org.mockito.invocation.InvocationOnMock;
54 import org.mockito.stubbing.Answer;
55 
56 import java.util.ArrayList;
57 import java.util.List;
58 
59 /**
60  * Mock Telephony Connection used in TelephonyConferenceController.java for testing purpose
61  */
62 
63 public class TestTelephonyConnection extends TelephonyConnection {
64 
65     @Mock
66     com.android.internal.telephony.Connection mMockRadioConnection;
67 
68     @Mock
69     Call mMockCall;
70 
71     @Mock
72     Context mMockContext;
73 
74     @Mock
75     ContentResolver mMockContentResolver;
76 
77     @Mock
78     Resources mMockResources;
79 
80     @Mock
81     TelephonyManager mMockTelephonyManager;
82 
83     @Mock
84     EmergencyNumberTracker mEmergencyNumberTracker;
85 
86     @Mock
87     ImsPhoneConnection mImsPhoneConnection;
88 
89     @Mock
90     ImsExternalConnection mImsExternalConnection;
91 
92     @Mock
93     ImsCall mImsCall;
94 
95     @Mock
96     TelecomAccountRegistry mTelecomAccountRegistry;
97 
98     @Mock
99     CarrierConfigManager mCarrierConfigManager;
100 
101     private boolean mIsImsConnection;
102     private boolean mIsImsExternalConnection;
103     private boolean mIsConferenceSupported = true;
104     private Phone mMockPhone;
105     private int mNotifyPhoneAccountChangedCount = 0;
106     private List<String> mLastConnectionEvents = new ArrayList<>();
107     private List<Bundle> mLastConnectionEventExtras = new ArrayList<>();
108     private Object mLock = new Object();
109     private PersistableBundle mCarrierConfig = new PersistableBundle();
110 
111     @Override
getOriginalConnection()112     public com.android.internal.telephony.Connection getOriginalConnection() {
113         if (mIsImsExternalConnection) {
114             return mImsExternalConnection;
115         } else if (mIsImsConnection) {
116             return mImsPhoneConnection;
117         } else {
118             return mMockRadioConnection;
119         }
120     }
121 
122     @Override
getCall()123     protected Call getCall() {
124         return mMockCall;
125     }
126 
TestTelephonyConnection()127     public TestTelephonyConnection() {
128         super(null, null, android.telecom.Call.Details.DIRECTION_INCOMING);
129         MockitoAnnotations.initMocks(this);
130 
131         AttributionSource attributionSource = new AttributionSource.Builder(
132                 Process.myUid()).build();
133 
134         mIsImsConnection = false;
135         mIsImsExternalConnection = false;
136         mMockPhone = mock(Phone.class);
137         mMockContext = mock(Context.class);
138         mMockTelephonyManager = mock(TelephonyManager.class);
139         mOriginalConnection = mMockRadioConnection;
140         // Set up mMockRadioConnection and mMockPhone to contain an active call
141         when(mMockRadioConnection.getState()).thenReturn(Call.State.ACTIVE);
142         when(mOriginalConnection.getState()).thenReturn(Call.State.ACTIVE);
143         when(mMockRadioConnection.getAudioCodec()).thenReturn(
144                 android.telecom.Connection.AUDIO_CODEC_AMR);
145         when(mImsPhoneConnection.getAudioCodec()).thenReturn(
146                 android.telecom.Connection.AUDIO_CODEC_AMR);
147         when(mMockRadioConnection.getCall()).thenReturn(mMockCall);
148         when(mMockRadioConnection.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_IMS);
149         when(mImsPhoneConnection.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_IMS);
150         doNothing().when(mMockRadioConnection).addListener(any(Connection.Listener.class));
151         doNothing().when(mMockRadioConnection).addPostDialListener(
152                 any(Connection.PostDialListener.class));
153         when(mEmergencyNumberTracker.getEmergencyNumber(anyString())).thenReturn(null);
154         when(mMockPhone.getEmergencyNumberTracker()).thenReturn(mEmergencyNumberTracker);
155         when(mMockPhone.getRingingCall()).thenReturn(mMockCall);
156         when(mMockPhone.getContext()).thenReturn(mMockContext);
157         when(mMockPhone.getCurrentSubscriberUris()).thenReturn(null);
158         when(mMockContext.getResources()).thenReturn(mMockResources);
159         when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver);
160         when(mMockContext.getSystemService(Context.TELEPHONY_SERVICE))
161                 .thenReturn(mMockTelephonyManager);
162         when(mMockContext.getAttributionSource()).thenReturn(attributionSource);
163         when(mMockContentResolver.getUserId()).thenReturn(UserHandle.USER_CURRENT);
164         when(mMockContentResolver.getAttributionSource()).thenReturn(attributionSource);
165         when(mMockResources.getBoolean(anyInt())).thenReturn(false);
166         when(mMockPhone.getDefaultPhone()).thenReturn(mMockPhone);
167         when(mMockPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_IMS);
168         when(mMockCall.getState()).thenReturn(Call.State.ACTIVE);
169         when(mMockCall.getPhone()).thenReturn(mMockPhone);
170         when(mMockPhone.getDefaultPhone()).thenReturn(mMockPhone);
171         when(mImsPhoneConnection.getImsCall()).thenReturn(mImsCall);
172         when(mTelecomAccountRegistry.isMergeCallSupported(notNull(PhoneAccountHandle.class)))
173                 .thenReturn(mIsConferenceSupported);
174         when(mTelecomAccountRegistry.isMergeImsCallSupported(notNull(PhoneAccountHandle.class)))
175                 .thenReturn(mIsImsConnection);
176         when(mTelecomAccountRegistry
177                 .isVideoConferencingSupported(notNull(PhoneAccountHandle.class))).thenReturn(false);
178         when(mTelecomAccountRegistry
179                 .isMergeOfWifiCallsAllowedWhenVoWifiOff(notNull(PhoneAccountHandle.class)))
180                 .thenReturn(false);
181         try {
182             doNothing().when(mMockCall).hangup();
183         } catch (CallStateException e) {
184             e.printStackTrace();
185         }
186     }
187 
setMockPhone(Phone newPhone)188     public void setMockPhone(Phone newPhone) {
189         mMockPhone = newPhone;
190     }
191 
192     @Override
getPhone()193     public Phone getPhone() {
194         return mMockPhone;
195     }
196 
cloneConnection()197     public TelephonyConnection cloneConnection() {
198         return this;
199     }
200 
201     @Override
notifyPhoneAccountChanged(PhoneAccountHandle pHandle)202     public void notifyPhoneAccountChanged(PhoneAccountHandle pHandle) {
203         mNotifyPhoneAccountChangedCount++;
204     }
205 
206     @Override
sendConnectionEvent(String event, Bundle extras)207     public void sendConnectionEvent(String event, Bundle extras) {
208         mLastConnectionEvents.add(event);
209         mLastConnectionEventExtras.add(extras);
210     }
211 
212     @Override
clearOriginalConnection()213     void clearOriginalConnection() {
214         // Do nothing since the original connection is mock object
215     }
216 
217     @Override
getCarrierConfig()218     public PersistableBundle getCarrierConfig() {
219         // Depends on PhoneGlobals for context in TelephonyConnection, do not implement during
220         // testing.
221         return mCarrierConfig;
222     }
223 
224     @Override
refreshConferenceSupported()225     public void refreshConferenceSupported() {
226         if (mIsImsConnection) {
227             super.refreshConferenceSupported();
228         }
229     }
230 
231     @Override
getResourceText(int messageId)232     public CharSequence getResourceText(int messageId) {
233         return "TEST";
234     }
235 
236     @Override
getResourceString(int id)237     public String getResourceString(int id) {
238         return "TEST";
239     }
240 
241     @Override
setConferenceSupported(boolean conferenceSupported)242     public void setConferenceSupported(boolean conferenceSupported) {
243         mIsConferenceSupported = conferenceSupported;
244     }
245 
246     @Override
isConferenceSupported()247     public boolean isConferenceSupported() {
248         return mIsConferenceSupported;
249     }
250 
251     @Override
getTelecomAccountRegistry(Context context)252     public TelecomAccountRegistry getTelecomAccountRegistry(Context context) {
253         return mTelecomAccountRegistry;
254     }
255 
setIsVideoCall(boolean isVideoCall)256     public void setIsVideoCall(boolean isVideoCall) {
257         if (isVideoCall) {
258             setVideoState(VideoProfile.STATE_TX_ENABLED);
259         } else {
260             setVideoState(VideoProfile.STATE_AUDIO_ONLY);
261         }
262     }
263 
setWasVideoCall(boolean wasVideoCall)264     public void setWasVideoCall(boolean wasVideoCall) {
265         when(mImsCall.wasVideoCall()).thenReturn(wasVideoCall);
266     }
267 
268     @Override
isWfcEnabled(Phone phone)269     boolean isWfcEnabled(Phone phone) {
270         // Requires ImsManager dependencies, mock for test.
271         return true;
272     }
273 
getNotifyPhoneAccountChangedCount()274     public int getNotifyPhoneAccountChangedCount() {
275         return mNotifyPhoneAccountChangedCount;
276     }
277 
getLastConnectionEvents()278     public List<String> getLastConnectionEvents() {
279         return mLastConnectionEvents;
280     }
281 
getLastConnectionEventExtras()282     public List<Bundle> getLastConnectionEventExtras() {
283         return mLastConnectionEventExtras;
284     }
285 
setIsImsConnection(boolean isImsConnection)286     public void setIsImsConnection(boolean isImsConnection) {
287         mIsImsConnection = isImsConnection;
288         when(mTelecomAccountRegistry.isMergeImsCallSupported(notNull(PhoneAccountHandle.class)))
289                 .thenReturn(isImsConnection && mIsConferenceSupported);
290     }
291 
setIsImsExternalConnection(boolean isExternalConnection)292     public void setIsImsExternalConnection(boolean isExternalConnection) {
293         mIsImsExternalConnection = isExternalConnection;
294     }
295 
setDownGradeVideoCall(boolean downgrade)296     public void setDownGradeVideoCall(boolean downgrade) {
297         PersistableBundle bundle = new PersistableBundle();
298         bundle.putBoolean(CarrierConfigManager.KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL,
299                 downgrade);
300         when(mMockContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
301                 .thenReturn(mCarrierConfigManager);
302         when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
303     }
304 
getCarrierConfigBundle()305     public PersistableBundle getCarrierConfigBundle() {
306         return mCarrierConfig;
307     }
308 
getMockImsPhoneConnection()309     public ImsPhoneConnection getMockImsPhoneConnection() {
310         return mImsPhoneConnection;
311     }
312 
setMockImsPhoneConnection(ImsPhoneConnection connection)313     public void setMockImsPhoneConnection(ImsPhoneConnection connection) {
314         mImsPhoneConnection = connection;
315     }
316 }
317