1 /*
2  * Copyright (C) 2020 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;
18 
19 import android.Manifest;
20 import android.annotation.IntDef;
21 import android.annotation.IntRange;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.annotation.RequiresFeature;
25 import android.annotation.RequiresPermission;
26 import android.annotation.SystemApi;
27 import android.content.Context;
28 import android.content.pm.PackageManager;
29 import android.os.RemoteException;
30 import android.os.ServiceSpecificException;
31 import android.telephony.BinderCacheManager;
32 import android.telephony.ims.aidl.IImsRcsController;
33 import android.telephony.ims.aidl.SipDelegateConnectionAidlWrapper;
34 import android.telephony.ims.feature.ImsFeature;
35 import android.telephony.ims.stub.DelegateConnectionMessageCallback;
36 import android.telephony.ims.stub.DelegateConnectionStateCallback;
37 import android.telephony.ims.stub.SipDelegate;
38 import android.util.ArrayMap;
39 
40 import com.android.internal.annotations.VisibleForTesting;
41 import com.android.internal.telephony.ITelephony;
42 
43 import java.lang.annotation.Retention;
44 import java.lang.annotation.RetentionPolicy;
45 import java.util.Objects;
46 import java.util.concurrent.Executor;
47 
48 /**
49  * Manages the creation and destruction of SipDelegates for the {@link ImsService} managing IMS
50  * for the subscription ID that this SipDelegateManager has been created for.
51  *
52  * This allows multiple IMS applications to forward SIP messages to/from their application for the
53  * purposes of providing a single IMS registration to the carrier's IMS network from potentially
54  * many IMS stacks implementing a subset of the supported MMTEL/RCS features.
55  * <p>
56  * This API is only supported if the device supports the
57  * {@link PackageManager#FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION} feature.
58  * @hide
59  */
60 @SystemApi
61 @RequiresFeature(PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION)
62 public class SipDelegateManager {
63 
64     /**
65      * The SIP message has failed being sent or received for an unknown reason.
66      * <p>
67      * The caller should retry a message that failed with this response.
68      */
69     public static final int MESSAGE_FAILURE_REASON_UNKNOWN = 0;
70 
71     /**
72      * The remote service associated with this connection has died and the message was not
73      * properly sent/received.
74      * <p>
75      * This is considered a permanent error and the system will automatically begin the teardown and
76      * destruction of the SipDelegate. No further messages should be sent on this transport.
77      */
78     public static final int MESSAGE_FAILURE_REASON_DELEGATE_DEAD = 1;
79 
80     /**
81      * The message has not been sent/received because the delegate is in the process of closing and
82      * has become unavailable. No further messages should be sent/received on this delegate.
83      */
84     public static final int MESSAGE_FAILURE_REASON_DELEGATE_CLOSED = 2;
85 
86     /**
87      * The SIP message has an invalid start line and the message can not be sent or the start line
88      * failed validation due to the request containing a restricted SIP request method.
89      * {@link SipDelegateConnection}s can not send SIP requests for the methods: REGISTER, PUBLISH,
90      * or OPTIONS.
91      */
92     public static final int MESSAGE_FAILURE_REASON_INVALID_START_LINE = 3;
93 
94     /**
95      * One or more of the header fields in the header section of the outgoing SIP message is invalid
96      * or contains a restricted header value and the SIP message can not be sent.
97      * {@link SipDelegateConnection}s can not send SIP SUBSCRIBE requests for the "Event" header
98      * value of "presence".
99      */
100     public static final int MESSAGE_FAILURE_REASON_INVALID_HEADER_FIELDS = 4;
101 
102     /**
103      * The body content of the SIP message is invalid and the message can not be sent.
104      */
105     public static final int MESSAGE_FAILURE_REASON_INVALID_BODY_CONTENT = 5;
106 
107     /**
108      * The feature tag associated with the outgoing message does not match any known feature tags
109      * or it matches a denied tag and this message can not be sent.
110      */
111     public static final int MESSAGE_FAILURE_REASON_INVALID_FEATURE_TAG = 6;
112 
113     /**
114      * The feature tag associated with the outgoing message is not enabled for the associated
115      * SipDelegateConnection and can not be sent.
116      */
117     public static final int MESSAGE_FAILURE_REASON_TAG_NOT_ENABLED_FOR_DELEGATE = 7;
118 
119     /**
120      * The link to the network has been lost and the outgoing message has failed to send.
121      * <p>
122      * This message should be retried when connectivity to the network is re-established. See
123      * {@link android.net.ConnectivityManager.NetworkCallback} for how this can be determined.
124      */
125     public static final int MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE = 8;
126 
127     /**
128      * The outgoing SIP message has not been sent due to the SipDelegate not being registered for
129      * IMS at this time.
130      * <p>
131      * This is considered a temporary failure, the message should not be retried until an IMS
132      * registration change callback is received via
133      * {@link DelegateConnectionStateCallback#onFeatureTagStatusChanged}
134      */
135     public static final int MESSAGE_FAILURE_REASON_NOT_REGISTERED = 9;
136 
137     /**
138      * The outgoing SIP message has not been sent because the {@link SipDelegateConfiguration}
139      * version associated with the outgoing {@link SipMessage} is now stale and has failed
140      * validation checks.
141      * <p>
142      * The @link SipMessage} should be recreated using the newest
143      * {@link SipDelegateConfiguration} and sent again.
144      */
145     public static final int MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION = 10;
146 
147     /**
148      * The outgoing SIP message has not been sent because the internal state of the associated
149      * {@link SipDelegate} is changing and has temporarily brought the transport down.
150      * <p>
151      * This is considered a temporary error and the {@link SipDelegateConnection} should resend the
152      * message once {@link DelegateRegistrationState#DEREGISTERING_REASON_FEATURE_TAGS_CHANGING} is
153      * no longer reported.
154      */
155     public static final int MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION = 11;
156 
157     /** @hide */
158     @Retention(RetentionPolicy.SOURCE)
159     @IntDef(prefix = "MESSAGE_FAILURE_REASON_", value = {
160             MESSAGE_FAILURE_REASON_UNKNOWN,
161             MESSAGE_FAILURE_REASON_DELEGATE_DEAD,
162             MESSAGE_FAILURE_REASON_DELEGATE_CLOSED,
163             MESSAGE_FAILURE_REASON_INVALID_START_LINE,
164             MESSAGE_FAILURE_REASON_INVALID_HEADER_FIELDS,
165             MESSAGE_FAILURE_REASON_INVALID_BODY_CONTENT,
166             MESSAGE_FAILURE_REASON_INVALID_FEATURE_TAG,
167             MESSAGE_FAILURE_REASON_TAG_NOT_ENABLED_FOR_DELEGATE,
168             MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE,
169             MESSAGE_FAILURE_REASON_NOT_REGISTERED,
170             MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION,
171             MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION
172     })
173     public @interface MessageFailureReason {}
174 
175     /**@hide*/
176     public static final ArrayMap<Integer, String> MESSAGE_FAILURE_REASON_STRING_MAP =
177             new ArrayMap<>(11);
178     static {
MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_UNKNOWN, "MESSAGE_FAILURE_REASON_UNKNOWN")179         MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_UNKNOWN,
180                 "MESSAGE_FAILURE_REASON_UNKNOWN");
MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_DELEGATE_DEAD, "MESSAGE_FAILURE_REASON_DELEGATE_DEAD")181         MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_DELEGATE_DEAD,
182                 "MESSAGE_FAILURE_REASON_DELEGATE_DEAD");
MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_DELEGATE_CLOSED, "MESSAGE_FAILURE_REASON_DELEGATE_CLOSED")183         MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_DELEGATE_CLOSED,
184                 "MESSAGE_FAILURE_REASON_DELEGATE_CLOSED");
MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_INVALID_HEADER_FIELDS, "MESSAGE_FAILURE_REASON_INVALID_HEADER_FIELDS")185         MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_INVALID_HEADER_FIELDS,
186                 "MESSAGE_FAILURE_REASON_INVALID_HEADER_FIELDS");
MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_INVALID_BODY_CONTENT, "MESSAGE_FAILURE_REASON_INVALID_BODY_CONTENT")187         MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_INVALID_BODY_CONTENT,
188                 "MESSAGE_FAILURE_REASON_INVALID_BODY_CONTENT");
MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_INVALID_FEATURE_TAG, "MESSAGE_FAILURE_REASON_INVALID_FEATURE_TAG")189         MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_INVALID_FEATURE_TAG,
190                 "MESSAGE_FAILURE_REASON_INVALID_FEATURE_TAG");
MESSAGE_FAILURE_REASON_STRING_MAP.append( MESSAGE_FAILURE_REASON_TAG_NOT_ENABLED_FOR_DELEGATE, "MESSAGE_FAILURE_REASON_TAG_NOT_ENABLED_FOR_DELEGATE")191         MESSAGE_FAILURE_REASON_STRING_MAP.append(
192                 MESSAGE_FAILURE_REASON_TAG_NOT_ENABLED_FOR_DELEGATE,
193                 "MESSAGE_FAILURE_REASON_TAG_NOT_ENABLED_FOR_DELEGATE");
MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE, "MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE")194         MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE,
195                 "MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE");
MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_NOT_REGISTERED, "MESSAGE_FAILURE_REASON_NOT_REGISTERED")196         MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_NOT_REGISTERED,
197                 "MESSAGE_FAILURE_REASON_NOT_REGISTERED");
MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION, "MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION")198         MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION,
199                 "MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION");
MESSAGE_FAILURE_REASON_STRING_MAP.append( MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION, "MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION")200         MESSAGE_FAILURE_REASON_STRING_MAP.append(
201                 MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION,
202                 "MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION");
203     }
204 
205     /**
206      * Access to use this feature tag has been denied for an unknown reason.
207      */
208     public static final int DENIED_REASON_UNKNOWN = 0;
209 
210     /**
211      * This feature tag is allowed to be used by this SipDelegateConnection, but it is in use by
212      * another SipDelegateConnection and can not be associated with this delegate. The feature tag
213      * will stay in this state until the feature tag is release by the other application.
214      */
215     public static final int DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE = 1;
216 
217     /**
218      * Access to use this feature tag has been denied because this application does not have the
219      * permissions required to access this feature tag.
220      */
221     public static final int DENIED_REASON_NOT_ALLOWED = 2;
222 
223     /**
224      * Access to use this feature tag has been denied because single registration is not allowed by
225      * the carrier at this time. The application should fall back to dual registration if
226      * applicable.
227      */
228     public static final int DENIED_REASON_SINGLE_REGISTRATION_NOT_ALLOWED = 3;
229 
230     /**
231      * This feature tag is not recognized as a valid feature tag by the SipDelegate and has been
232      * denied.
233      */
234     public static final int DENIED_REASON_INVALID = 4;
235 
236     /** @hide */
237     @Retention(RetentionPolicy.SOURCE)
238     @IntDef(prefix = "DENIED_REASON_", value = {
239             DENIED_REASON_UNKNOWN,
240             DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE,
241             DENIED_REASON_NOT_ALLOWED,
242             DENIED_REASON_SINGLE_REGISTRATION_NOT_ALLOWED,
243             DENIED_REASON_INVALID
244     })
245     public @interface DeniedReason {}
246 
247     /**
248      * The SipDelegate has closed due to an unknown reason.
249      */
250     public static final int SIP_DELEGATE_DESTROY_REASON_UNKNOWN = 0;
251 
252     /**
253      * The SipDelegate has closed because the IMS service has died unexpectedly.
254      */
255     public static final int SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD = 1;
256 
257     /**
258      * The SipDelegate has closed because the IMS application has requested that the connection be
259      * destroyed.
260      */
261     public static final int SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP = 2;
262 
263     /**
264      * The SipDelegate has been closed due to the user disabling RCS.
265      */
266     public static final int SIP_DELEGATE_DESTROY_REASON_USER_DISABLED_RCS = 3;
267 
268     /**
269      * The SipDelegate has been closed due to the subscription associated with this delegate being
270      * torn down.
271      */
272     public static final int SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN = 4;
273 
274     /** @hide */
275     @Retention(RetentionPolicy.SOURCE)
276     @IntDef(prefix = "SIP_DELEGATE_DESTROY_REASON", value = {
277             SIP_DELEGATE_DESTROY_REASON_UNKNOWN,
278             SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD,
279             SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP,
280             SIP_DELEGATE_DESTROY_REASON_USER_DISABLED_RCS,
281             SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN
282     })
283     public @interface SipDelegateDestroyReason {}
284 
285     private final Context mContext;
286     private final int mSubId;
287     private final BinderCacheManager<IImsRcsController> mBinderCache;
288     private final BinderCacheManager<ITelephony> mTelephonyBinderCache;
289 
290     /**
291      * Only visible for testing. To instantiate an instance of this class, please use
292      * {@link ImsManager#getSipDelegateManager(int)}.
293      * @hide
294      */
295     @VisibleForTesting
SipDelegateManager(Context context, int subId, BinderCacheManager<IImsRcsController> binderCache, BinderCacheManager<ITelephony> telephonyBinderCache)296     public SipDelegateManager(Context context, int subId,
297             BinderCacheManager<IImsRcsController> binderCache,
298             BinderCacheManager<ITelephony> telephonyBinderCache) {
299         mContext = context;
300         mSubId = subId;
301         mBinderCache = binderCache;
302         mTelephonyBinderCache = telephonyBinderCache;
303     }
304 
305     /**
306      * Determines if creating SIP delegates are supported for the subscription specified.
307      * <p>
308      * If SIP delegates are not supported on this device or the carrier associated with this
309      * subscription, creating a SIP delegate will always fail, as this feature is not supported.
310      * @return true if this device supports creating a SIP delegate and the carrier associated with
311      * this subscription supports single registration, false if creating SIP delegates is not
312      * supported.
313      * @throws ImsException If the remote ImsService is not available for any reason or the
314      * subscription associated with this instance is no longer active. See
315      * {@link ImsException#getCode()} for more information.
316      *
317      * @see CarrierConfigManager.Ims#KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL
318      * @see PackageManager#FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION
319      */
320     @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
321             Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION})
isSupported()322     public boolean isSupported() throws ImsException {
323         try {
324             IImsRcsController controller = mBinderCache.getBinder();
325             if (controller == null) {
326                 throw new ImsException("Telephony server is down",
327                         ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
328             }
329             return controller.isSipDelegateSupported(mSubId);
330         } catch (ServiceSpecificException e) {
331             throw new ImsException(e.getMessage(), e.errorCode);
332         } catch (RemoteException e) {
333             throw new ImsException(e.getMessage(),
334                     ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
335         }
336     }
337 
338     /**
339      * Request that the ImsService implementation create a SipDelegate, which will configure the
340      * ImsService to forward SIP traffic that matches the filtering criteria set in supplied
341      * {@link DelegateRequest} to the application that the supplied callbacks are registered for.
342      * <p>
343      * This API requires that the caller is running as part of a long-running process and will
344      * always be available to handle incoming messages. One mechanism that can be used for this is
345      * the {@link android.service.carrier.CarrierMessagingClientService}, which the framework keeps
346      * a persistent binding to when the app is the default SMS application.
347      * <p>
348      * Note: the ability to create SipDelegates is only available applications running as the
349      * primary user.
350      * @param request The parameters that are associated with the SipDelegate creation request that
351      *                will be used to create the SipDelegate connection.
352      * @param executor The executor that will be used to call the callbacks associated with this
353      *          SipDelegate.
354      * @param dc The callback that will be used to notify the listener of the creation/destruction
355      *           of the remote SipDelegate as well as changes to the state of the remote SipDelegate
356      *           connection.
357      * @param mc The callback that will be used to notify the listener of new incoming SIP messages
358      *           as well as the status of messages that were sent by the associated
359      *           SipDelegateConnection.
360      * @throws ImsException Thrown if there was a problem communicating with the ImsService
361      * associated with this SipDelegateManager. See {@link ImsException#getCode()}.
362      */
363     @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION)
createSipDelegate(@onNull DelegateRequest request, @NonNull Executor executor, @NonNull DelegateConnectionStateCallback dc, @NonNull DelegateConnectionMessageCallback mc)364     public void createSipDelegate(@NonNull DelegateRequest request, @NonNull Executor executor,
365             @NonNull DelegateConnectionStateCallback dc,
366             @NonNull DelegateConnectionMessageCallback mc) throws ImsException {
367         Objects.requireNonNull(request, "The DelegateRequest must not be null.");
368         Objects.requireNonNull(executor, "The Executor must not be null.");
369         Objects.requireNonNull(dc, "The DelegateConnectionStateCallback must not be null.");
370         Objects.requireNonNull(mc, "The DelegateConnectionMessageCallback must not be null.");
371         try {
372             SipDelegateConnectionAidlWrapper wrapper =
373                     new SipDelegateConnectionAidlWrapper(executor, dc, mc);
374             IImsRcsController controller = mBinderCache.listenOnBinder(wrapper,
375                     wrapper::binderDied);
376             if (controller == null) {
377                 throw new ImsException("Telephony server is down",
378                         ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
379             }
380             controller.createSipDelegate(mSubId, request, mContext.getOpPackageName(),
381                     wrapper.getStateCallbackBinder(), wrapper.getMessageCallbackBinder());
382         } catch (ServiceSpecificException e) {
383             throw new ImsException(e.getMessage(), e.errorCode);
384         } catch (RemoteException e) {
385             throw new ImsException(e.getMessage(),
386                     ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
387         }
388     }
389 
390     /**
391      * Destroy a previously created {@link SipDelegateConnection} that was created using
392      * {@link #createSipDelegate}.
393      * <p>
394      * This will also clean up all related callbacks in the associated ImsService.
395      * @param delegateConnection The SipDelegateConnection to destroy.
396      * @param reason The reason for why this SipDelegateConnection was destroyed.
397      */
398     @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION)
destroySipDelegate(@onNull SipDelegateConnection delegateConnection, @SipDelegateDestroyReason int reason)399     public void destroySipDelegate(@NonNull SipDelegateConnection delegateConnection,
400             @SipDelegateDestroyReason int reason) {
401         Objects.requireNonNull(delegateConnection, "SipDelegateConnection can not be null.");
402         if (delegateConnection instanceof SipDelegateConnectionAidlWrapper) {
403             SipDelegateConnectionAidlWrapper w =
404                     (SipDelegateConnectionAidlWrapper) delegateConnection;
405             try {
406                 IImsRcsController c = mBinderCache.removeRunnable(w);
407                 c.destroySipDelegate(mSubId, w.getSipDelegateBinder(), reason);
408             } catch (RemoteException e) {
409                 // Connection to telephony died, but this will signal destruction of SipDelegate
410                 // eventually anyway, so return normally.
411                 try {
412                     w.getStateCallbackBinder().onDestroyed(
413                             SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
414                 } catch (RemoteException ignore) {
415                     // Local to process.
416                 }
417             }
418         } else {
419             throw new IllegalArgumentException("Unknown SipDelegateConnection implementation passed"
420                     + " into this method");
421         }
422     }
423 
424     /**
425      * Trigger a full network registration as required by receiving a SIP message containing a
426      * permanent error from the network or never receiving a response to a SIP transaction request.
427      *
428      * @param connection The {@link SipDelegateConnection} that was being used when this error was
429      *         received.
430      * @param sipCode The SIP code response associated with the SIP message request that
431      *         triggered this condition.
432      * @param sipReason The SIP reason code associated with the SIP message request that triggered
433      *         this condition. May be {@code null} if there was no reason String provided from the
434      *         network.
435      */
436     @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION)
triggerFullNetworkRegistration(@onNull SipDelegateConnection connection, @IntRange(from = 100, to = 699) int sipCode, @Nullable String sipReason)437     public void triggerFullNetworkRegistration(@NonNull SipDelegateConnection connection,
438             @IntRange(from = 100, to = 699) int sipCode, @Nullable String sipReason) {
439         Objects.requireNonNull(connection, "SipDelegateConnection can not be null.");
440         if (connection instanceof SipDelegateConnectionAidlWrapper) {
441             SipDelegateConnectionAidlWrapper w = (SipDelegateConnectionAidlWrapper) connection;
442             try {
443                 IImsRcsController controller = mBinderCache.getBinder();
444                 controller.triggerNetworkRegistration(mSubId, w.getSipDelegateBinder(), sipCode,
445                         sipReason);
446             } catch (RemoteException e) {
447                 // Connection to telephony died, but this will signal destruction of SipDelegate
448                 // eventually anyway, so return.
449             }
450         } else {
451             throw new IllegalArgumentException("Unknown SipDelegateConnection implementation passed"
452                     + " into this method");
453         }
454     }
455 
456     /**
457      * Register a new callback, which is used to notify the registrant of changes to
458      * the state of the underlying  IMS service that is attached to telephony to
459      * implement IMS functionality. If the manager is created for
460      * the {@link android.telephony.SubscriptionManager#DEFAULT_SUBSCRIPTION_ID},
461      * this throws an {@link ImsException}.
462      *
463      * <p>Requires Permission:
464      * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE READ_PRECISE_PHONE_STATE}
465      * or that the calling app has carrier privileges
466      * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}).
467      *
468      * @param executor the Executor that will be used to call the {@link ImsStateCallback}.
469      * @param callback The callback instance being registered.
470      * @throws ImsException in the case that the callback can not be registered.
471      * See {@link ImsException#getCode} for more information on when this is called.
472      */
473     @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
474             Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION})
registerImsStateCallback(@onNull Executor executor, @NonNull ImsStateCallback callback)475     public void registerImsStateCallback(@NonNull Executor executor,
476             @NonNull ImsStateCallback callback) throws ImsException {
477         Objects.requireNonNull(callback, "Must include a non-null ImsStateCallback.");
478         Objects.requireNonNull(executor, "Must include a non-null Executor.");
479 
480         callback.init(executor);
481         ITelephony telephony = mTelephonyBinderCache.listenOnBinder(callback, callback::binderDied);
482         if (telephony == null) {
483             throw new ImsException("Telephony server is down",
484                     ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
485         }
486 
487         try {
488             telephony.registerImsStateCallback(
489                     mSubId, ImsFeature.FEATURE_RCS,
490                     callback.getCallbackBinder(), mContext.getOpPackageName());
491         } catch (ServiceSpecificException e) {
492             throw new ImsException(e.getMessage(), e.errorCode);
493         } catch (RemoteException | IllegalStateException e) {
494             throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
495         }
496     }
497 
498     /**
499      * Unregisters a previously registered callback.
500      *
501      * @param callback The callback instance to be unregistered.
502      */
unregisterImsStateCallback(@onNull ImsStateCallback callback)503     public void unregisterImsStateCallback(@NonNull ImsStateCallback callback) {
504         Objects.requireNonNull(callback, "Must include a non-null ImsStateCallback.");
505 
506         ITelephony telephony = mTelephonyBinderCache.removeRunnable(callback);
507 
508         try {
509             if (telephony != null) {
510                 telephony.unregisterImsStateCallback(callback.getCallbackBinder());
511             }
512         } catch (RemoteException ignore) {
513             // ignore it
514         }
515     }
516 
517     /**
518      * Register a new callback, which is used to notify the registrant of changes
519      * to the state of the Sip Sessions managed remotely by the IMS stack.
520      *
521      * <p>Requires Permission:
522      * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE}
523      *
524      * @param executor the Executor that will be used to call the {@link SipDialogStateCallback}.
525      * @param callback The callback instance being registered.
526      * @throws ImsException in the case that the callback can not be registered.
527      * See {@link ImsException#getCode} for more information on when this is called.
528      * @throws UnsupportedOperationException If the device does not have
529      *          {@link PackageManager#FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION}.
530      */
531     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
registerSipDialogStateCallback(@onNull Executor executor, @NonNull SipDialogStateCallback callback)532     public void registerSipDialogStateCallback(@NonNull Executor executor,
533             @NonNull SipDialogStateCallback callback) throws ImsException {
534         Objects.requireNonNull(callback, "Must include a non-null SipDialogStateCallback.");
535         Objects.requireNonNull(executor, "Must include a non-null Executor.");
536 
537         callback.attachExecutor(executor);
538         try {
539             IImsRcsController controller = mBinderCache.listenOnBinder(
540                     callback, callback::binderDied);
541             if (controller == null) {
542                 throw new ImsException("Telephony server is down",
543                         ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
544             }
545             controller.registerSipDialogStateCallback(mSubId, callback.getCallbackBinder());
546         } catch (ServiceSpecificException e) {
547             throw new ImsException(e.getMessage(), e.errorCode);
548         } catch (RemoteException e) {
549             throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
550         } catch (IllegalStateException e) {
551             throw new IllegalStateException(e.getMessage());
552         }
553     }
554 
555     /**
556      * Unregisters a previously registered callback.
557      *
558      *  <p>Requires Permission:
559      * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE}
560      *
561      * @param callback The callback instance to be unregistered.
562      *
563      * @throws UnsupportedOperationException If the device does not have
564      *          {@link PackageManager#FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION}.
565      */
566     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
unregisterSipDialogStateCallback(@onNull SipDialogStateCallback callback)567     public void unregisterSipDialogStateCallback(@NonNull SipDialogStateCallback callback)
568             throws ImsException {
569         Objects.requireNonNull(callback, "Must include a non-null SipDialogStateCallback.");
570 
571         IImsRcsController controller = mBinderCache.removeRunnable(callback);
572         try {
573             if (controller == null) {
574                 throw new ImsException("Telephony server is down",
575                         ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
576             }
577             controller.unregisterSipDialogStateCallback(mSubId, callback.getCallbackBinder());
578         } catch (ServiceSpecificException e) {
579             throw new ImsException(e.getMessage(), e.errorCode);
580         } catch (RemoteException e) {
581             throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
582         } catch (IllegalStateException e) {
583             throw new IllegalStateException(e.getMessage());
584         }
585     }
586 }
587