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