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