Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f95e394 authored by James Lin's avatar James Lin Committed by Automerger Merge Worker
Browse files

Merge "[RCS UCE] Update the ImsService APIs and application APIs change." am:...

Merge "[RCS UCE] Update the ImsService APIs and application APIs change." am: adaf6fd8 am: a5c6bb77

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1479639

Change-Id: Ie27ddf06fd31e1d46a7cf13ffed808fa4f287120
parents ce71ee6e a5c6bb77
Loading
Loading
Loading
Loading
+5 −8
Original line number Diff line number Diff line
@@ -29,12 +29,10 @@ import android.os.RemoteException;
import android.provider.Settings;
import android.telephony.AccessNetworkConstants;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyFrameworkInitializer;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsRcsController;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.RcsFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.util.Log;

@@ -77,7 +75,7 @@ public class ImsRcsManager {
            "android.telephony.ims.action.SHOW_CAPABILITY_DISCOVERY_OPT_IN";

    /**
     * Receives RCS availability status updates from the ImsService.
     * Receives RCS Feature availability status updates from the ImsService.
     *
     * @see #isAvailable(int)
     * @see #registerRcsAvailabilityCallback(Executor, AvailabilityCallback)
@@ -101,8 +99,7 @@ public class ImsRcsManager {

                long callingIdentity = Binder.clearCallingIdentity();
                try {
                    mExecutor.execute(() -> mLocalCallback.onAvailabilityChanged(
                            new RcsFeature.RcsImsCapabilities(config)));
                    mExecutor.execute(() -> mLocalCallback.onAvailabilityChanged(config));
                } finally {
                    restoreCallingIdentity(callingIdentity);
                }
@@ -137,7 +134,7 @@ public class ImsRcsManager {
         *
         * @param capabilities The new availability of the capabilities.
         */
        public void onAvailabilityChanged(@NonNull RcsFeature.RcsImsCapabilities capabilities) {
        public void onAvailabilityChanged(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) {
        }

        /**@hide*/
@@ -394,7 +391,7 @@ public class ImsRcsManager {
     * @hide
     */
    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
    public boolean isCapable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
    public boolean isCapable(@RcsUceAdapter.RcsImsCapabilityFlag int capability,
            @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) throws ImsException {
        IImsRcsController imsRcsController = getIImsRcsController();
        if (imsRcsController == null) {
@@ -428,7 +425,7 @@ public class ImsRcsManager {
     * @hide
     */
    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
    public boolean isAvailable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability)
    public boolean isAvailable(@RcsUceAdapter.RcsImsCapabilityFlag int capability)
            throws ImsException {
        IImsRcsController imsRcsController = getIImsRcsController();
        if (imsRcsController == null) {
+20 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package android.telephony.ims;

parcelable RcsContactTerminatedReason;
+75 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.telephony.ims;

import android.annotation.NonNull;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;

/**
 * When the resource for the presence subscribe event has been terminated, the method
 * SubscribeResponseCallback#onResourceTerminated wil be called with a list of
 * RcsContactTerminatedReason.
 * @hide
 */
public final class RcsContactTerminatedReason implements Parcelable {
    private final Uri mContactUri;
    private final String mReason;

    public RcsContactTerminatedReason(Uri contact, String reason) {
        mContactUri = contact;
        mReason = reason;
    }

    private RcsContactTerminatedReason(Parcel in) {
        mContactUri = in.readParcelable(Uri.class.getClassLoader());
        mReason = in.readString();
    }

    @Override
    public void writeToParcel(@NonNull Parcel out, int flags) {
        out.writeParcelable(mContactUri, flags);
        out.writeString(mReason);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public static final @NonNull Creator<RcsContactTerminatedReason> CREATOR =
            new Creator<RcsContactTerminatedReason>() {
                @Override
                public RcsContactTerminatedReason createFromParcel(Parcel in) {
                    return new RcsContactTerminatedReason(in);
                }

                @Override
                public RcsContactTerminatedReason[] newArray(int size) {
                    return new RcsContactTerminatedReason[size];
                }
            };

    public Uri getContactUri() {
        return mContactUri;
    }

    public String getReason() {
        return mReason;
    }
}
+225 −23
Original line number Diff line number Diff line
@@ -46,6 +46,30 @@ import java.util.concurrent.Executor;
public class RcsUceAdapter {
    private static final String TAG = "RcsUceAdapter";

    /**
     * This carrier supports User Capability Exchange as, defined by the framework using
     * SIP OPTIONS. If set, the RcsFeature should support capability exchange. If not set, this
     * RcsFeature should not publish capabilities or service capability requests.
     * @hide
     */
    public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1 << 0;

    /**
     * This carrier supports User Capability Exchange as, defined by the framework using a
     * presence server. If set, the RcsFeature should support capability exchange. If not set, this
     * RcsFeature should not publish capabilities or service capability requests.
     * @hide
     */
    public static final int CAPABILITY_TYPE_PRESENCE_UCE = 1 << 1;

    /**@hide*/
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = "CAPABILITY_TYPE_", value = {
            CAPABILITY_TYPE_OPTIONS_UCE,
            CAPABILITY_TYPE_PRESENCE_UCE
    })
    public @interface RcsImsCapabilityFlag {}

    /**
     * An unknown error has caused the request to fail.
     * @hide
@@ -106,11 +130,6 @@ public class RcsUceAdapter {
     * @hide
     */
    public static final int ERROR_LOST_NETWORK = 12;
    /**
     * The request has failed because the same request has already been added to the queue.
     * @hide
     */
    public static final int ERROR_ALREADY_IN_QUEUE = 13;

    /**@hide*/
    @Retention(RetentionPolicy.SOURCE)
@@ -125,11 +144,89 @@ public class RcsUceAdapter {
            ERROR_REQUEST_TOO_LARGE,
            ERROR_REQUEST_TIMEOUT,
            ERROR_INSUFFICIENT_MEMORY,
            ERROR_LOST_NETWORK,
            ERROR_ALREADY_IN_QUEUE
            ERROR_LOST_NETWORK
    })
    public @interface ErrorCode {}

    /**
     * A capability update has been requested due to the Entity Tag (ETag) expiring.
     * @hide
     */
    public static final int CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED = 0;
    /**
     * A capability update has been requested due to moving to LTE with VoPS disabled.
     * @hide
     */
    public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED = 1;
    /**
     * A capability update has been requested due to moving to LTE with VoPS enabled.
     * @hide
     */
    public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED = 2;
    /**
     * A capability update has been requested due to moving to eHRPD.
     * @hide
     */
    public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD = 3;
    /**
     * A capability update has been requested due to moving to HSPA+.
     * @hide
     */
    public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS = 4;
    /**
     * A capability update has been requested due to moving to 3G.
     * @hide
     */
    public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G = 5;
    /**
     * A capability update has been requested due to moving to 2G.
     * @hide
     */
    public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G = 6;
    /**
     * A capability update has been requested due to moving to WLAN
     * @hide
     */
    public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN = 7;
    /**
     * A capability update has been requested due to moving to IWLAN
     * @hide
     */
    public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN = 8;
    /**
     * A capability update has been requested but the reason is unknown.
     * @hide
     */
    public static final int CAPABILITY_UPDATE_TRIGGER_UNKNOWN = 9;
    /**
     * A capability update has been requested due to moving to 5G NR with VoPS disabled.
     * @hide
     */
    public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED = 10;
    /**
     * A capability update has been requested due to moving to 5G NR with VoPS enabled.
     * @hide
     */
    public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED = 11;

    /**@hide*/
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = "ERROR_", value = {
            CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED,
            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED,
            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED,
            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD,
            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS,
            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G,
            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G,
            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN,
            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN,
            CAPABILITY_UPDATE_TRIGGER_UNKNOWN,
            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED,
            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED
    })
    public @interface StackPublishTriggerType {}

    /**
     * The last publish has resulted in a "200 OK" response or the device is using SIP OPTIONS for
     * UCE.
@@ -205,7 +302,7 @@ public class RcsUceAdapter {
            public void onPublishStateChanged(int publishState) {
                if (mLocalCallback == null) return;

                long callingIdentity = Binder.clearCallingIdentity();
                final long callingIdentity = Binder.clearCallingIdentity();
                try {
                    mExecutor.execute(() -> mLocalCallback.onChanged(publishState));
                } finally {
@@ -238,38 +335,49 @@ public class RcsUceAdapter {
    }

    /**
     * Provides a one-time callback for the response to a UCE request. After this callback is called
     * by the framework, the reference to this callback will be discarded on the service side.
     * A callback for the response to a UCE request. The method
     * {@link CapabilitiesCallback#onCapabilitiesReceived} will be called zero or more times as the
     * capabilities are received for each requested contact.
     * <p>
     * This request will take a varying amount of time depending on if the contacts requested are
     * cached or if it requires a network query. The timeout time of these requests can vary
     * depending on the network, however in poor cases it could take up to a minute for a request
     * to timeout. In that time only a subset of capabilities may have been retrieved.
     * <p>
     * After {@link CapabilitiesCallback#onComplete} or {@link CapabilitiesCallback#onError} has
     * been called, the reference to this callback will be discarded on the service side.
     * @see #requestCapabilities(Executor, List, CapabilitiesCallback)
     * @hide
     */
    public static class CapabilitiesCallback {
    public interface CapabilitiesCallback {

        /**
         * Notify this application that the pending capability request has returned successfully.
         * Notify this application that the pending capability request has returned successfully
         * for one or more of the requested contacts.
         * @param contactCapabilities List of capabilities associated with each contact requested.
         */
        public void onCapabilitiesReceived(
                @NonNull List<RcsContactUceCapability> contactCapabilities) {
        void onCapabilitiesReceived(@NonNull List<RcsContactUceCapability> contactCapabilities);

        }
        /**
         * The pending request has completed successfully due to all requested contacts information
         * being delivered.
         */
        void onComplete();

        /**
         * The pending request has resulted in an error and may need to be retried, depending on the
         * error code.
         * @param errorCode The reason for the framework being unable to process the request.
         */
        public void onError(@ErrorCode int errorCode) {

        }
        void onError(@ErrorCode int errorCode);
    }

    private final Context mContext;
    private final int mSubId;

    /**
     * Not to be instantiated directly, use
     * {@link ImsRcsManager#getUceAdapter()} to instantiate this manager class.
     * Not to be instantiated directly, use {@link ImsRcsManager#getUceAdapter()} to instantiate
     * this manager class.
     * @hide
     */
    RcsUceAdapter(Context context, int subId) {
@@ -280,6 +388,9 @@ public class RcsUceAdapter {
    /**
     * Request the User Capability Exchange capabilities for one or more contacts.
     * <p>
     * This will return the cached capabilities of the contact and will not perform a capability
     * poll on the network unless there are contacts being queried with stale information.
     * <p>
     * Be sure to check the availability of this feature using
     * {@link ImsRcsManager#isAvailable(int)} and ensuring
     * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} or
@@ -302,7 +413,7 @@ public class RcsUceAdapter {
            @NonNull List<Uri> contactNumbers,
            @NonNull CapabilitiesCallback c) throws ImsException {
        if (c == null) {
            throw new IllegalArgumentException("Must include a non-null AvailabilityCallback.");
            throw new IllegalArgumentException("Must include a non-null CapabilitiesCallback.");
        }
        if (executor == null) {
            throw new IllegalArgumentException("Must include a non-null Executor.");
@@ -321,7 +432,7 @@ public class RcsUceAdapter {
        IRcsUceControllerCallback internalCallback = new IRcsUceControllerCallback.Stub() {
            @Override
            public void onCapabilitiesReceived(List<RcsContactUceCapability> contactCapabilities) {
                long callingIdentity = Binder.clearCallingIdentity();
                final long callingIdentity = Binder.clearCallingIdentity();
                try {
                    executor.execute(() ->
                            c.onCapabilitiesReceived(contactCapabilities));
@@ -330,8 +441,17 @@ public class RcsUceAdapter {
                }
            }
            @Override
            public void onComplete() {
                final long callingIdentity = Binder.clearCallingIdentity();
                try {
                    executor.execute(() -> c.onComplete());
                } finally {
                    restoreCallingIdentity(callingIdentity);
                }
            }
            @Override
            public void onError(int errorCode) {
                long callingIdentity = Binder.clearCallingIdentity();
                final long callingIdentity = Binder.clearCallingIdentity();
                try {
                    executor.execute(() -> c.onError(errorCode));
                } finally {
@@ -350,6 +470,88 @@ public class RcsUceAdapter {
        }
    }

    /**
     * Ignore the device cache and perform a capability discovery for one contact, also called
     * "availability fetch."
     * <p>
     * This will always perform a query to the network as long as requests are over the carrier
     * availability fetch throttling threshold. If too many network requests are sent too quickly,
     * #ERROR_TOO_MANY_REQUESTS will be returned.
     *
     * <p>
     * Be sure to check the availability of this feature using
     * {@link ImsRcsManager#isAvailable(int)} and ensuring
     * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} or
     * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE} is
     * enabled or else this operation will fail with
     * {@link #ERROR_NOT_AVAILABLE} or {@link #ERROR_NOT_ENABLED}.
     *
     * @param contactNumber The contact of the capabilities is being requested for.
     * @param c A one-time callback for when the request for capabilities completes or there is
     * an error processing the request.
     * @hide
     */
    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
    public void requestNetworkAvailability(@NonNull @CallbackExecutor Executor executor,
            @NonNull Uri contactNumber, @NonNull CapabilitiesCallback c) throws ImsException {
        if (executor == null) {
            throw new IllegalArgumentException("Must include a non-null Executor.");
        }
        if (contactNumber == null) {
            throw new IllegalArgumentException("Must include non-null contact number.");
        }
        if (c == null) {
            throw new IllegalArgumentException("Must include a non-null CapabilitiesCallback.");
        }

        IImsRcsController imsRcsController = getIImsRcsController();
        if (imsRcsController == null) {
            Log.e(TAG, "requestNetworkAvailability: IImsRcsController is null");
            throw new ImsException("Cannot find remote IMS service",
                    ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
        }

        IRcsUceControllerCallback internalCallback = new IRcsUceControllerCallback.Stub() {
            @Override
            public void onCapabilitiesReceived(List<RcsContactUceCapability> contactCapabilities) {
                final long callingIdentity = Binder.clearCallingIdentity();
                try {
                    executor.execute(() ->
                            c.onCapabilitiesReceived(contactCapabilities));
                } finally {
                    restoreCallingIdentity(callingIdentity);
                }
            }
            @Override
            public void onComplete() {
                final long callingIdentity = Binder.clearCallingIdentity();
                try {
                    executor.execute(() -> c.onComplete());
                } finally {
                    restoreCallingIdentity(callingIdentity);
                }
            }
            @Override
            public void onError(int errorCode) {
                final long callingIdentity = Binder.clearCallingIdentity();
                try {
                    executor.execute(() -> c.onError(errorCode));
                } finally {
                    restoreCallingIdentity(callingIdentity);
                }
            }
        };

        try {
            imsRcsController.requestNetworkAvailability(mSubId, mContext.getOpPackageName(),
                    mContext.getAttributionTag(), contactNumber, internalCallback);
        } catch (RemoteException e) {
            Log.e(TAG, "Error calling IImsRcsController#requestNetworkAvailability", e);
            throw new ImsException("Remote IMS Service is not available",
                    ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
        }
    }

    /**
     * Gets the last publish result from the UCE service if the device is using an RCS presence
     * server.
+75 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.telephony.ims.aidl;

import android.net.Uri;
import android.telephony.ims.aidl.IOptionsRequestCallback;

import java.util.List;

/**
 * Listener interface for the ImsService to use to notify the framework of UCE events.
 * {@hide}
 */
oneway interface ICapabilityExchangeEventListener {
    /**
     * Trigger the framework to provide a capability update using
     * {@link RcsCapabilityExchangeImplBase#publishCapabilities}.
     * <p>
     * This is typically used when trying to generate an initial PUBLISH for a new
     * subscription to the network. The device will cache all presence publications
     * after boot until this method is called the first time.
     * @param publishTriggerType {@link StackPublishTriggerType} The reason for the
     * capability update request.
     * @throws ImsException If this {@link RcsPresenceExchangeImplBase} instance is
     * not currently connected to the framework. This can happen if the
     * {@link RcsFeature} is not {@link ImsFeature#STATE_READY} and the
     * {@link RcsFeature} has not received the
     * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare
     * cases when the Telephony stack has crashed.
     */
    void onRequestPublishCapabilities(int publishTriggerType);

    /**
     * Notify the framework that the device's capabilities have been unpublished from the network.
     *
     * @throws ImsException If this {@link RcsPresenceExchangeImplBase} instance is not currently
     * connected to the framework. This can happen if the {@link RcsFeature} is not
     * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the
     * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the
     * Telephony stack has crashed.
     */
    void onUnpublish();

    /**
     * Inform the framework of a query for this device's UCE capabilities.
     * <p>
     * The framework will respond via the
     * {@link IOptionsRequestCallback#respondToCapabilityRequest} or
     * {@link IOptionsRequestCallback#respondToCapabilityRequestWithError} method.
     * @param contactUri The URI associated with the remote contact that is requesting capabilities.
     * @param remoteCapabilities The remote contact's capability information.
     * @throws ImsException If this {@link RcsSipOptionsImplBase} instance is not currently
     * connected to the framework. This can happen if the {@link RcsFeature} is not
     * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received
     * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when
     * the Telephony stack has crashed.
     */
    void onRemoteCapabilityRequest(in Uri contactUri,
            in List<String> remoteCapabilities,
            IOptionsRequestCallback cb);
}
Loading