• 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         Log.d(TAG, "createCallSession");
182         ImsCallSessionImplBase s = new TestImsCallSessionImpl(profile);
183         mCallSession = (TestImsCallSessionImpl) s;
184         onCallCreate(mCallSession);
185         return s != null ? s : null;
186     }
187 
188     @Override
setTerminalBasedCallWaitingStatus(boolean enabled)189     public void setTerminalBasedCallWaitingStatus(boolean enabled) {
190         mIsTerminalBasedCallWaitingNotified = true;
191         mIsTerminalBasedCallWaitingEnabled = enabled;
192         mTerminalBasedCallWaitingLatch.countDown();
193     }
194 
195     @Override
notifySrvccStarted(Consumer<List<SrvccCall>> cb)196     public void notifySrvccStarted(Consumer<List<SrvccCall>> cb) {
197         mSrvccState = TelephonyManager.SRVCC_STATE_HANDOVER_STARTED;
198         mSrvccStartedCallback = cb;
199     }
200 
201     @Override
notifySrvccCompleted()202     public void notifySrvccCompleted() {
203         mSrvccState = TelephonyManager.SRVCC_STATE_HANDOVER_COMPLETED;
204         mSrvccStartedCallback = null;
205     }
206 
207     @Override
notifySrvccFailed()208     public void notifySrvccFailed() {
209         mSrvccState = TelephonyManager.SRVCC_STATE_HANDOVER_FAILED;
210         mSrvccStartedCallback = null;
211     }
212 
213     @Override
notifySrvccCanceled()214     public void notifySrvccCanceled() {
215         mSrvccState = TelephonyManager.SRVCC_STATE_HANDOVER_CANCELED;
216         mSrvccStartedCallback = null;
217     }
218 
219     @Override
queryMediaQualityStatus(int sessionType)220     public MediaQualityStatus queryMediaQualityStatus(int sessionType) {
221         if (!mCallSession.isInCall()) {
222             Log.d(TAG, "queryMediaQualityStatus: no call.");
223             return null;
224         }
225         MediaQualityStatus status = new MediaQualityStatus(mCallSession.getCallId(),
226                     MediaQualityStatus.MEDIA_SESSION_TYPE_AUDIO,
227                     AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
228                     0 /*packetLossRate*/, 0 /*jitter*/, 0 /*inactivityTime*/);
229 
230         Log.d(TAG, "queryMediaQualityStatus: current status " + status);
231         return status;
232     }
233 
setCapabilities(MmTelCapabilities capabilities)234     public void setCapabilities(MmTelCapabilities capabilities) {
235         mCapabilities = capabilities;
236     }
237 
getCapabilities()238     public MmTelCapabilities getCapabilities() {
239         return mCapabilities;
240     }
241 
getOfferedRtpHeaderExtensionTypes()242     public Set<RtpHeaderExtensionType> getOfferedRtpHeaderExtensionTypes() {
243         return mOfferedRtpHeaderExtensionTypes;
244     }
245 
getOfferedRtpHeaderExtensionLatch()246     public CountDownLatch getOfferedRtpHeaderExtensionLatch() {
247         return mOfferedRtpHeaderExtensionLatch;
248     }
249 
getSetMediaThreshold()250     public MediaThreshold getSetMediaThreshold() {
251         Log.d(TAG, "getSetMediaThreshold: " + mSetMediaThreshold);
252         return mSetMediaThreshold;
253     }
254 
getSetMediaThresholdLatch(int testPacketLossRate, int testJitter, long testInactivityMillis)255     public CountDownLatch getSetMediaThresholdLatch(int testPacketLossRate, int testJitter,
256             long testInactivityMillis) {
257         mTestPacketLossRateValue = testPacketLossRate;
258         mTestJitterValue = testJitter;
259         mTestInactivityTime = testInactivityMillis;
260         return mSetMediaThresholdLatch;
261     }
262 
getImsCallsession()263     public TestImsCallSessionImpl getImsCallsession() {
264         Log.d(TAG, "getImsCallsession");
265         return mCallSession;
266     }
267 
isCallSessionCreated()268     public boolean isCallSessionCreated() {
269         return (mCallSession != null);
270     }
271 
onIncomingCallReceived(Bundle extras)272     public void onIncomingCallReceived(Bundle extras) {
273         Log.d(TAG, "onIncomingCallReceived");
274 
275         ImsStreamMediaProfile mediaProfile = new ImsStreamMediaProfile(
276                 ImsStreamMediaProfile.AUDIO_QUALITY_AMR,
277                 ImsStreamMediaProfile.DIRECTION_SEND_RECEIVE,
278                 ImsStreamMediaProfile.VIDEO_QUALITY_NONE,
279                 ImsStreamMediaProfile.DIRECTION_INVALID,
280                 ImsStreamMediaProfile.RTT_MODE_DISABLED);
281 
282         ImsCallProfile callProfile = new ImsCallProfile(ImsCallProfile.SERVICE_TYPE_NORMAL,
283                 ImsCallProfile.CALL_TYPE_VOICE, new Bundle(), mediaProfile);
284 
285         TestImsCallSessionImpl incomingSession = new TestImsCallSessionImpl(callProfile);
286         mCallSession = incomingSession;
287 
288         Executor executor = incomingSession.getExecutor();
289         executor.execute(() -> {
290             notifyIncomingCall(incomingSession, extras);
291         });
292     }
293 
294 
onIncomingCallReceivedReturnListener(Bundle extras)295     public ImsCallSessionListener onIncomingCallReceivedReturnListener(Bundle extras) {
296         Log.d(TAG, "onIncomingCallReceivedReturnListener");
297 
298         ImsStreamMediaProfile mediaProfile = new ImsStreamMediaProfile(
299                 ImsStreamMediaProfile.AUDIO_QUALITY_AMR,
300                 ImsStreamMediaProfile.DIRECTION_SEND_RECEIVE,
301                 ImsStreamMediaProfile.VIDEO_QUALITY_NONE,
302                 ImsStreamMediaProfile.DIRECTION_INVALID,
303                 ImsStreamMediaProfile.RTT_MODE_DISABLED);
304 
305         ImsCallProfile callProfile = new ImsCallProfile(ImsCallProfile.SERVICE_TYPE_NORMAL,
306                 ImsCallProfile.CALL_TYPE_VOICE, new Bundle(), mediaProfile);
307 
308         TestImsCallSessionImpl incomingSession = new TestImsCallSessionImpl(callProfile);
309         mCallSession = incomingSession;
310         String callId = mCallSession.getCallId();
311 
312         CompletableFuture<ImsCallSessionListener> future =
313                 CompletableFuture.supplyAsync(()->
314                         notifyIncomingCall(incomingSession, callId, extras),
315                         incomingSession.getExecutor());
316         try {
317             ImsCallSessionListener isl = future.get();
318             return future.get();
319         } catch (ExecutionException | InterruptedException e) {
320             e.printStackTrace();
321             return null;
322         }
323     }
324 
onCallCreate(TestImsCallSessionImpl session)325     private void onCallCreate(TestImsCallSessionImpl session) {
326         if (sConferenceHelper != null) {
327             sConferenceHelper.addSession(session);
328             session.setConferenceHelper(sConferenceHelper);
329         }
330     }
331 
getConferenceHelper()332     public ConferenceHelper getConferenceHelper() {
333         return sConferenceHelper;
334     }
335 
getTerminalBasedCallWaitingLatch()336     public CountDownLatch getTerminalBasedCallWaitingLatch() {
337         return mTerminalBasedCallWaitingLatch;
338     }
339 
resetTerminalBasedCallWaitingLatch()340     public CountDownLatch resetTerminalBasedCallWaitingLatch() {
341         mIsTerminalBasedCallWaitingNotified = false;
342         mTerminalBasedCallWaitingLatch = new CountDownLatch(1);
343         return mTerminalBasedCallWaitingLatch;
344     }
345 
isTerminalBasedCallWaitingNotified()346     public boolean isTerminalBasedCallWaitingNotified() {
347         return mIsTerminalBasedCallWaitingNotified;
348     }
349 
isTerminalBasedCallWaitingEnabled()350     public boolean isTerminalBasedCallWaitingEnabled() {
351         return mIsTerminalBasedCallWaitingEnabled;
352     }
353 
getSrvccStateLatch()354     public CountDownLatch getSrvccStateLatch() {
355         return mSrvccStateLatch;
356     }
357 
getSrvccState()358     public int getSrvccState() {
359         return mSrvccState;
360     }
361 
notifySrvccCall(List<SrvccCall> profiles)362     public void notifySrvccCall(List<SrvccCall> profiles) {
363         if (mSrvccStartedCallback != null) {
364             mSrvccStartedCallback.accept(profiles);
365             mSrvccStartedCallback = null;
366         }
367     }
368 
resetSrvccState()369     public void resetSrvccState() {
370         mSrvccStateLatch = new CountDownLatch(1);
371         mSrvccState = TelephonyManager.SRVCC_STATE_HANDOVER_NONE;
372         mSrvccStartedCallback = null;
373     }
374 }
375