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.telephony.ims.stub.SipTransportImplBase; 31 import android.util.Log; 32 33 34 import androidx.annotation.Nullable; 35 36 import java.util.concurrent.CountDownLatch; 37 import java.util.concurrent.TimeUnit; 38 39 /** 40 * A Test ImsService that will verify ImsService functionality. 41 */ 42 public class TestImsService extends Service { 43 44 private static final String TAG = "GtsImsTestImsService"; 45 46 private static final TestImsRegistration sImsRegistrationImplBase = 47 new TestImsRegistration(); 48 49 private TestRcsFeature mTestRcsFeature; 50 private TestMmTelFeature mTestMmTelFeature; 51 private TestImsConfig mTestImsConfig; 52 private TestSipTransport mTestSipTransport; 53 private ImsService mTestImsService; 54 private boolean mIsEnabled = false; 55 private boolean mSetNullRcsBinding = false; 56 private boolean mIsSipTransportImplemented = false; 57 private long mCapabilities = 0; 58 private ImsFeatureConfiguration mFeatureConfig; 59 private final Object mLock = new Object(); 60 61 public static final int LATCH_FEATURES_READY = 0; 62 public static final int LATCH_ENABLE_IMS = 1; 63 public static final int LATCH_DISABLE_IMS = 2; 64 public static final int LATCH_CREATE_MMTEL = 3; 65 public static final int LATCH_CREATE_RCS = 4; 66 public static final int LATCH_REMOVE_MMTEL = 5; 67 public static final int LATCH_REMOVE_RCS = 6; 68 public static final int LATCH_MMTEL_READY = 7; 69 public static final int LATCH_RCS_READY = 8; 70 public static final int LATCH_MMTEL_CAP_SET = 9; 71 public static final int LATCH_RCS_CAP_SET = 10; 72 public static final int LATCH_UCE_LISTENER_SET = 11; 73 public static final int LATCH_UCE_REQUEST_PUBLISH = 12; 74 private static final int LATCH_MAX = 13; 75 protected static final CountDownLatch[] sLatches = new CountDownLatch[LATCH_MAX]; 76 static { 77 for (int i = 0; i < LATCH_MAX; i++) { 78 sLatches[i] = new CountDownLatch(1); 79 } 80 } 81 82 interface RemovedListener { onRemoved()83 void onRemoved(); 84 } 85 interface ReadyListener { onReady()86 void onReady(); 87 } 88 interface CapabilitiesSetListener { onSet()89 void onSet(); 90 } 91 interface RcsCapabilityExchangeEventListener { onSet()92 void onSet(); 93 } 94 interface DeviceCapPublishListener { onPublish()95 void onPublish(); 96 } 97 98 // This is defined here instead TestImsService extending ImsService directly because the GTS 99 // tests were failing to run on pre-P devices. Not sure why, but TestImsService is loaded 100 // even if it isn't used. 101 private class ImsServiceUT extends ImsService { 102 ImsServiceUT(Context context)103 ImsServiceUT(Context context) { 104 // As explained above, ImsServiceUT is created in order to get around classloader 105 // restrictions. Attach the base context from the wrapper ImsService. 106 if (getBaseContext() == null) { 107 attachBaseContext(context); 108 } 109 mTestImsConfig = new TestImsConfig(); 110 // For testing, just run on binder thread until required otherwise. 111 mTestSipTransport = new TestSipTransport(Runnable::run); 112 } 113 114 @Override querySupportedImsFeatures()115 public ImsFeatureConfiguration querySupportedImsFeatures() { 116 return getFeatureConfig(); 117 } 118 119 @Override getImsServiceCapabilities()120 public long getImsServiceCapabilities() { 121 return mCapabilities; 122 } 123 124 @Override readyForFeatureCreation()125 public void readyForFeatureCreation() { 126 synchronized (mLock) { 127 countDownLatch(LATCH_FEATURES_READY); 128 } 129 } 130 131 @Override enableIms(int slotId)132 public void enableIms(int slotId) { 133 synchronized (mLock) { 134 countDownLatch(LATCH_ENABLE_IMS); 135 setIsEnabled(true); 136 } 137 } 138 139 @Override disableIms(int slotId)140 public void disableIms(int slotId) { 141 synchronized (mLock) { 142 countDownLatch(LATCH_DISABLE_IMS); 143 setIsEnabled(false); 144 } 145 } 146 147 @Override createRcsFeature(int slotId)148 public RcsFeature createRcsFeature(int slotId) { 149 synchronized (mLock) { 150 countDownLatch(LATCH_CREATE_RCS); 151 mTestRcsFeature = new TestRcsFeature(getBaseContext(), 152 //onReady 153 () -> { 154 synchronized (mLock) { 155 countDownLatch(LATCH_RCS_READY); 156 } 157 }, 158 //onRemoved 159 () -> { 160 synchronized (mLock) { 161 countDownLatch(LATCH_REMOVE_RCS); 162 mTestRcsFeature = null; 163 } 164 }, 165 //onCapabilitiesSet 166 () -> { 167 synchronized (mLock) { 168 countDownLatch(LATCH_RCS_CAP_SET); 169 } 170 }, 171 () -> { 172 synchronized (mLock) { 173 countDownLatch(LATCH_UCE_LISTENER_SET); 174 } 175 }); 176 177 // Setup UCE request listener 178 mTestRcsFeature.setDeviceCapPublishListener(() -> { 179 synchronized (mLock) { 180 countDownLatch(LATCH_UCE_REQUEST_PUBLISH); 181 } 182 }); 183 184 if (mSetNullRcsBinding) { 185 return null; 186 } 187 return mTestRcsFeature; 188 } 189 } 190 191 @Override getConfig(int slotId)192 public ImsConfigImplBase getConfig(int slotId) { 193 return mTestImsConfig; 194 } 195 196 @Override createMmTelFeature(int slotId)197 public MmTelFeature createMmTelFeature(int slotId) { 198 synchronized (mLock) { 199 countDownLatch(LATCH_CREATE_MMTEL); 200 mTestMmTelFeature = new TestMmTelFeature( 201 //onReady 202 () -> { 203 synchronized (mLock) { 204 countDownLatch(LATCH_MMTEL_READY); 205 } 206 }, 207 //onRemoved 208 () -> { 209 synchronized (mLock) { 210 countDownLatch(LATCH_REMOVE_MMTEL); 211 mTestMmTelFeature = null; 212 } 213 }, 214 //onCapabilitiesSet 215 () -> { 216 synchronized (mLock) { 217 countDownLatch(LATCH_MMTEL_CAP_SET); 218 } 219 } 220 ); 221 return mTestMmTelFeature; 222 } 223 } 224 225 @Override getRegistration(int slotId)226 public ImsRegistrationImplBase getRegistration(int slotId) { 227 return sImsRegistrationImplBase; 228 } 229 230 @Nullable 231 @Override getSipTransport(int slotId)232 public SipTransportImplBase getSipTransport(int slotId) { 233 if (mIsSipTransportImplemented) { 234 return mTestSipTransport; 235 } else { 236 return null; 237 } 238 } 239 } 240 241 private final LocalBinder mBinder = new LocalBinder(); 242 // For local access of this Service. 243 class LocalBinder extends Binder { getService()244 TestImsService getService() { 245 return TestImsService.this; 246 } 247 } 248 getImsService()249 protected ImsService getImsService() { 250 synchronized (mLock) { 251 if (mTestImsService != null) { 252 return mTestImsService; 253 } 254 mTestImsService = new ImsServiceUT(this); 255 return mTestImsService; 256 } 257 } 258 259 @Override onBind(Intent intent)260 public IBinder onBind(Intent intent) { 261 if ("android.telephony.ims.ImsService".equals(intent.getAction())) { 262 if (ImsUtils.VDBG) { 263 Log.d(TAG, "onBind-Remote"); 264 } 265 return getImsService().onBind(intent); 266 } 267 if (ImsUtils.VDBG) { 268 Log.i(TAG, "onBind-Local"); 269 } 270 return mBinder; 271 } 272 resetState()273 public void resetState() { 274 synchronized (mLock) { 275 mTestMmTelFeature = null; 276 mTestRcsFeature = null; 277 mIsEnabled = false; 278 mSetNullRcsBinding = false; 279 mIsSipTransportImplemented = false; 280 mCapabilities = 0; 281 for (int i = 0; i < LATCH_MAX; i++) { 282 sLatches[i] = new CountDownLatch(1); 283 } 284 } 285 } 286 287 // Sets the feature configuration. Make sure to call this before initiating Bind to this 288 // ImsService. setFeatureConfig(ImsFeatureConfiguration f)289 public void setFeatureConfig(ImsFeatureConfiguration f) { 290 synchronized (mLock) { 291 mFeatureConfig = f; 292 } 293 } 294 getFeatureConfig()295 public ImsFeatureConfiguration getFeatureConfig() { 296 synchronized (mLock) { 297 return mFeatureConfig; 298 } 299 } 300 isEnabled()301 public boolean isEnabled() { 302 synchronized (mLock) { 303 return mIsEnabled; 304 } 305 } 306 setNullRcsBinding()307 public void setNullRcsBinding() { 308 synchronized (mLock) { 309 mSetNullRcsBinding = true; 310 } 311 } 312 setIsEnabled(boolean isEnabled)313 public void setIsEnabled(boolean isEnabled) { 314 synchronized (mLock) { 315 mIsEnabled = isEnabled; 316 } 317 } 318 addCapabilities(long capabilities)319 public void addCapabilities(long capabilities) { 320 synchronized (mLock) { 321 mCapabilities |= capabilities; 322 } 323 } 324 setSipTransportImplemented()325 public void setSipTransportImplemented() { 326 synchronized (mLock) { 327 mIsSipTransportImplemented = true; 328 } 329 } 330 waitForLatchCountdown(int latchIndex)331 public boolean waitForLatchCountdown(int latchIndex) { 332 boolean complete = false; 333 try { 334 CountDownLatch latch; 335 synchronized (mLock) { 336 latch = sLatches[latchIndex]; 337 } 338 complete = latch.await(ImsUtils.TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS); 339 } catch (InterruptedException e) { 340 // complete == false 341 } 342 synchronized (mLock) { 343 sLatches[latchIndex] = new CountDownLatch(1); 344 } 345 return complete; 346 } 347 waitForLatchCountdown(int latchIndex, long waitMs)348 public boolean waitForLatchCountdown(int latchIndex, long waitMs) { 349 boolean complete = false; 350 try { 351 CountDownLatch latch; 352 synchronized (mLock) { 353 latch = sLatches[latchIndex]; 354 } 355 complete = latch.await(waitMs, TimeUnit.MILLISECONDS); 356 } catch (InterruptedException e) { 357 // complete == false 358 } 359 synchronized (mLock) { 360 sLatches[latchIndex] = new CountDownLatch(1); 361 } 362 return complete; 363 } 364 countDownLatch(int latchIndex)365 public void countDownLatch(int latchIndex) { 366 synchronized (mLock) { 367 sLatches[latchIndex].countDown(); 368 } 369 } 370 getMmTelFeature()371 public TestMmTelFeature getMmTelFeature() { 372 synchronized (mLock) { 373 return mTestMmTelFeature; 374 } 375 } 376 getRcsFeature()377 public TestRcsFeature getRcsFeature() { 378 synchronized (mLock) { 379 return mTestRcsFeature; 380 } 381 } 382 getSipTransport()383 public TestSipTransport getSipTransport() { 384 synchronized (mLock) { 385 return mTestSipTransport; 386 } 387 } 388 getImsRegistration()389 public TestImsRegistration getImsRegistration() { 390 synchronized (mLock) { 391 return sImsRegistrationImplBase; 392 } 393 } 394 getConfig()395 public ImsConfigImplBase getConfig() { 396 return mTestImsConfig; 397 } 398 } 399