1 /*
2  * Copyright (C) 2018 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.CallbackExecutor;
21 import android.annotation.IntDef;
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.net.Uri;
30 import android.os.Binder;
31 import android.os.IBinder;
32 import android.os.RemoteException;
33 import android.os.ServiceSpecificException;
34 import android.telephony.TelephonyFrameworkInitializer;
35 import android.telephony.ims.aidl.IImsRcsController;
36 import android.telephony.ims.aidl.IRcsUceControllerCallback;
37 import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
38 import android.util.Log;
39 
40 import java.lang.annotation.Retention;
41 import java.lang.annotation.RetentionPolicy;
42 import java.util.ArrayList;
43 import java.util.Collection;
44 import java.util.HashMap;
45 import java.util.List;
46 import java.util.Map;
47 import java.util.concurrent.Executor;
48 
49 /**
50  * Manages RCS User Capability Exchange for the subscription specified.
51  *
52  * @see ImsRcsManager#getUceAdapter() for information on creating an instance of this class.
53  */
54 @RequiresFeature(PackageManager.FEATURE_TELEPHONY_IMS)
55 public class RcsUceAdapter {
56     private static final String TAG = "RcsUceAdapter";
57 
58     /**
59      * This carrier supports User Capability Exchange as, defined by the framework using
60      * SIP OPTIONS. If set, the RcsFeature should support capability exchange. If not set, this
61      * RcsFeature should not publish capabilities or service capability requests.
62      * @deprecated Use {@link ImsRcsManager#CAPABILITY_TYPE_OPTIONS_UCE} instead.
63      * @hide
64      */
65     @Deprecated
66     public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1 << 0;
67 
68     /**
69      * This carrier supports User Capability Exchange as, defined by the framework using a
70      * presence server. If set, the RcsFeature should support capability exchange. If not set, this
71      * RcsFeature should not publish capabilities or service capability requests.
72      * @deprecated Use {@link ImsRcsManager#CAPABILITY_TYPE_PRESENCE_UCE} instead.
73      * @hide
74      */
75     @Deprecated
76     @SystemApi
77     public static final int CAPABILITY_TYPE_PRESENCE_UCE = 1 << 1;
78 
79     /**
80      * @deprecated Use {@link ImsRcsManager.RcsImsCapabilityFlag} instead.
81      * @hide
82      */
83     @Deprecated
84     @Retention(RetentionPolicy.SOURCE)
85     @IntDef(prefix = "CAPABILITY_TYPE_", value = {
86             CAPABILITY_TYPE_OPTIONS_UCE,
87             CAPABILITY_TYPE_PRESENCE_UCE
88     })
89     public @interface RcsImsCapabilityFlag {}
90 
91     /**
92      * An unknown error has caused the request to fail.
93      * @hide
94      */
95     @SystemApi
96     public static final int ERROR_GENERIC_FAILURE = 1;
97 
98     /**
99      * The carrier network does not have UCE support enabled for this subscriber.
100      * @hide
101      */
102     @SystemApi
103     public static final int ERROR_NOT_ENABLED = 2;
104 
105     /**
106      * The data network that the device is connected to does not support UCE currently (e.g. it is
107      * 1x only currently).
108      * @hide
109      */
110     @SystemApi
111     public static final int ERROR_NOT_AVAILABLE = 3;
112 
113     /**
114      * The network has responded with SIP 403 error and a reason "User not registered."
115      * @hide
116      */
117     @SystemApi
118     public static final int ERROR_NOT_REGISTERED = 4;
119 
120     /**
121      * The network has responded to this request with a SIP 403 error and reason "not authorized for
122      * presence" for this subscriber.
123      * @hide
124      */
125     @SystemApi
126     public static final int ERROR_NOT_AUTHORIZED = 5;
127 
128     /**
129      * The network has responded to this request with a SIP 403 error and no reason.
130      * @hide
131      */
132     @SystemApi
133     public static final int ERROR_FORBIDDEN = 6;
134 
135     /**
136      * The contact URI requested is not provisioned for voice or it is not known as an IMS
137      * subscriber to the carrier network.
138      * @hide
139      */
140     @SystemApi
141     public static final int ERROR_NOT_FOUND = 7;
142 
143     /**
144      * The capabilities request contained too many URIs for the carrier network to handle. Retry
145      * with a lower number of contact numbers. The number varies per carrier.
146      * @hide
147      */
148     @SystemApi
149     // TODO: Try to integrate this into the API so that the service will split based on carrier.
150     public static final int ERROR_REQUEST_TOO_LARGE = 8;
151 
152     /**
153      * The network did not respond to the capabilities request before the request timed out.
154      * @hide
155      */
156     @SystemApi
157     public static final int ERROR_REQUEST_TIMEOUT = 9;
158 
159     /**
160      * The request failed due to the service having insufficient memory.
161      * @hide
162      */
163     @SystemApi
164     public static final int ERROR_INSUFFICIENT_MEMORY = 10;
165 
166     /**
167      * The network was lost while trying to complete the request.
168      * @hide
169      */
170     @SystemApi
171     public static final int ERROR_LOST_NETWORK = 11;
172 
173     /**
174      * The network is temporarily unavailable or busy. Retries should only be done after the retry
175      * time returned in {@link CapabilitiesCallback#onError} has elapsed.
176      * @hide
177      */
178     @SystemApi
179     public static final int ERROR_SERVER_UNAVAILABLE = 12;
180 
181     /**@hide*/
182     @Retention(RetentionPolicy.SOURCE)
183     @IntDef(prefix = "ERROR_", value = {
184             ERROR_GENERIC_FAILURE,
185             ERROR_NOT_ENABLED,
186             ERROR_NOT_AVAILABLE,
187             ERROR_NOT_REGISTERED,
188             ERROR_NOT_AUTHORIZED,
189             ERROR_FORBIDDEN,
190             ERROR_NOT_FOUND,
191             ERROR_REQUEST_TOO_LARGE,
192             ERROR_REQUEST_TIMEOUT,
193             ERROR_INSUFFICIENT_MEMORY,
194             ERROR_LOST_NETWORK,
195             ERROR_SERVER_UNAVAILABLE
196     })
197     public @interface ErrorCode {}
198 
199     /**
200      * A capability update has been requested but the reason is unknown.
201      * @hide
202      */
203     @SystemApi
204     public static final int CAPABILITY_UPDATE_TRIGGER_UNKNOWN = 0;
205 
206     /**
207      * A capability update has been requested due to the Entity Tag (ETag) expiring.
208      * @hide
209      */
210     @SystemApi
211     public static final int CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED = 1;
212 
213     /**
214      * A capability update has been requested due to moving to LTE with VoPS disabled.
215      * @hide
216      */
217     @SystemApi
218     public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED = 2;
219 
220     /**
221      * A capability update has been requested due to moving to LTE with VoPS enabled.
222      * @hide
223      */
224     @SystemApi
225     public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED = 3;
226 
227     /**
228      * A capability update has been requested due to moving to eHRPD.
229      * @hide
230      */
231     @SystemApi
232     public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD = 4;
233 
234     /**
235      * A capability update has been requested due to moving to HSPA+.
236      * @hide
237      */
238     @SystemApi
239     public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS = 5;
240 
241     /**
242      * A capability update has been requested due to moving to 3G.
243      * @hide
244      */
245     @SystemApi
246     public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G = 6;
247 
248     /**
249      * A capability update has been requested due to moving to 2G.
250      * @hide
251      */
252     @SystemApi
253     public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G = 7;
254 
255     /**
256      * A capability update has been requested due to moving to WLAN
257      * @hide
258      */
259     @SystemApi
260     public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN = 8;
261 
262     /**
263      * A capability update has been requested due to moving to IWLAN
264      * @hide
265      */
266     @SystemApi
267     public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN = 9;
268 
269     /**
270      * A capability update has been requested due to moving to 5G NR with VoPS disabled.
271      * @hide
272      */
273     @SystemApi
274     public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED = 10;
275 
276     /**
277      * A capability update has been requested due to moving to 5G NR with VoPS enabled.
278      * @hide
279      */
280     @SystemApi
281     public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED = 11;
282 
283     /**
284      * A capability update has been requested due to IMS being registered over INTERNET PDN.
285      * @hide
286      */
287     @SystemApi
288     public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_INTERNET_PDN = 12;
289 
290     /**@hide*/
291     @Retention(RetentionPolicy.SOURCE)
292     @IntDef(prefix = "ERROR_", value = {
293             CAPABILITY_UPDATE_TRIGGER_UNKNOWN,
294             CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED,
295             CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED,
296             CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED,
297             CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD,
298             CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS,
299             CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G,
300             CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G,
301             CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN,
302             CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN,
303             CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED,
304             CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED,
305             CAPABILITY_UPDATE_TRIGGER_MOVE_TO_INTERNET_PDN
306     })
307     public @interface StackPublishTriggerType {}
308 
309     /**
310      * The last publish has resulted in a "200 OK" response or the device is using SIP OPTIONS for
311      * UCE.
312      * @hide
313      */
314     @SystemApi
315     public static final int PUBLISH_STATE_OK = 1;
316 
317     /**
318      * The hasn't published its capabilities since boot or hasn't gotten any publish response yet.
319      * @hide
320      */
321     @SystemApi
322     public static final int PUBLISH_STATE_NOT_PUBLISHED = 2;
323 
324     /**
325      * The device has tried to publish its capabilities, which has resulted in an error. This error
326      * is related to the fact that the device is not provisioned for voice.
327      * @hide
328      */
329     @SystemApi
330     public static final int PUBLISH_STATE_VOICE_PROVISION_ERROR = 3;
331 
332     /**
333      * The device has tried to publish its capabilities, which has resulted in an error. This error
334      * is related to the fact that the device is not RCS or UCE provisioned.
335      * @hide
336      */
337     @SystemApi
338     public static final int PUBLISH_STATE_RCS_PROVISION_ERROR = 4;
339 
340     /**
341      * The last publish resulted in a "408 Request Timeout" response.
342      * @hide
343      */
344     @SystemApi
345     public static final int PUBLISH_STATE_REQUEST_TIMEOUT = 5;
346 
347     /**
348      * The last publish resulted in another unknown error, such as SIP 503 - "Service Unavailable"
349      * or SIP 423 - "Interval too short".
350      * <p>
351      * Device shall retry with exponential back-off.
352      * @hide
353      */
354     @SystemApi
355     public static final int PUBLISH_STATE_OTHER_ERROR = 6;
356 
357     /**
358      * The device is currently trying to publish its capabilities to the network.
359      * @hide
360      */
361     @SystemApi
362     public static final int PUBLISH_STATE_PUBLISHING = 7;
363 
364 
365     /**@hide*/
366     @Retention(RetentionPolicy.SOURCE)
367     @IntDef(prefix = "PUBLISH_STATE_", value = {
368             PUBLISH_STATE_OK,
369             PUBLISH_STATE_NOT_PUBLISHED,
370             PUBLISH_STATE_VOICE_PROVISION_ERROR,
371             PUBLISH_STATE_RCS_PROVISION_ERROR,
372             PUBLISH_STATE_REQUEST_TIMEOUT,
373             PUBLISH_STATE_OTHER_ERROR,
374             PUBLISH_STATE_PUBLISHING
375     })
376     public @interface PublishState {}
377 
378     /**
379      * An application can use {@link #addOnPublishStateChangedListener} to register a
380      * {@link OnPublishStateChangedListener ), which will notify the user when the publish state to
381      * the network changes.
382      * @hide
383      */
384     @SystemApi
385     public interface OnPublishStateChangedListener {
386         /**
387          * Notifies the callback when the publish state has changed.
388          * @param publishState The latest update to the publish state.
389          *
390          * @deprecated Replaced by {@link #onPublishStateChange}, deprecated for
391          * sip information.
392          */
393         @Deprecated
onPublishStateChange(@ublishState int publishState)394         void onPublishStateChange(@PublishState int publishState);
395 
396         /**
397          * Notifies the callback when the publish state has changed or the publish operation is
398          * done.
399          * @param attributes The latest information related to the publish.
400          */
onPublishStateChange(@onNull PublishAttributes attributes)401         default void onPublishStateChange(@NonNull PublishAttributes attributes) {
402             onPublishStateChange(attributes.getPublishState());
403         };
404     }
405 
406     /**
407      * An application can use {@link #addOnPublishStateChangedListener} to register a
408      * {@link OnPublishStateChangedListener ), which will notify the user when the publish state to
409      * the network changes.
410      * @hide
411      */
412     public static class PublishStateCallbackAdapter {
413 
414         private static class PublishStateBinder extends IRcsUcePublishStateCallback.Stub {
415             private final OnPublishStateChangedListener mPublishStateChangeListener;
416             private final Executor mExecutor;
417 
PublishStateBinder(Executor executor, OnPublishStateChangedListener listener)418             PublishStateBinder(Executor executor, OnPublishStateChangedListener listener) {
419                 mExecutor = executor;
420                 mPublishStateChangeListener = listener;
421             }
422 
423             @Override
onPublishUpdated(@onNull PublishAttributes attributes)424             public void onPublishUpdated(@NonNull PublishAttributes attributes) {
425                 if (mPublishStateChangeListener == null) return;
426 
427                 final long callingIdentity = Binder.clearCallingIdentity();
428                 try {
429                     mExecutor.execute(() ->
430                             mPublishStateChangeListener.onPublishStateChange(attributes));
431                 } finally {
432                     restoreCallingIdentity(callingIdentity);
433                 }
434             }
435         }
436 
437         private final PublishStateBinder mBinder;
438 
PublishStateCallbackAdapter(@onNull Executor executor, @NonNull OnPublishStateChangedListener listener)439         public PublishStateCallbackAdapter(@NonNull Executor executor,
440                 @NonNull OnPublishStateChangedListener listener) {
441             mBinder = new PublishStateBinder(executor, listener);
442         }
443 
444         /**@hide*/
getBinder()445         public final IRcsUcePublishStateCallback getBinder() {
446             return mBinder;
447         }
448     }
449 
450     /**
451      * A callback for the response to a UCE request. The method
452      * {@link CapabilitiesCallback#onCapabilitiesReceived} will be called zero or more times as the
453      * capabilities are fetched from multiple sources, both cached on the device and on the network.
454      * <p>
455      * This request will take a varying amount of time depending on if the contacts requested are
456      * cached or if it requires a network query. The timeout time of these requests can vary
457      * depending on the network, however in poor cases it could take up to a minute for a request
458      * to timeout. In that time, only a subset of capabilities may have been retrieved.
459      * <p>
460      * After {@link CapabilitiesCallback#onComplete} or {@link CapabilitiesCallback#onError} has
461      * been called, the reference to this callback will be discarded on the service side.
462      * @see #requestCapabilities(Collection, Executor, CapabilitiesCallback)
463      * @hide
464      */
465     @SystemApi
466     public interface CapabilitiesCallback {
467 
468         /**
469          * The pending capability request has completed successfully for one or more of the
470          * requested contacts.
471          * This may be called one or more times before the request is fully completed, as
472          * capabilities may need to be fetched from multiple sources both on device and on the
473          * network. Once the capabilities of all the requested contacts have been received,
474          * {@link #onComplete()} will be called. If there was an error during the capability
475          * exchange process, {@link #onError(int, long)} will be called instead.
476          * @param contactCapabilities List of capabilities associated with each contact requested.
477          */
onCapabilitiesReceived(@onNull List<RcsContactUceCapability> contactCapabilities)478         void onCapabilitiesReceived(@NonNull List<RcsContactUceCapability> contactCapabilities);
479 
480         /**
481          * Called when the pending request has completed successfully due to all requested contacts
482          * information being delivered. The callback {@link #onCapabilitiesReceived(List)} will be
483          * called one or more times and will contain the contacts in the request that the device has
484          * received capabilities for.
485          *
486          * @see #onComplete(SipDetails) onComplete(SipDetails) provides more information related to
487          * the underlying SIP transaction used to perform the capabilities exchange. Either this
488          * method or the alternate method should be implemented to determine when the request has
489          * completed successfully.
490          */
onComplete()491         default void onComplete() {}
492 
493         /**
494          * The pending request has resulted in an error and may need to be retried, depending on the
495          * error code.
496          * @param errorCode The reason for the framework being unable to process the request.
497          * @param retryIntervalMillis The time in milliseconds the requesting application should
498          * wait before retrying, if non-zero.
499          *
500          * @see #onError(int, long, SipDetails) onError(int, long, SipDetails) provides more
501          * information related to the underlying SIP transaction that resulted in an error. Either
502          * this method or the alternative method should be implemented to determine when the
503          * request has completed with an error.
504          */
onError(@rrorCode int errorCode, long retryIntervalMillis)505         default void onError(@ErrorCode int errorCode, long retryIntervalMillis) {}
506 
507         /**
508          * Called when the pending request has completed successfully due to all requested contacts
509          * information being delivered. The callback {@link #onCapabilitiesReceived(List)} will be
510          * called one or more times and will contain the contacts in the request that the device has
511          * received capabilities for.
512          *
513          * This method contains more information about the underlying SIP transaction if it exists.
514          * If this information is not needed, {@link #onComplete()} can be implemented
515          * instead.
516          *
517          * @param details The SIP information related to this request if the device supports
518          *                supplying this information. This parameter will be {@code null} if this
519          *                information is not available.
520          */
onComplete(@ullable SipDetails details)521         default void onComplete(@Nullable SipDetails details) {
522             onComplete();
523         };
524 
525         /**
526          * The pending request has resulted in an error and may need to be retried, depending on the
527          * error code.
528          *
529          * This method contains more information about the underlying SIP transaction if it exists.
530          * If this information is not needed, {@link #onError(int, long)} can be implemented
531          * instead.
532          * @param errorCode The reason for the framework being unable to process the request.
533          * @param retryIntervalMillis The time in milliseconds the requesting application should
534          * wait before retrying, if non-zero.
535          * @param details The SIP information related to this request if the device supports
536          *                supplying this information. This parameter will be {@code null} if this
537          *                information is not available.
538          */
onError(@rrorCode int errorCode, long retryIntervalMillis, @Nullable SipDetails details)539         default void onError(@ErrorCode int errorCode, long retryIntervalMillis,
540                 @Nullable SipDetails details) {
541             onError(errorCode, retryIntervalMillis);
542         };
543     }
544 
545     private final Context mContext;
546     private final int mSubId;
547     private final Map<OnPublishStateChangedListener, PublishStateCallbackAdapter>
548             mPublishStateCallbacks;
549 
550     /**
551      * Not to be instantiated directly, use {@link ImsRcsManager#getUceAdapter()} to instantiate
552      * this manager class.
553      * @hide
554      */
RcsUceAdapter(Context context, int subId)555     RcsUceAdapter(Context context, int subId) {
556         mContext = context;
557         mSubId = subId;
558         mPublishStateCallbacks = new HashMap<>();
559     }
560 
561     /**
562      * Request the RCS capabilities for one or more contacts using RCS User Capability Exchange.
563      * <p>
564      * This API will first check a local cache for the requested numbers and return the cached
565      * RCS capabilities of each number if the cache exists and is not stale. If the cache for a
566      * number is stale or there is no cached information about the requested number, the device will
567      * then perform a query to the carrier's network to request the RCS capabilities of the
568      * requested numbers.
569      * <p>
570      * Depending on the number of requests being sent, this API may throttled internally as the
571      * operations are queued to be executed by the carrier's network.
572      * <p>
573      * Be sure to check the availability of this feature using
574      * {@link ImsRcsManager#isAvailable(int, int)} and ensuring
575      * {@link
576      * android.telephony.ims.feature.RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} or
577      * {@link
578      * android.telephony.ims.feature.RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE} is
579      * enabled or else this operation will fail with {@link #ERROR_NOT_AVAILABLE} or
580      * {@link #ERROR_NOT_ENABLED}.
581      *
582      * @param contactNumbers A list of numbers that the capabilities are being requested for.
583      * @param executor The executor that will be used when the request is completed and the
584      *         {@link CapabilitiesCallback} is called.
585      * @param c A one-time callback for when the request for capabilities completes or there is an
586      *         error processing the request.
587      * @throws ImsException if the subscription associated with this instance of
588      * {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not
589      * available. This can happen if the ImsService has crashed, for example, or if the subscription
590      * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes.
591      * @throws UnsupportedOperationException If the device does not have
592      *          {@link PackageManager#FEATURE_TELEPHONY_IMS}.
593      * @hide
594      */
595     @SystemApi
596     @RequiresPermission(allOf = {Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE,
597             Manifest.permission.READ_CONTACTS})
requestCapabilities(@onNull Collection<Uri> contactNumbers, @NonNull @CallbackExecutor Executor executor, @NonNull CapabilitiesCallback c)598     public void requestCapabilities(@NonNull Collection<Uri> contactNumbers,
599             @NonNull @CallbackExecutor Executor executor,
600             @NonNull CapabilitiesCallback c) throws ImsException {
601         if (c == null) {
602             throw new IllegalArgumentException("Must include a non-null CapabilitiesCallback.");
603         }
604         if (executor == null) {
605             throw new IllegalArgumentException("Must include a non-null Executor.");
606         }
607         if (contactNumbers == null) {
608             throw new IllegalArgumentException("Must include non-null contact number list.");
609         }
610 
611         IImsRcsController imsRcsController = getIImsRcsController();
612         if (imsRcsController == null) {
613             Log.e(TAG, "requestCapabilities: IImsRcsController is null");
614             throw new ImsException("Can not find remote IMS service",
615                     ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
616         }
617 
618         IRcsUceControllerCallback internalCallback = new IRcsUceControllerCallback.Stub() {
619             @Override
620             public void onCapabilitiesReceived(List<RcsContactUceCapability> contactCapabilities) {
621                 final long callingIdentity = Binder.clearCallingIdentity();
622                 try {
623                     executor.execute(() -> c.onCapabilitiesReceived(contactCapabilities));
624                 } finally {
625                     restoreCallingIdentity(callingIdentity);
626                 }
627             }
628             @Override
629             public void onComplete(@Nullable SipDetails details) {
630                 final long callingIdentity = Binder.clearCallingIdentity();
631                 try {
632                     executor.execute(() -> c.onComplete(details));
633                 } finally {
634                     restoreCallingIdentity(callingIdentity);
635                 }
636             }
637             @Override
638             public void onError(int errorCode, long retryAfterMilliseconds,
639                     @Nullable SipDetails details) {
640                 final long callingIdentity = Binder.clearCallingIdentity();
641                 try {
642                     executor.execute(() -> c.onError(errorCode, retryAfterMilliseconds, details));
643                 } finally {
644                     restoreCallingIdentity(callingIdentity);
645                 }
646             }
647         };
648 
649         try {
650             imsRcsController.requestCapabilities(mSubId, mContext.getOpPackageName(),
651                     mContext.getAttributionTag(), new ArrayList(contactNumbers), internalCallback);
652         } catch (ServiceSpecificException e) {
653             throw new ImsException(e.toString(), e.errorCode);
654         } catch (RemoteException e) {
655             Log.e(TAG, "Error calling IImsRcsController#requestCapabilities", e);
656             throw new ImsException("Remote IMS Service is not available",
657                     ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
658         }
659     }
660 
661     /**
662      * Request the RCS capabilities for a phone number using User Capability Exchange.
663      * <p>
664      * Unlike {@link #requestCapabilities(Collection, Executor, CapabilitiesCallback)}, which caches
665      * the result received from the network for a certain amount of time and uses that cached result
666      * for subsequent requests for RCS capabilities of the same phone number, this API will always
667      * request the RCS capabilities of a contact from the carrier's network.
668      * <p>
669      * Depending on the number of requests, this API may throttled internally as the operations are
670      * queued to be executed by the carrier's network.
671      * <p>
672      * Be sure to check the availability of this feature using
673      * {@link ImsRcsManager#isAvailable(int, int)} and ensuring
674      * {@link
675      * android.telephony.ims.feature.RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} or
676      * {@link
677      * android.telephony.ims.feature.RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE} is
678      * enabled or else this operation will fail with
679      * {@link #ERROR_NOT_AVAILABLE} or {@link #ERROR_NOT_ENABLED}.
680      *
681      * @param contactNumber The contact of the capabilities is being requested for.
682      * @param executor The executor that will be used when the request is completed and the
683      * {@link CapabilitiesCallback} is called.
684      * @param c A one-time callback for when the request for capabilities completes or there is
685      * an error processing the request.
686      * @throws ImsException if the subscription associated with this instance of
687      * {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not
688      * available. This can happen if the ImsService has crashed, for example, or if the subscription
689      * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes.
690      * @throws UnsupportedOperationException If the device does not have
691      *          {@link PackageManager#FEATURE_TELEPHONY_IMS}.
692      * @hide
693      */
694     @SystemApi
695     @RequiresPermission(allOf = {Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE,
696             Manifest.permission.READ_CONTACTS})
requestAvailability(@onNull Uri contactNumber, @NonNull @CallbackExecutor Executor executor, @NonNull CapabilitiesCallback c)697     public void requestAvailability(@NonNull Uri contactNumber,
698             @NonNull @CallbackExecutor Executor executor,
699             @NonNull CapabilitiesCallback c) throws ImsException {
700         if (executor == null) {
701             throw new IllegalArgumentException("Must include a non-null Executor.");
702         }
703         if (contactNumber == null) {
704             throw new IllegalArgumentException("Must include non-null contact number.");
705         }
706         if (c == null) {
707             throw new IllegalArgumentException("Must include a non-null CapabilitiesCallback.");
708         }
709 
710         IImsRcsController imsRcsController = getIImsRcsController();
711         if (imsRcsController == null) {
712             Log.e(TAG, "requestAvailability: IImsRcsController is null");
713             throw new ImsException("Cannot find remote IMS service",
714                     ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
715         }
716 
717         IRcsUceControllerCallback internalCallback = new IRcsUceControllerCallback.Stub() {
718             @Override
719             public void onCapabilitiesReceived(List<RcsContactUceCapability> contactCapabilities) {
720                 final long callingIdentity = Binder.clearCallingIdentity();
721                 try {
722                     executor.execute(() -> c.onCapabilitiesReceived(contactCapabilities));
723                 } finally {
724                     restoreCallingIdentity(callingIdentity);
725                 }
726             }
727             @Override
728             public void onComplete(@Nullable SipDetails details) {
729                 final long callingIdentity = Binder.clearCallingIdentity();
730                 try {
731                     executor.execute(() -> c.onComplete(details));
732                 } finally {
733                     restoreCallingIdentity(callingIdentity);
734                 }
735             }
736             @Override
737             public void onError(int errorCode, long retryAfterMilliseconds,
738                     @Nullable SipDetails details) {
739                 final long callingIdentity = Binder.clearCallingIdentity();
740                 try {
741                     executor.execute(() -> c.onError(errorCode, retryAfterMilliseconds, details));
742                 } finally {
743                     restoreCallingIdentity(callingIdentity);
744                 }
745             }
746         };
747 
748         try {
749             imsRcsController.requestAvailability(mSubId, mContext.getOpPackageName(),
750                     mContext.getAttributionTag(), contactNumber, internalCallback);
751         } catch (ServiceSpecificException e) {
752             throw new ImsException(e.toString(), e.errorCode);
753         } catch (RemoteException e) {
754             Log.e(TAG, "Error calling IImsRcsController#requestAvailability", e);
755             throw new ImsException("Remote IMS Service is not available",
756                     ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
757         }
758     }
759 
760     /**
761      * Gets the last publish result from the UCE service if the device is using an RCS presence
762      * server.
763      * @return The last publish result from the UCE service. If the device is using SIP OPTIONS,
764      * this method will return {@link #PUBLISH_STATE_OK} as well.
765      * @throws ImsException if the subscription associated with this instance of
766      * {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not
767      * available. This can happen if the ImsService has crashed, for example, or if the subscription
768      * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes.
769      * @throws UnsupportedOperationException If the device does not have
770      *          {@link PackageManager#FEATURE_TELEPHONY_IMS}.
771      * @hide
772      */
773     @SystemApi
774     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
getUcePublishState()775     public @PublishState int getUcePublishState() throws ImsException {
776         IImsRcsController imsRcsController = getIImsRcsController();
777         if (imsRcsController == null) {
778             Log.e(TAG, "getUcePublishState: IImsRcsController is null");
779             throw new ImsException("Can not find remote IMS service",
780                     ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
781         }
782 
783         try {
784             return imsRcsController.getUcePublishState(mSubId);
785         } catch (ServiceSpecificException e) {
786             throw new ImsException(e.getMessage(), e.errorCode);
787         } catch (RemoteException e) {
788             Log.e(TAG, "Error calling IImsRcsController#getUcePublishState", e);
789             throw new ImsException("Remote IMS Service is not available",
790                     ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
791         }
792     }
793 
794     /**
795      * Registers a {@link OnPublishStateChangedListener} with the system, which will provide publish
796      * state updates for the subscription specified in {@link ImsManager@getRcsManager(subid)}.
797      * <p>
798      * Use {@link android.telephony.SubscriptionManager.OnSubscriptionsChangedListener} to listen
799      * to subscription
800      * changed events and call
801      * {@link #removeOnPublishStateChangedListener(OnPublishStateChangedListener)} to clean up.
802      * <p>
803      * The registered {@link OnPublishStateChangedListener} will also receive a callback when it is
804      * registered with the current publish state.
805      *
806      * @param executor The executor the listener callback events should be run on.
807      * @param listener The {@link OnPublishStateChangedListener} to be added.
808      * @throws ImsException if the subscription associated with this callback is valid, but
809      * the {@link ImsService} associated with the subscription is not available. This can happen if
810      * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed
811      * reason.
812      * @throws UnsupportedOperationException If the device does not have
813      *          {@link PackageManager#FEATURE_TELEPHONY_IMS}.
814      * @hide
815      */
816     @SystemApi
817     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
addOnPublishStateChangedListener(@onNull @allbackExecutor Executor executor, @NonNull OnPublishStateChangedListener listener)818     public void addOnPublishStateChangedListener(@NonNull @CallbackExecutor Executor executor,
819             @NonNull OnPublishStateChangedListener listener) throws ImsException {
820         if (executor == null) {
821             throw new IllegalArgumentException("Must include a non-null Executor.");
822         }
823         if (listener == null) {
824             throw new IllegalArgumentException(
825                     "Must include a non-null OnPublishStateChangedListener.");
826         }
827 
828         IImsRcsController imsRcsController = getIImsRcsController();
829         if (imsRcsController == null) {
830             Log.e(TAG, "addOnPublishStateChangedListener : IImsRcsController is null");
831             throw new ImsException("Cannot find remote IMS service",
832                     ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
833         }
834 
835         PublishStateCallbackAdapter stateCallback = addPublishStateCallback(executor, listener);
836         try {
837             imsRcsController.registerUcePublishStateCallback(mSubId, stateCallback.getBinder());
838         } catch (ServiceSpecificException e) {
839             throw new ImsException(e.getMessage(), e.errorCode);
840         } catch (RemoteException e) {
841             Log.e(TAG, "Error calling IImsRcsController#registerUcePublishStateCallback", e);
842             throw new ImsException("Remote IMS Service is not available",
843                     ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
844         }
845     }
846 
847     /**
848      * Removes an existing {@link OnPublishStateChangedListener}.
849      * <p>
850      * When the subscription associated with this callback is removed
851      * (SIM removed, ESIM swap,etc...), this callback will automatically be removed. If this method
852      * is called for an inactive subscription, it will result in a no-op.
853      *
854      * @param listener The callback to be unregistered.
855      * @throws ImsException if the subscription associated with this callback is valid, but
856      * the {@link ImsService} associated with the subscription is not available. This can happen if
857      * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed
858      * reason.
859      * @throws UnsupportedOperationException If the device does not have
860      *          {@link PackageManager#FEATURE_TELEPHONY_IMS}.
861      * @hide
862      */
863     @SystemApi
864     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
removeOnPublishStateChangedListener( @onNull OnPublishStateChangedListener listener)865     public void removeOnPublishStateChangedListener(
866             @NonNull OnPublishStateChangedListener listener) throws ImsException {
867         if (listener == null) {
868             throw new IllegalArgumentException(
869                     "Must include a non-null OnPublishStateChangedListener.");
870         }
871         IImsRcsController imsRcsController = getIImsRcsController();
872         if (imsRcsController == null) {
873             Log.e(TAG, "removeOnPublishStateChangedListener: IImsRcsController is null");
874             throw new ImsException("Cannot find remote IMS service",
875                     ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
876         }
877 
878         PublishStateCallbackAdapter callback = removePublishStateCallback(listener);
879         if (callback == null) {
880             return;
881         }
882 
883         try {
884             imsRcsController.unregisterUcePublishStateCallback(mSubId, callback.getBinder());
885         } catch (android.os.ServiceSpecificException e) {
886             throw new ImsException(e.getMessage(), e.errorCode);
887         } catch (RemoteException e) {
888             Log.e(TAG, "Error calling IImsRcsController#unregisterUcePublishStateCallback", e);
889             throw new ImsException("Remote IMS Service is not available",
890                     ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
891         }
892     }
893 
894     /**
895      * The setting for whether or not the user has opted in to the automatic refresh of the RCS
896      * capabilities associated with the contacts in the user's contact address book. By default,
897      * this setting is disabled and must be enabled after the user has seen the opt-in dialog shown
898      * by {@link ImsRcsManager#ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN}.
899      * <p>
900      * If this feature is enabled, the device will periodically share the phone numbers of all of
901      * the contacts in the user's address book with the carrier to refresh the RCS capabilities
902      * cache associated with those contacts as the local cache becomes stale.
903      * <p>
904      * This setting will only enable this feature if
905      * {@link android.telephony.CarrierConfigManager.Ims#KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL} is
906      * also enabled.
907      * <p>
908      * Note: This setting does not affect whether or not the device publishes its service
909      * capabilities if the subscription supports presence publication.
910      *
911      * @return true if the user has opted in for automatic refresh of the RCS capabilities of their
912      * contacts, false otherwise.
913      * @throws ImsException if the subscription associated with this instance of
914      * {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not
915      * available. This can happen if the ImsService has crashed, for example, or if the subscription
916      * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes.
917      * @throws UnsupportedOperationException If the device does not have
918      *          {@link PackageManager#FEATURE_TELEPHONY_IMS}.
919      */
920     @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
isUceSettingEnabled()921     public boolean isUceSettingEnabled() throws ImsException {
922         IImsRcsController imsRcsController = getIImsRcsController();
923         if (imsRcsController == null) {
924             Log.e(TAG, "isUceSettingEnabled: IImsRcsController is null");
925             throw new ImsException("Can not find remote IMS service",
926                     ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
927         }
928         try {
929             // Telephony.SimInfo#IMS_RCS_UCE_ENABLED can also be used to listen to changes to this.
930             return imsRcsController.isUceSettingEnabled(mSubId, mContext.getOpPackageName(),
931                     mContext.getAttributionTag());
932         } catch (RemoteException e) {
933             Log.e(TAG, "Error calling IImsRcsController#isUceSettingEnabled", e);
934             throw new ImsException("Remote IMS Service is not available",
935                     ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
936         }
937     }
938 
939     /**
940      * Change the user’s setting for whether or not the user has opted in to the automatic
941      * refresh of the RCS capabilities associated with the contacts in the user's contact address
942      * book. By default, this setting is disabled and must be enabled using this method after the
943      * user has seen the opt-in dialog shown by
944      * {@link ImsRcsManager#ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN}.
945      * <p>
946      * If an application wishes to request that the user enable this feature, they must launch an
947      * Activity using the Intent {@link ImsRcsManager#ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN},
948      * which will ask the user if they wish to enable this feature. This setting must only be
949      * enabled after the user has opted-in to this feature.
950      * <p>
951      * This must not affect the
952      * {@link #requestCapabilities(Collection, Executor, CapabilitiesCallback)} or
953      * {@link #requestAvailability(Uri, Executor, CapabilitiesCallback)} API,
954      * as those APIs are still required for per-contact RCS capability queries of phone numbers
955      * required for operations such as placing a Video Telephony call or starting an RCS chat
956      * session.
957      * <p>
958      * This setting will only enable this feature if
959      * {@link android.telephony.CarrierConfigManager.Ims#KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL} is
960      * also enabled.
961      * <p>
962      * Note: This setting does not affect whether or not the device publishes its service
963      * capabilities if the subscription supports presence publication.
964      *
965      * @param isEnabled true if the user has opted in for automatic refresh of the RCS capabilities
966      *                  of their contacts, or false if they have chosen to opt-out. By default this
967      *                  setting is disabled.
968      * @throws ImsException if the subscription associated with this instance of
969      * {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not
970      * available. This can happen if the ImsService has crashed, for example, or if the subscription
971      * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes.
972      * @throws UnsupportedOperationException If the device does not have
973      *          {@link PackageManager#FEATURE_TELEPHONY_IMS}.
974      * @hide
975      */
976     @SystemApi
977     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
setUceSettingEnabled(boolean isEnabled)978     public void setUceSettingEnabled(boolean isEnabled) throws ImsException {
979         IImsRcsController imsRcsController = getIImsRcsController();
980         if (imsRcsController == null) {
981             Log.e(TAG, "setUceSettingEnabled: IImsRcsController is null");
982             throw new ImsException("Can not find remote IMS service",
983                     ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
984         }
985 
986         try {
987             imsRcsController.setUceSettingEnabled(mSubId, isEnabled);
988         } catch (RemoteException e) {
989             Log.e(TAG, "Error calling IImsRcsController#setUceSettingEnabled", e);
990             throw new ImsException("Remote IMS Service is not available",
991                     ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
992         }
993     }
994 
995     /**
996      * Add the {@link OnPublishStateChangedListener} to collection for tracking.
997      * @param executor The executor that will be used when the publish state is changed and the
998      * {@link OnPublishStateChangedListener} is called.
999      * @param listener The {@link OnPublishStateChangedListener} to call the publish state changed.
1000      * @return The {@link PublishStateCallbackAdapter} to wrapper the
1001      * {@link OnPublishStateChangedListener}
1002      */
addPublishStateCallback(@onNull Executor executor, @NonNull OnPublishStateChangedListener listener)1003     private PublishStateCallbackAdapter addPublishStateCallback(@NonNull Executor executor,
1004             @NonNull OnPublishStateChangedListener listener) {
1005         PublishStateCallbackAdapter adapter = new PublishStateCallbackAdapter(executor, listener);
1006         synchronized (mPublishStateCallbacks) {
1007             mPublishStateCallbacks.put(listener, adapter);
1008         }
1009         return adapter;
1010     }
1011 
1012     /**
1013      * Remove the existing {@link OnPublishStateChangedListener}.
1014      * @param listener The {@link OnPublishStateChangedListener} to remove from the collection.
1015      * @return The wrapper class {@link PublishStateCallbackAdapter} associated with the
1016      * {@link OnPublishStateChangedListener}.
1017      */
removePublishStateCallback( @onNull OnPublishStateChangedListener listener)1018     private PublishStateCallbackAdapter removePublishStateCallback(
1019             @NonNull OnPublishStateChangedListener listener) {
1020         synchronized (mPublishStateCallbacks) {
1021             return mPublishStateCallbacks.remove(listener);
1022         }
1023     }
1024 
getIImsRcsController()1025     private IImsRcsController getIImsRcsController() {
1026         IBinder binder = TelephonyFrameworkInitializer
1027                 .getTelephonyServiceManager()
1028                 .getTelephonyImsServiceRegisterer()
1029                 .get();
1030         return IImsRcsController.Stub.asInterface(binder);
1031     }
1032 }
1033