• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.telephony.ims.cts;
18 
19 import android.os.Bundle;
20 import android.telephony.AccessNetworkConstants;
21 import android.telephony.TelephonyManager;
22 import android.telephony.ims.ImsCallProfile;
23 import android.telephony.ims.ImsCallSessionListener;
24 import android.telephony.ims.ImsStreamMediaProfile;
25 import android.telephony.ims.MediaQualityStatus;
26 import android.telephony.ims.MediaThreshold;
27 import android.telephony.ims.RtpHeaderExtensionType;
28 import android.telephony.ims.SrvccCall;
29 import android.telephony.ims.feature.CapabilityChangeRequest;
30 import android.telephony.ims.feature.MmTelFeature;
31 import android.telephony.ims.stub.ImsCallSessionImplBase;
32 import android.telephony.ims.stub.ImsRegistrationImplBase;
33 import android.util.Log;
34 
35 import java.util.List;
36 import java.util.Set;
37 import java.util.concurrent.CompletableFuture;
38 import java.util.concurrent.CountDownLatch;
39 import java.util.concurrent.ExecutionException;
40 import java.util.concurrent.Executor;
41 import java.util.function.Consumer;
42 
43 public class TestMmTelFeature extends MmTelFeature {
44 
45     private final TestImsService.RemovedListener mRemovedListener;
46     private final TestImsService.ReadyListener mReadyListener;
47     private final TestImsService.CapabilitiesSetListener mCapSetListener;
48 
49     private static final String TAG = "CtsTestImsService";
50     public static ConferenceHelper sConferenceHelper = new ConferenceHelper();
51 
52     private MmTelCapabilities mCapabilities =
53             new MmTelCapabilities(MmTelCapabilities.CAPABILITY_TYPE_SMS);
54     private TestImsSmsImpl mSmsImpl;
55     private Set<RtpHeaderExtensionType> mOfferedRtpHeaderExtensionTypes;
56     private CountDownLatch mOfferedRtpHeaderExtensionLatch = new CountDownLatch(1);
57     private MediaThreshold mSetMediaThreshold;
58     private CountDownLatch mSetMediaThresholdLatch = new CountDownLatch(1);
59     private int mTestPacketLossRateValue;
60     private int mTestJitterValue;
61     private long mTestInactivityTime;
62     private TestImsCallSessionImpl mCallSession;
63     private CountDownLatch mTerminalBasedCallWaitingLatch = new CountDownLatch(1);
64     private boolean mIsTerminalBasedCallWaitingNotified = false;
65     private boolean mIsTerminalBasedCallWaitingEnabled = false;
66     private CountDownLatch mSrvccStateLatch = new CountDownLatch(1);
67     private int mSrvccState = TelephonyManager.SRVCC_STATE_HANDOVER_NONE;
68     private Consumer<List<SrvccCall>> mSrvccStartedCallback;
69 
TestMmTelFeature(TestImsService.ReadyListener readyListener, TestImsService.RemovedListener removedListener, TestImsService.CapabilitiesSetListener setListener)70     TestMmTelFeature(TestImsService.ReadyListener readyListener,
71             TestImsService.RemovedListener removedListener,
72             TestImsService.CapabilitiesSetListener setListener) {
73         Log.d(TAG, "TestMmTelFeature with default constructor");
74         mReadyListener = readyListener;
75         mRemovedListener = removedListener;
76         mCapSetListener = setListener;
77         mSmsImpl = new TestImsSmsImpl();
78         // Must set the state to READY in the constructor - onFeatureReady depends on the state
79         // being ready.
80         setFeatureState(STATE_READY);
81     }
82 
TestMmTelFeature(TestImsService.ReadyListener readyListener, TestImsService.RemovedListener removedListener, TestImsService.CapabilitiesSetListener setListener, Executor executor)83     TestMmTelFeature(TestImsService.ReadyListener readyListener,
84             TestImsService.RemovedListener removedListener,
85             TestImsService.CapabilitiesSetListener setListener, Executor executor) {
86         super(executor);
87         Log.d(TAG, "TestMmTelFeature with Executor constructor");
88         mReadyListener = readyListener;
89         mRemovedListener = removedListener;
90         mCapSetListener = setListener;
91         mSmsImpl = new TestImsSmsImpl();
92         // Must set the state to READY in the constructor - onFeatureReady depends on the state
93         // being ready.
94         setFeatureState(STATE_READY);
95     }
96 
getSmsImplementation()97     public TestImsSmsImpl getSmsImplementation() {
98         return mSmsImpl;
99     }
100 
101     @Override
queryCapabilityConfiguration(int capability, int radioTech)102     public boolean queryCapabilityConfiguration(int capability, int radioTech) {
103         if (ImsUtils.VDBG) {
104             Log.d(TAG, "queryCapabilityConfiguration called with capability: " + capability);
105         }
106         return mCapabilities.isCapable(capability);
107     }
108 
109     @Override
changeEnabledCapabilities(CapabilityChangeRequest request, CapabilityCallbackProxy c)110     public void changeEnabledCapabilities(CapabilityChangeRequest request,
111             CapabilityCallbackProxy c) {
112         List<CapabilityChangeRequest.CapabilityPair> pairs = request.getCapabilitiesToEnable();
113         for (CapabilityChangeRequest.CapabilityPair pair : pairs) {
114             if (pair.getRadioTech() == ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
115                 mCapabilities.addCapabilities(pair.getCapability());
116             }
117         }
118         pairs = request.getCapabilitiesToDisable();
119         for (CapabilityChangeRequest.CapabilityPair pair : pairs) {
120             if (pair.getRadioTech() == ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
121                 mCapabilities.removeCapabilities(pair.getCapability());
122             }
123         }
124         mCapSetListener.onSet();
125     }
126 
127     @Override
onFeatureReady()128     public void onFeatureReady() {
129         if (ImsUtils.VDBG) {
130             Log.d(TAG, "TestMmTelFeature.onFeatureReady called");
131         }
132         mReadyListener.onReady();
133     }
134 
135     @Override
onFeatureRemoved()136     public void onFeatureRemoved() {
137         if (ImsUtils.VDBG) {
138             Log.d(TAG, "TestMmTelFeature.onFeatureRemoved called");
139         }
140         mRemovedListener.onRemoved();
141     }
142 
143     @Override
changeOfferedRtpHeaderExtensionTypes(Set<RtpHeaderExtensionType> extensionTypes)144     public void changeOfferedRtpHeaderExtensionTypes(Set<RtpHeaderExtensionType> extensionTypes) {
145         mOfferedRtpHeaderExtensionTypes = extensionTypes;
146         mOfferedRtpHeaderExtensionLatch.countDown();
147     }
148 
149     @Override
setMediaThreshold(int sessionType, MediaThreshold threshold)150     public void setMediaThreshold(int sessionType, MediaThreshold threshold) {
151         Log.d(TAG, "setMediaThreshold" + threshold);
152         int[] packetLossThreshold = threshold.getThresholdsRtpPacketLossRate();
153         int[] jitterThreshold = threshold.getThresholdsRtpJitterMillis();
154         long[] inactivityTimeThreshold = threshold.getThresholdsRtpInactivityTimeMillis();
155         if (packetLossThreshold != null && packetLossThreshold.length == 1
156                 && packetLossThreshold[0] == mTestPacketLossRateValue
157                 && jitterThreshold[0] == mTestJitterValue
158                 && inactivityTimeThreshold[0] == mTestInactivityTime) {
159             mSetMediaThreshold = threshold;
160             mSetMediaThresholdLatch.countDown();
161         } else {
162             Log.d(TAG, "setMediaThreshold, this is not config update for test" + threshold);
163         }
164     }
165 
166     @Override
createCallProfile(int serviceType, int callType)167     public ImsCallProfile createCallProfile(int serviceType, int callType) {
168         ImsStreamMediaProfile mediaProfile = new ImsStreamMediaProfile(
169                 ImsStreamMediaProfile.AUDIO_QUALITY_AMR,
170                 ImsStreamMediaProfile.DIRECTION_INVALID,
171                 ImsStreamMediaProfile.VIDEO_QUALITY_NONE,
172                 ImsStreamMediaProfile.DIRECTION_INVALID,
173                 ImsStreamMediaProfile.RTT_MODE_DISABLED);
174         ImsCallProfile profile = new ImsCallProfile(serviceType, callType,
175                     new Bundle(), mediaProfile);
176         return profile;
177     }
178 
179     @Override
createCallSession(ImsCallProfile profile)180     public ImsCallSessionImplBase createCallSession(ImsCallProfile profile) {
181         ImsCallSessionImplBase s = new TestImsCallSessionImpl(profile);
182         mCallSession = (TestImsCallSessionImpl) s;
183         onCallCreate(mCallSession);
184         return s != null ? s : null;
185     }
186 
187     @Override
setTerminalBasedCallWaitingStatus(boolean enabled)188     public void setTerminalBasedCallWaitingStatus(boolean enabled) {
189         mIsTerminalBasedCallWaitingNotified = true;
190         mIsTerminalBasedCallWaitingEnabled = enabled;
191         mTerminalBasedCallWaitingLatch.countDown();
192     }
193 
194     @Override
notifySrvccStarted(Consumer<List<SrvccCall>> cb)195     public void notifySrvccStarted(Consumer<List<SrvccCall>> cb) {
196         mSrvccState = TelephonyManager.SRVCC_STATE_HANDOVER_STARTED;
197         mSrvccStartedCallback = cb;
198     }
199 
200     @Override
notifySrvccCompleted()201     public void notifySrvccCompleted() {
202         mSrvccState = TelephonyManager.SRVCC_STATE_HANDOVER_COMPLETED;
203         mSrvccStartedCallback = null;
204     }
205 
206     @Override
notifySrvccFailed()207     public void notifySrvccFailed() {
208         mSrvccState = TelephonyManager.SRVCC_STATE_HANDOVER_FAILED;
209         mSrvccStartedCallback = null;
210     }
211 
212     @Override
notifySrvccCanceled()213     public void notifySrvccCanceled() {
214         mSrvccState = TelephonyManager.SRVCC_STATE_HANDOVER_CANCELED;
215         mSrvccStartedCallback = null;
216     }
217 
218     @Override
queryMediaQualityStatus(int sessionType)219     public MediaQualityStatus queryMediaQualityStatus(int sessionType) {
220         if (!mCallSession.isInCall()) {
221             Log.d(TAG, "queryMediaQualityStatus: no call.");
222             return null;
223         }
224         MediaQualityStatus status = new MediaQualityStatus(mCallSession.getCallId(),
225                     MediaQualityStatus.MEDIA_SESSION_TYPE_AUDIO,
226                     AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
227                     0 /*packetLossRate*/, 0 /*jitter*/, 0 /*inactivityTime*/);
228 
229         Log.d(TAG, "queryMediaQualityStatus: current status " + status);
230         return status;
231     }
232 
setCapabilities(MmTelCapabilities capabilities)233     public void setCapabilities(MmTelCapabilities capabilities) {
234         mCapabilities = capabilities;
235     }
236 
getCapabilities()237     public MmTelCapabilities getCapabilities() {
238         return mCapabilities;
239     }
240 
getOfferedRtpHeaderExtensionTypes()241     public Set<RtpHeaderExtensionType> getOfferedRtpHeaderExtensionTypes() {
242         return mOfferedRtpHeaderExtensionTypes;
243     }
244 
getOfferedRtpHeaderExtensionLatch()245     public CountDownLatch getOfferedRtpHeaderExtensionLatch() {
246         return mOfferedRtpHeaderExtensionLatch;
247     }
248 
getSetMediaThreshold()249     public MediaThreshold getSetMediaThreshold() {
250         Log.d(TAG, "getSetMediaThreshold: " + mSetMediaThreshold);
251         return mSetMediaThreshold;
252     }
253 
getSetMediaThresholdLatch(int testPacketLossRate, int testJitter, long testInactivityMillis)254     public CountDownLatch getSetMediaThresholdLatch(int testPacketLossRate, int testJitter,
255             long testInactivityMillis) {
256         mTestPacketLossRateValue = testPacketLossRate;
257         mTestJitterValue = testJitter;
258         mTestInactivityTime = testInactivityMillis;
259         return mSetMediaThresholdLatch;
260     }
261 
getImsCallsession()262     public TestImsCallSessionImpl getImsCallsession() {
263         return mCallSession;
264     }
265 
isCallSessionCreated()266     public boolean isCallSessionCreated() {
267         return (mCallSession != null);
268     }
269 
onIncomingCallReceived(Bundle extras)270     public void onIncomingCallReceived(Bundle extras) {
271         Log.d(TAG, "onIncomingCallReceived");
272 
273         ImsStreamMediaProfile mediaProfile = new ImsStreamMediaProfile(
274                 ImsStreamMediaProfile.AUDIO_QUALITY_AMR,
275                 ImsStreamMediaProfile.DIRECTION_SEND_RECEIVE,
276                 ImsStreamMediaProfile.VIDEO_QUALITY_NONE,
277                 ImsStreamMediaProfile.DIRECTION_INVALID,
278                 ImsStreamMediaProfile.RTT_MODE_DISABLED);
279 
280         ImsCallProfile callProfile = new ImsCallProfile(ImsCallProfile.SERVICE_TYPE_NORMAL,
281                 ImsCallProfile.CALL_TYPE_VOICE, new Bundle(), mediaProfile);
282 
283         TestImsCallSessionImpl incomingSession = new TestImsCallSessionImpl(callProfile);
284         mCallSession = incomingSession;
285 
286         Executor executor = incomingSession.getExecutor();
287         executor.execute(() -> {
288             notifyIncomingCall(incomingSession, extras);
289         });
290     }
291 
292 
onIncomingCallReceivedReturnListener(Bundle extras)293     public ImsCallSessionListener onIncomingCallReceivedReturnListener(Bundle extras) {
294         Log.d(TAG, "onIncomingCallReceivedReturnListener");
295 
296         ImsStreamMediaProfile mediaProfile = new ImsStreamMediaProfile(
297                 ImsStreamMediaProfile.AUDIO_QUALITY_AMR,
298                 ImsStreamMediaProfile.DIRECTION_SEND_RECEIVE,
299                 ImsStreamMediaProfile.VIDEO_QUALITY_NONE,
300                 ImsStreamMediaProfile.DIRECTION_INVALID,
301                 ImsStreamMediaProfile.RTT_MODE_DISABLED);
302 
303         ImsCallProfile callProfile = new ImsCallProfile(ImsCallProfile.SERVICE_TYPE_NORMAL,
304                 ImsCallProfile.CALL_TYPE_VOICE, new Bundle(), mediaProfile);
305 
306         TestImsCallSessionImpl incomingSession = new TestImsCallSessionImpl(callProfile);
307         mCallSession = incomingSession;
308         String callId = mCallSession.getCallId();
309 
310         CompletableFuture<ImsCallSessionListener> future =
311                 CompletableFuture.supplyAsync(()->
312                         notifyIncomingCall(incomingSession, callId, extras),
313                         incomingSession.getExecutor());
314         try {
315             ImsCallSessionListener isl = future.get();
316             return future.get();
317         } catch (ExecutionException | InterruptedException e) {
318             e.printStackTrace();
319             return null;
320         }
321     }
322 
onCallCreate(TestImsCallSessionImpl session)323     private void onCallCreate(TestImsCallSessionImpl session) {
324         if (sConferenceHelper != null) {
325             sConferenceHelper.addSession(session);
326             session.setConferenceHelper(sConferenceHelper);
327         }
328     }
329 
getConferenceHelper()330     public ConferenceHelper getConferenceHelper() {
331         return sConferenceHelper;
332     }
333 
getTerminalBasedCallWaitingLatch()334     public CountDownLatch getTerminalBasedCallWaitingLatch() {
335         return mTerminalBasedCallWaitingLatch;
336     }
337 
resetTerminalBasedCallWaitingLatch()338     public CountDownLatch resetTerminalBasedCallWaitingLatch() {
339         mIsTerminalBasedCallWaitingNotified = false;
340         mTerminalBasedCallWaitingLatch = new CountDownLatch(1);
341         return mTerminalBasedCallWaitingLatch;
342     }
343 
isTerminalBasedCallWaitingNotified()344     public boolean isTerminalBasedCallWaitingNotified() {
345         return mIsTerminalBasedCallWaitingNotified;
346     }
347 
isTerminalBasedCallWaitingEnabled()348     public boolean isTerminalBasedCallWaitingEnabled() {
349         return mIsTerminalBasedCallWaitingEnabled;
350     }
351 
getSrvccStateLatch()352     public CountDownLatch getSrvccStateLatch() {
353         return mSrvccStateLatch;
354     }
355 
getSrvccState()356     public int getSrvccState() {
357         return mSrvccState;
358     }
359 
notifySrvccCall(List<SrvccCall> profiles)360     public void notifySrvccCall(List<SrvccCall> profiles) {
361         if (mSrvccStartedCallback != null) {
362             mSrvccStartedCallback.accept(profiles);
363             mSrvccStartedCallback = null;
364         }
365     }
366 
resetSrvccState()367     public void resetSrvccState() {
368         mSrvccStateLatch = new CountDownLatch(1);
369         mSrvccState = TelephonyManager.SRVCC_STATE_HANDOVER_NONE;
370         mSrvccStartedCallback = null;
371     }
372 }
373