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.app.Service;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.os.Binder;
23 import android.os.IBinder;
24 import android.telephony.ims.ImsService;
25 import android.telephony.ims.feature.MmTelFeature;
26 import android.telephony.ims.feature.RcsFeature;
27 import android.telephony.ims.stub.ImsConfigImplBase;
28 import android.telephony.ims.stub.ImsFeatureConfiguration;
29 import android.telephony.ims.stub.ImsRegistrationImplBase;
30 import android.util.Log;
31 
32 
33 import java.util.concurrent.CountDownLatch;
34 import java.util.concurrent.TimeUnit;
35 
36 /**
37  * A Test ImsService that will verify ImsService functionality.
38  */
39 public class TestImsService extends Service {
40 
41     private static final String TAG = "GtsImsTestImsService";
42 
43     private static ImsRegistrationImplBase sImsRegistrationImplBase = new ImsRegistrationImplBase();
44 
45     private TestRcsFeature mTestRcsFeature;
46     private TestMmTelFeature mTestMmTelFeature;
47     private TestImsConfig mTestImsConfig;
48     private ImsService mTestImsService;
49     private boolean mIsEnabled = false;
50     private ImsFeatureConfiguration mFeatureConfig;
51     private final Object mLock = new Object();
52 
53     public static final int LATCH_FEATURES_READY = 0;
54     public static final int LATCH_ENABLE_IMS = 1;
55     public static final int LATCH_DISABLE_IMS = 2;
56     public static final int LATCH_CREATE_MMTEL = 3;
57     public static final int LATCH_CREATE_RCS = 4;
58     public static final int LATCH_REMOVE_MMTEL = 5;
59     public static final int LATCH_REMOVE_RCS = 6;
60     public static final int LATCH_MMTEL_READY = 7;
61     public static final int LATCH_RCS_READY = 8;
62     public static final int LATCH_MMTEL_CAP_SET = 9;
63     public static final int LATCH_RCS_CAP_SET = 10;
64     private static final int LATCH_MAX = 11;
65     protected static final CountDownLatch[] sLatches = new CountDownLatch[LATCH_MAX];
66     static {
67         for (int i = 0; i < LATCH_MAX; i++) {
68             sLatches[i] = new CountDownLatch(1);
69         }
70     }
71 
72     interface RemovedListener {
onRemoved()73         void onRemoved();
74     }
75     interface ReadyListener {
onReady()76         void onReady();
77     }
78     interface CapabilitiesSetListener {
onSet()79         void onSet();
80     }
81 
82     // This is defined here instead TestImsService extending ImsService directly because the GTS
83     // tests were failing to run on pre-P devices. Not sure why, but TestImsService is loaded
84     // even if it isn't used.
85     private class ImsServiceUT extends ImsService {
86 
ImsServiceUT(Context context)87         ImsServiceUT(Context context) {
88             // As explained above, ImsServiceUT is created in order to get around classloader
89             // restrictions. Attach the base context from the wrapper ImsService.
90             if (getBaseContext() == null) {
91                 attachBaseContext(context);
92             }
93             mTestImsConfig = new TestImsConfig();
94         }
95 
96         @Override
querySupportedImsFeatures()97         public ImsFeatureConfiguration querySupportedImsFeatures() {
98             return getFeatureConfig();
99         }
100 
101         @Override
readyForFeatureCreation()102         public void readyForFeatureCreation() {
103             synchronized (mLock) {
104                 countDownLatch(LATCH_FEATURES_READY);
105             }
106         }
107 
108         @Override
enableIms(int slotId)109         public void enableIms(int slotId) {
110             synchronized (mLock) {
111                 countDownLatch(LATCH_ENABLE_IMS);
112                 setIsEnabled(true);
113             }
114         }
115 
116         @Override
disableIms(int slotId)117         public void disableIms(int slotId) {
118             synchronized (mLock) {
119                 countDownLatch(LATCH_DISABLE_IMS);
120                 setIsEnabled(false);
121             }
122         }
123 
124         @Override
createRcsFeature(int slotId)125         public RcsFeature createRcsFeature(int slotId) {
126             synchronized (mLock) {
127                 countDownLatch(LATCH_CREATE_RCS);
128                 mTestRcsFeature = new TestRcsFeature(
129                         //onReady
130                         () -> {
131                             synchronized (mLock) {
132                                 countDownLatch(LATCH_RCS_READY);
133                             }
134                         },
135                         //onRemoved
136                         () -> {
137                             synchronized (mLock) {
138                                 countDownLatch(LATCH_REMOVE_RCS);
139                                 mTestRcsFeature = null;
140                             }
141                         },
142                         //onCapabilitiesSet
143                         () -> {
144                             synchronized (mLock) {
145                                 countDownLatch(LATCH_RCS_CAP_SET);
146                             }
147                         }
148                         );
149                 return mTestRcsFeature;
150             }
151         }
152 
153         @Override
getConfig(int slotId)154         public ImsConfigImplBase getConfig(int slotId) {
155             return mTestImsConfig;
156         }
157 
158         @Override
createMmTelFeature(int slotId)159         public MmTelFeature createMmTelFeature(int slotId) {
160             synchronized (mLock) {
161                 countDownLatch(LATCH_CREATE_MMTEL);
162                 mTestMmTelFeature = new TestMmTelFeature(
163                         //onReady
164                         () -> {
165                             synchronized (mLock) {
166                                 countDownLatch(LATCH_MMTEL_READY);
167                             }
168                         },
169                         //onRemoved
170                         () -> {
171                             synchronized (mLock) {
172                                 countDownLatch(LATCH_REMOVE_MMTEL);
173                                 mTestMmTelFeature = null;
174                             }
175                         },
176                         //onCapabilitiesSet
177                         () -> {
178                             synchronized (mLock) {
179                                 countDownLatch(LATCH_MMTEL_CAP_SET);
180                             }
181                         }
182                         );
183                 return mTestMmTelFeature;
184             }
185         }
186 
187         @Override
getRegistration(int slotId)188         public ImsRegistrationImplBase getRegistration(int slotId) {
189             return sImsRegistrationImplBase;
190         }
191     }
192 
193     private final LocalBinder mBinder = new LocalBinder();
194     // For local access of this Service.
195     class LocalBinder extends Binder {
getService()196         TestImsService getService() {
197             return TestImsService.this;
198         }
199     }
200 
getImsService()201     protected ImsService getImsService() {
202         synchronized (mLock) {
203             if (mTestImsService != null) {
204                 return mTestImsService;
205             }
206             mTestImsService = new ImsServiceUT(this);
207             return mTestImsService;
208         }
209     }
210 
211     @Override
onBind(Intent intent)212     public IBinder onBind(Intent intent) {
213         if ("android.telephony.ims.ImsService".equals(intent.getAction())) {
214             if (ImsUtils.VDBG) {
215                 Log.d(TAG, "onBind-Remote");
216             }
217             return getImsService().onBind(intent);
218         }
219         if (ImsUtils.VDBG) {
220             Log.i(TAG, "onBind-Local");
221         }
222         return mBinder;
223     }
224 
resetState()225     public void resetState() {
226         synchronized (mLock) {
227             mTestMmTelFeature = null;
228             mTestRcsFeature = null;
229             mIsEnabled = false;
230             for (int i = 0; i < LATCH_MAX; i++) {
231                 sLatches[i] = new CountDownLatch(1);
232             }
233         }
234     }
235 
236     // Sets the feature configuration. Make sure to call this before initiating Bind to this
237     // ImsService.
setFeatureConfig(ImsFeatureConfiguration f)238     public void setFeatureConfig(ImsFeatureConfiguration f) {
239         synchronized (mLock) {
240             mFeatureConfig = f;
241         }
242     }
243 
getFeatureConfig()244     public ImsFeatureConfiguration getFeatureConfig() {
245         synchronized (mLock) {
246             return mFeatureConfig;
247         }
248     }
249 
isEnabled()250     public boolean isEnabled() {
251         synchronized (mLock) {
252             return mIsEnabled;
253         }
254     }
255 
setIsEnabled(boolean isEnabled)256     public void setIsEnabled(boolean isEnabled) {
257         synchronized (mLock) {
258             mIsEnabled = isEnabled;
259         }
260     }
261 
waitForLatchCountdown(int latchIndex)262     public boolean waitForLatchCountdown(int latchIndex) {
263         boolean complete = false;
264         try {
265             CountDownLatch latch;
266             synchronized (mLock) {
267                 latch = sLatches[latchIndex];
268             }
269             complete = latch.await(ImsUtils.TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
270         } catch (InterruptedException e) {
271             // complete == false
272         }
273         synchronized (mLock) {
274             sLatches[latchIndex] = new CountDownLatch(1);
275         }
276         return complete;
277     }
278 
countDownLatch(int latchIndex)279     public void countDownLatch(int latchIndex) {
280         synchronized (mLock) {
281             sLatches[latchIndex].countDown();
282         }
283     }
284 
getMmTelFeature()285     public TestMmTelFeature getMmTelFeature() {
286         synchronized (mLock) {
287             return mTestMmTelFeature;
288         }
289     }
290 
getRcsFeature()291     public TestRcsFeature getRcsFeature() {
292         synchronized (mLock) {
293             return mTestRcsFeature;
294         }
295     }
296 
getImsRegistration()297     public ImsRegistrationImplBase getImsRegistration() {
298         synchronized (mLock) {
299             return sImsRegistrationImplBase;
300         }
301     }
302 
getConfig()303     public ImsConfigImplBase getConfig() {
304         return mTestImsConfig;
305     }
306 }
307