1 /* 2 * Copyright (C) 2017 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.stub; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.SystemApi; 23 import android.os.Bundle; 24 import android.os.RemoteException; 25 import android.telephony.ims.ImsUtListener; 26 import android.util.Log; 27 28 import com.android.ims.internal.IImsUt; 29 import com.android.ims.internal.IImsUtListener; 30 import com.android.internal.telephony.util.TelephonyUtils; 31 32 import java.lang.annotation.Retention; 33 import java.lang.annotation.RetentionPolicy; 34 import java.util.Objects; 35 import java.util.concurrent.CancellationException; 36 import java.util.concurrent.CompletableFuture; 37 import java.util.concurrent.CompletionException; 38 import java.util.concurrent.ExecutionException; 39 import java.util.concurrent.Executor; 40 import java.util.function.Supplier; 41 42 /** 43 * Base implementation of IMS UT interface, which implements stubs. Override these methods to 44 * implement functionality. 45 * 46 * @hide 47 */ 48 // DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you 49 // will break other implementations of ImsUt maintained by other ImsServices. 50 @SystemApi 51 public class ImsUtImplBase { 52 private static final String TAG = "ImsUtImplBase"; 53 /** 54 * Bar all incoming calls. (See 3GPP TS 24.611) 55 * @hide 56 */ 57 public static final int CALL_BARRING_ALL_INCOMING = 1; 58 59 /** 60 * Bar all outgoing calls. (See 3GPP TS 24.611) 61 * @hide 62 */ 63 public static final int CALL_BARRING_ALL_OUTGOING = 2; 64 65 /** 66 * Bar all outgoing international calls. (See 3GPP TS 24.611) 67 * @hide 68 */ 69 public static final int CALL_BARRING_OUTGOING_INTL = 3; 70 71 /** 72 * Bar all outgoing international calls, excluding those to the home PLMN country 73 * (See 3GPP TS 24.611) 74 * @hide 75 */ 76 public static final int CALL_BARRING_OUTGOING_INTL_EXCL_HOME = 4; 77 78 /** 79 * Bar all incoming calls when roaming (See 3GPP TS 24.611) 80 * @hide 81 */ 82 public static final int CALL_BLOCKING_INCOMING_WHEN_ROAMING = 5; 83 84 /** 85 * Enable Anonymous Communication Rejection (See 3GPP TS 24.611) 86 * @hide 87 */ 88 public static final int CALL_BARRING_ANONYMOUS_INCOMING = 6; 89 90 /** 91 * Bar all incoming and outgoing calls. (See 3GPP TS 24.611) 92 * @hide 93 */ 94 public static final int CALL_BARRING_ALL = 7; 95 96 /** 97 * Bar all outgoing service requests, including calls. (See 3GPP TS 24.611) 98 * @hide 99 */ 100 public static final int CALL_BARRING_OUTGOING_ALL_SERVICES = 8; 101 102 /** 103 * Bar all incoming service requests, including calls. (See 3GPP TS 24.611) 104 * @hide 105 */ 106 public static final int CALL_BARRING_INCOMING_ALL_SERVICES = 9; 107 108 /** 109 * Bar specific incoming calls. (See 3GPP TS 24.611) 110 * @hide 111 */ 112 public static final int CALL_BARRING_SPECIFIC_INCOMING_CALLS = 10; 113 114 /** @hide */ 115 @Retention(RetentionPolicy.SOURCE) 116 @IntDef(prefix = "CALL_BARRING_", value = {CALL_BARRING_ALL_INCOMING, CALL_BARRING_ALL_OUTGOING, 117 CALL_BARRING_OUTGOING_INTL, CALL_BARRING_OUTGOING_INTL_EXCL_HOME, 118 CALL_BLOCKING_INCOMING_WHEN_ROAMING, CALL_BARRING_ANONYMOUS_INCOMING, 119 CALL_BARRING_ALL, CALL_BARRING_OUTGOING_ALL_SERVICES, 120 CALL_BARRING_INCOMING_ALL_SERVICES, CALL_BARRING_SPECIFIC_INCOMING_CALLS}) 121 public @interface CallBarringMode {} 122 123 /** 124 * Constant used to denote an invalid return value. 125 * @hide 126 */ 127 public static final int INVALID_RESULT = -1; 128 129 private Executor mExecutor = Runnable::run; 130 131 private final IImsUt.Stub mServiceImpl = new IImsUt.Stub() { 132 private final Object mLock = new Object(); 133 private ImsUtListener mUtListener; 134 135 @Override 136 public void close() throws RemoteException { 137 executeMethodAsync(() ->ImsUtImplBase.this.close(), "close"); 138 } 139 140 @Override 141 public int queryCallBarring(int cbType) throws RemoteException { 142 return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCallBarring(cbType), 143 "queryCallBarring"); 144 } 145 146 @Override 147 public int queryCallForward(int condition, String number) throws RemoteException { 148 return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCallForward( 149 condition, number), "queryCallForward"); 150 } 151 152 @Override 153 public int queryCallWaiting() throws RemoteException { 154 return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCallWaiting(), 155 "queryCallWaiting"); 156 } 157 158 @Override 159 public int queryCLIR() throws RemoteException { 160 return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCLIR(), "queryCLIR"); 161 } 162 163 @Override 164 public int queryCLIP() throws RemoteException { 165 return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCLIP(), "queryCLIP"); 166 } 167 168 @Override 169 public int queryCOLR() throws RemoteException { 170 return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCOLR(), "queryCOLR"); 171 } 172 173 @Override 174 public int queryCOLP() throws RemoteException { 175 return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCOLP(), "queryCOLP"); 176 } 177 178 @Override 179 public int transact(Bundle ssInfo) throws RemoteException { 180 return executeMethodAsyncForResult(() -> ImsUtImplBase.this.transact(ssInfo), 181 "transact"); 182 } 183 184 @Override 185 public int updateCallBarring(int cbType, int action, String[] barrList) throws 186 RemoteException { 187 return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCallBarring( 188 cbType, action, barrList), "updateCallBarring"); 189 } 190 191 @Override 192 public int updateCallForward(int action, int condition, String number, int serviceClass, 193 int timeSeconds) throws RemoteException { 194 return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCallForward( 195 action, condition, number, serviceClass, timeSeconds), "updateCallForward"); 196 } 197 198 @Override 199 public int updateCallWaiting(boolean enable, int serviceClass) throws RemoteException { 200 return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCallWaiting( 201 enable, serviceClass), "updateCallWaiting"); 202 } 203 204 @Override 205 public int updateCLIR(int clirMode) throws RemoteException { 206 return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCLIR(clirMode), 207 "updateCLIR"); 208 } 209 210 @Override 211 public int updateCLIP(boolean enable) throws RemoteException { 212 return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCLIP(enable), 213 "updateCLIP"); 214 } 215 216 @Override 217 public int updateCOLR(int presentation) throws RemoteException { 218 return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCOLR(presentation), 219 "updateCOLR"); 220 } 221 222 @Override 223 public int updateCOLP(boolean enable) throws RemoteException { 224 return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCOLP(enable), 225 "updateCOLP"); 226 } 227 228 @Override 229 public void setListener(IImsUtListener listener) throws RemoteException { 230 executeMethodAsync(() -> { 231 if (mUtListener != null 232 && !mUtListener.getListenerInterface().asBinder().isBinderAlive()) { 233 Log.w(TAG, "setListener: discarding dead Binder"); 234 mUtListener = null; 235 } 236 if (mUtListener != null && listener != null && Objects.equals( 237 mUtListener.getListenerInterface().asBinder(), listener.asBinder())) { 238 return; 239 } 240 241 if (listener == null) { 242 mUtListener = null; 243 } else if (listener != null && mUtListener == null) { 244 mUtListener = new ImsUtListener(listener); 245 } else { 246 // Warn that the listener is being replaced while active 247 Log.w(TAG, "setListener is being called when there is already an active " 248 + "listener"); 249 mUtListener = new ImsUtListener(listener); 250 } 251 252 ImsUtImplBase.this.setListener(mUtListener); 253 }, "setListener"); 254 } 255 256 @Override 257 public int queryCallBarringForServiceClass(int cbType, int serviceClass) 258 throws RemoteException { 259 return executeMethodAsyncForResult(() -> ImsUtImplBase.this 260 .queryCallBarringForServiceClass(cbType, serviceClass), 261 "queryCallBarringForServiceClass"); 262 } 263 264 @Override 265 public int updateCallBarringForServiceClass(int cbType, int action, 266 String[] barrList, int serviceClass) throws RemoteException { 267 return executeMethodAsyncForResult(() -> ImsUtImplBase.this 268 .updateCallBarringForServiceClass(cbType, action, barrList, serviceClass), 269 "updateCallBarringForServiceClass"); 270 } 271 272 @Override 273 public int updateCallBarringWithPassword(int cbType, int action, String[] barrList, 274 int serviceClass, String password) throws RemoteException { 275 return executeMethodAsyncForResult(() -> ImsUtImplBase.this 276 .updateCallBarringWithPassword(cbType, action, barrList, serviceClass, 277 password), "updateCallBarringWithPassword"); 278 } 279 280 // Call the methods with a clean calling identity on the executor and wait indefinitely for 281 // the future to return. 282 private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException { 283 try { 284 CompletableFuture.runAsync( 285 () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join(); 286 } catch (CancellationException | CompletionException e) { 287 Log.w(TAG, "ImsUtImplBase Binder - " + errorLogName + " exception: " 288 + e.getMessage()); 289 throw new RemoteException(e.getMessage()); 290 } 291 } 292 293 private <T> T executeMethodAsyncForResult(Supplier<T> r, 294 String errorLogName) throws RemoteException { 295 CompletableFuture<T> future = CompletableFuture.supplyAsync( 296 () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor); 297 try { 298 return future.get(); 299 } catch (ExecutionException | InterruptedException e) { 300 Log.w(TAG, "ImsUtImplBase Binder - " + errorLogName + " exception: " 301 + e.getMessage()); 302 throw new RemoteException(e.getMessage()); 303 } 304 } 305 }; 306 307 /** 308 * Called when the framework no longer needs to interact with the IMS UT implementation any 309 * longer. 310 */ close()311 public void close() { 312 313 } 314 315 /** 316 * Retrieves the call barring configuration. 317 * @param cbType 318 */ queryCallBarring(int cbType)319 public int queryCallBarring(int cbType) { 320 return -1; 321 } 322 323 /** 324 * Retrieves the configuration of the call barring for specified service class. 325 */ queryCallBarringForServiceClass(int cbType, int serviceClass)326 public int queryCallBarringForServiceClass(int cbType, int serviceClass) { 327 return -1; 328 } 329 330 /** 331 * Retrieves the configuration of the call forward. 332 */ queryCallForward(int condition, String number)333 public int queryCallForward(int condition, String number) { 334 return -1; 335 } 336 337 /** 338 * Retrieves the configuration of the call waiting. 339 */ queryCallWaiting()340 public int queryCallWaiting() { 341 return -1; 342 } 343 344 /** 345 * Retrieves the default CLIR setting. 346 * @hide 347 */ queryCLIR()348 public int queryCLIR() { 349 return queryClir(); 350 } 351 352 /** 353 * Retrieves the CLIP call setting. 354 * @hide 355 */ queryCLIP()356 public int queryCLIP() { 357 return queryClip(); 358 } 359 360 /** 361 * Retrieves the COLR call setting. 362 * @hide 363 */ queryCOLR()364 public int queryCOLR() { 365 return queryColr(); 366 } 367 368 /** 369 * Retrieves the COLP call setting. 370 * @hide 371 */ queryCOLP()372 public int queryCOLP() { 373 return queryColp(); 374 } 375 376 /** 377 * Retrieves the default CLIR setting. 378 */ queryClir()379 public int queryClir() { 380 return -1; 381 } 382 383 /** 384 * Retrieves the CLIP call setting. 385 */ queryClip()386 public int queryClip() { 387 return -1; 388 } 389 390 /** 391 * Retrieves the COLR call setting. 392 */ queryColr()393 public int queryColr() { 394 return -1; 395 } 396 397 /** 398 * Retrieves the COLP call setting. 399 */ queryColp()400 public int queryColp() { 401 return -1; 402 } 403 404 /** 405 * Updates or retrieves the supplementary service configuration. 406 */ transact(Bundle ssInfo)407 public int transact(Bundle ssInfo) { 408 return -1; 409 } 410 411 /** 412 * Updates the configuration of the call barring. 413 */ updateCallBarring(@allBarringMode int cbType, int action, String[] barrList)414 public int updateCallBarring(@CallBarringMode int cbType, int action, String[] barrList) { 415 return -1; 416 } 417 418 /** 419 * Updates the configuration of the call barring for specified service class. 420 */ updateCallBarringForServiceClass(@allBarringMode int cbType, int action, String[] barrList, int serviceClass)421 public int updateCallBarringForServiceClass(@CallBarringMode int cbType, int action, 422 String[] barrList, int serviceClass) { 423 return -1; 424 } 425 426 /** 427 * Updates the configuration of the call barring for specified service class with password. 428 * @hide 429 */ updateCallBarringWithPassword(int cbType, int action, @Nullable String[] barrList, int serviceClass, @NonNull String password)430 public int updateCallBarringWithPassword(int cbType, int action, @Nullable String[] barrList, 431 int serviceClass, @NonNull String password) { 432 return -1; 433 } 434 435 /** 436 * Updates the configuration of the call forward. 437 */ updateCallForward(int action, int condition, String number, int serviceClass, int timeSeconds)438 public int updateCallForward(int action, int condition, String number, int serviceClass, 439 int timeSeconds) { 440 return 0; 441 } 442 443 /** 444 * Updates the configuration of the call waiting. 445 */ updateCallWaiting(boolean enable, int serviceClass)446 public int updateCallWaiting(boolean enable, int serviceClass) { 447 return -1; 448 } 449 450 /** 451 * Updates the configuration of the CLIR supplementary service. 452 * @hide 453 */ updateCLIR(int clirMode)454 public int updateCLIR(int clirMode) { 455 return updateClir(clirMode); 456 } 457 458 /** 459 * Updates the configuration of the CLIP supplementary service. 460 * @hide 461 */ updateCLIP(boolean enable)462 public int updateCLIP(boolean enable) { 463 return updateClip(enable); 464 } 465 466 /** 467 * Updates the configuration of the COLR supplementary service. 468 * @hide 469 */ updateCOLR(int presentation)470 public int updateCOLR(int presentation) { 471 return updateColr(presentation); 472 } 473 474 /** 475 * Updates the configuration of the COLP supplementary service. 476 * @hide 477 */ updateCOLP(boolean enable)478 public int updateCOLP(boolean enable) { 479 return updateColp(enable); 480 } 481 482 /** 483 * Updates the configuration of the CLIR supplementary service. 484 */ updateClir(int clirMode)485 public int updateClir(int clirMode) { 486 return -1; 487 } 488 489 /** 490 * Updates the configuration of the CLIP supplementary service. 491 */ updateClip(boolean enable)492 public int updateClip(boolean enable) { 493 return -1; 494 } 495 496 /** 497 * Updates the configuration of the COLR supplementary service. 498 */ updateColr(int presentation)499 public int updateColr(int presentation) { 500 return -1; 501 } 502 503 /** 504 * Updates the configuration of the COLP supplementary service. 505 */ updateColp(boolean enable)506 public int updateColp(boolean enable) { 507 return -1; 508 } 509 510 /** 511 * Sets the listener. 512 */ setListener(ImsUtListener listener)513 public void setListener(ImsUtListener listener) { 514 } 515 516 /** 517 * @hide 518 */ getInterface()519 public IImsUt getInterface() { 520 return mServiceImpl; 521 } 522 523 /** 524 * Set default Executor from MmTelFeature. 525 * @param executor The default executor for the framework to use when executing the methods 526 * overridden by the implementation of ImsUT. 527 * @hide 528 */ setDefaultExecutor(@onNull Executor executor)529 public final void setDefaultExecutor(@NonNull Executor executor) { 530 mExecutor = executor; 531 } 532 } 533