diff options
7 files changed, 329 insertions, 0 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 70b89b8af044..1b732cc8c8b0 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -13125,6 +13125,7 @@ package android.telephony {      field public static final int PRECISE_CALL_STATE_HOLDING = 2; // 0x2      field public static final int PRECISE_CALL_STATE_IDLE = 0; // 0x0      field public static final int PRECISE_CALL_STATE_INCOMING = 5; // 0x5 +    field public static final int PRECISE_CALL_STATE_INCOMING_SETUP = 9; // 0x9      field public static final int PRECISE_CALL_STATE_NOT_VALID = -1; // 0xffffffff      field public static final int PRECISE_CALL_STATE_WAITING = 6; // 0x6    } @@ -15380,6 +15381,16 @@ package android.telephony.ims {      field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.SipMessage> CREATOR;    } +  public final class SrvccCall implements android.os.Parcelable { +    ctor public SrvccCall(@NonNull String, int, @NonNull android.telephony.ims.ImsCallProfile); +    method public int describeContents(); +    method @NonNull public String getCallId(); +    method @NonNull public android.telephony.ims.ImsCallProfile getImsCallProfile(); +    method public int getPreciseCallState(); +    method public void writeToParcel(@NonNull android.os.Parcel, int); +    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.SrvccCall> CREATOR; +  } +  }  package android.telephony.ims.feature { @@ -15440,6 +15451,10 @@ package android.telephony.ims.feature {      method public final void notifyCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities);      method public final void notifyIncomingCall(@NonNull android.telephony.ims.stub.ImsCallSessionImplBase, @NonNull android.os.Bundle);      method public final void notifyRejectedCall(@NonNull android.telephony.ims.ImsCallProfile, @NonNull android.telephony.ims.ImsReasonInfo); +    method public void notifySrvccCanceled(); +    method public void notifySrvccCompleted(); +    method public void notifySrvccFailed(); +    method public void notifySrvccStarted(@NonNull java.util.function.Consumer<java.util.List<android.telephony.ims.SrvccCall>>);      method public final void notifyVoiceMessageCountUpdate(int);      method public void onFeatureReady();      method public void onFeatureRemoved(); diff --git a/telephony/java/android/telephony/PreciseCallState.java b/telephony/java/android/telephony/PreciseCallState.java index 98eeacf1a416..d4b912e76b2d 100644 --- a/telephony/java/android/telephony/PreciseCallState.java +++ b/telephony/java/android/telephony/PreciseCallState.java @@ -66,6 +66,11 @@ public final class PreciseCallState implements Parcelable {      public static final int PRECISE_CALL_STATE_DISCONNECTED =   7;      /** Call state: Disconnecting. */      public static final int PRECISE_CALL_STATE_DISCONNECTING =  8; +    /** +     * Call state: Incoming in pre-alerting state. +     * A call will be in this state prior to entering {@link #PRECISE_CALL_STATE_ALERTING}. +     */ +    public static final int PRECISE_CALL_STATE_INCOMING_SETUP = 9;      private @PreciseCallStates int mRingingCallState = PRECISE_CALL_STATE_NOT_VALID;      private @PreciseCallStates int mForegroundCallState = PRECISE_CALL_STATE_NOT_VALID; diff --git a/telephony/java/android/telephony/ims/SrvccCall.aidl b/telephony/java/android/telephony/ims/SrvccCall.aidl new file mode 100644 index 000000000000..0f0a0795cb2e --- /dev/null +++ b/telephony/java/android/telephony/ims/SrvccCall.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2022 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 SrvccCall; diff --git a/telephony/java/android/telephony/ims/SrvccCall.java b/telephony/java/android/telephony/ims/SrvccCall.java new file mode 100644 index 000000000000..cdc271ec8070 --- /dev/null +++ b/telephony/java/android/telephony/ims/SrvccCall.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2022 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.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.telephony.Annotation.PreciseCallStates; + +import java.util.Objects; + +/** + * A Parcelable object to represent the current state of an IMS call that is being tracked + * in the ImsService when an SRVCC begins. This information will be delivered to modem. + * @see SrvccStartedCallback + * + * @hide + */ +@SystemApi +public final class SrvccCall implements Parcelable { +    private static final String TAG = "SrvccCall"; + +    /** The IMS call profile */ +    private ImsCallProfile mImsCallProfile; + +    /** The IMS call id */ +    private String mCallId; + +    /** The call state */ +    private @PreciseCallStates int mCallState; + +    private SrvccCall(Parcel in) { +        readFromParcel(in); +    } + +    /** +     * Constructs an instance of SrvccCall. +     * +     * @param callId the call ID associated with the IMS call +     * @param callState the state of this IMS call +     * @param imsCallProfile the profile associated with this IMS call +     * @throws IllegalArgumentException if the callId or the imsCallProfile is null +     */ +    public SrvccCall(@NonNull String callId, @PreciseCallStates int callState, +            @NonNull ImsCallProfile imsCallProfile) { +        if (callId == null) throw new IllegalArgumentException("callId is null"); +        if (imsCallProfile == null) throw new IllegalArgumentException("imsCallProfile is null"); + +        mCallId = callId; +        mCallState = callState; +        mImsCallProfile = imsCallProfile; +    } + +    /** +     * @return the {@link ImsCallProfile} associated with this IMS call, +     * which will be used to get the address, the name, and the audio direction +     * including the call in pre-alerting state. +     */ +    @NonNull +    public ImsCallProfile getImsCallProfile() { +        return mImsCallProfile; +    } + +    /** +     * @return the call ID associated with this IMS call. +     * +     * @see android.telephony.ims.stub.ImsCallSessionImplBase#getCallId(). +     */ +    @NonNull +    public String getCallId() { +        return mCallId; +    } + +    /** +     * @return the call state of the associated IMS call. +     */ +    public @PreciseCallStates int getPreciseCallState() { +        return mCallState; +    } + +    @NonNull +    @Override +    public String toString() { +        return "{ callId=" + mCallId +                + ", callState=" + mCallState +                + ", imsCallProfile=" + mImsCallProfile +                + " }"; +    } + +    @Override +    public boolean equals(Object o) { +        if (this == o) return true; +        if (o == null || getClass() != o.getClass()) return false; +        SrvccCall that = (SrvccCall) o; +        return mImsCallProfile.equals(that.mImsCallProfile) +                && mCallId.equals(that.mCallId) +                && mCallState == that.mCallState; +    } + +    @Override +    public int hashCode() { +        int result = Objects.hash(mImsCallProfile, mCallId); +        result = 31 * result + mCallState; +        return result; +    } + +    @Override +    public int describeContents() { +        return 0; +    } + +    @Override +    public void writeToParcel(@NonNull Parcel out, int flags) { +        out.writeString(mCallId); +        out.writeInt(mCallState); +        out.writeParcelable(mImsCallProfile, 0); +    } + +    private void readFromParcel(Parcel in) { +        mCallId = in.readString(); +        mCallState = in.readInt(); +        mImsCallProfile = in.readParcelable(ImsCallProfile.class.getClassLoader(), +                android.telephony.ims.ImsCallProfile.class); +    } + +    public static final @android.annotation.NonNull Creator<SrvccCall> CREATOR = +            new Creator<SrvccCall>() { +        @Override +        public SrvccCall createFromParcel(Parcel in) { +            return new SrvccCall(in); +        } + +        @Override +        public SrvccCall[] newArray(int size) { +            return new SrvccCall[size]; +        } +    }; +} diff --git a/telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl b/telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl index 801b81c0e498..85191734872a 100644 --- a/telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl @@ -20,6 +20,7 @@ import android.os.Message;  import android.telephony.ims.aidl.IImsMmTelListener;  import android.telephony.ims.aidl.IImsSmsListener;  import android.telephony.ims.aidl.IImsCapabilityCallback; +import android.telephony.ims.aidl.ISrvccStartedCallback;  import android.telephony.ims.feature.CapabilityChangeRequest;  import android.telephony.ims.RtpHeaderExtensionType; @@ -55,6 +56,10 @@ interface IImsMmTelFeature {              IImsCapabilityCallback c);      oneway void queryCapabilityConfiguration(int capability, int radioTech,              IImsCapabilityCallback c); +    oneway void notifySrvccStarted(in ISrvccStartedCallback cb); +    oneway void notifySrvccCompleted(); +    oneway void notifySrvccFailed(); +    oneway void notifySrvccCanceled();      // SMS APIs      void setSmsListener(IImsSmsListener l);      oneway void sendSms(in int token, int messageRef, String format, String smsc, boolean retry, diff --git a/telephony/java/android/telephony/ims/aidl/ISrvccStartedCallback.aidl b/telephony/java/android/telephony/ims/aidl/ISrvccStartedCallback.aidl new file mode 100644 index 000000000000..a173abffbb8f --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/ISrvccStartedCallback.aidl @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 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.telephony.ims.SrvccCall; + +import java.util.List; + +/** + * {@hide} + */ +oneway interface ISrvccStartedCallback { +    void onSrvccCallNotified(in List<SrvccCall> profiles); +} diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java index c0ff12efb3c2..8147759769e6 100644 --- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java +++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java @@ -31,10 +31,12 @@ import android.telephony.ims.ImsException;  import android.telephony.ims.ImsReasonInfo;  import android.telephony.ims.ImsService;  import android.telephony.ims.RtpHeaderExtensionType; +import android.telephony.ims.SrvccCall;  import android.telephony.ims.aidl.IImsCapabilityCallback;  import android.telephony.ims.aidl.IImsMmTelFeature;  import android.telephony.ims.aidl.IImsMmTelListener;  import android.telephony.ims.aidl.IImsSmsListener; +import android.telephony.ims.aidl.ISrvccStartedCallback;  import android.telephony.ims.stub.ImsCallSessionImplBase;  import android.telephony.ims.stub.ImsEcbmImplBase;  import android.telephony.ims.stub.ImsMultiEndpointImplBase; @@ -60,6 +62,7 @@ import java.util.concurrent.CompletionException;  import java.util.concurrent.ExecutionException;  import java.util.concurrent.Executor;  import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer;  import java.util.function.Supplier;  /** @@ -289,6 +292,38 @@ public class MmTelFeature extends ImsFeature {                      "onSmsReady");          } +        @Override +        public void notifySrvccStarted(final ISrvccStartedCallback cb) { +            executeMethodAsyncNoException( +                    () -> MmTelFeature.this.notifySrvccStarted( +                            (profiles) -> { +                                try { +                                    cb.onSrvccCallNotified(profiles); +                                } catch (Exception e) { +                                    Log.e(LOG_TAG, "onSrvccCallNotified e=" + e); +                                } +                            }), +                    "notifySrvccStarted"); +        } + +        @Override +        public void notifySrvccCompleted() { +            executeMethodAsyncNoException( +                    () -> MmTelFeature.this.notifySrvccCompleted(), "notifySrvccCompleted"); +        } + +        @Override +        public void notifySrvccFailed() { +            executeMethodAsyncNoException( +                    () -> MmTelFeature.this.notifySrvccFailed(), "notifySrvccFailed"); +        } + +        @Override +        public void notifySrvccCanceled() { +            executeMethodAsyncNoException( +                    () -> MmTelFeature.this.notifySrvccCanceled(), "notifySrvccCanceled"); +        } +          // Call the methods with a clean calling identity on the executor and wait indefinitely for          // the future to return.          private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException { @@ -969,6 +1004,75 @@ public class MmTelFeature extends ImsFeature {                  "Not implemented on device.");      } +    /** +     * Notifies the MmTelFeature that the network has initiated an SRVCC (Single radio voice +     * call continuity) for all IMS calls. When the network initiates an SRVCC, calls from +     * the LTE domain are handed over to the legacy circuit switched domain. The modem requires +     * knowledge of ongoing calls in the IMS domain in order to complete the SRVCC operation. +     * <p> +     * @param consumer The callback used to notify the framework of the list of IMS calls and their +     * state at the time of the SRVCC. +     * +     * @hide +     */ +    @SystemApi +    public void notifySrvccStarted(@NonNull Consumer<List<SrvccCall>> consumer) { +        // Base Implementation - Should be overridden by IMS service +    } + +    /** +     * Notifies the MmTelFeature that the SRVCC is completed and the calls have been moved +     * over to the circuit-switched domain. +     * {@link android.telephony.CarrierConfigManager.ImsVoice#KEY_SRVCC_TYPE_INT_ARRAY} +     * specifies the calls can be moved. Other calls will be disconnected. +     * <p> +     * The MmTelFeature may now release all resources related to the IMS calls. +     * +     * @hide +     */ +    @SystemApi +    public void notifySrvccCompleted() { +        // Base Implementation - Should be overridden by IMS service +    } + +    /** +     * Notifies the MmTelFeature that the SRVCC has failed. +     * +     * The handover can fail by encountering a failure at the radio level +     * or temporary MSC server internal errors in handover procedure. +     * Refer to 3GPP TS 23.216 section 8 Handover Failure. +     * <p> +     * IMS service will recover and continue calls over IMS. +     * Per TS 24.237 12.2.4.2, UE shall send SIP UPDATE request containing the reason-text +     * set to "failure to transition to CS domain". +     * +     * @hide +     */ +    @SystemApi +    public void notifySrvccFailed() { +        // Base Implementation - Should be overridden by IMS service +    } + +    /** +     * Notifies the MmTelFeature that the SRVCC has been canceled. +     * +     * Since the state of network can be changed, the network can decide to terminate +     * the handover procedure before its completion and to return to its state before the handover +     * procedure was triggered. +     * Refer to 3GPP TS 23.216 section 8.1.3 Handover Cancellation. +     * +     * <p> +     * IMS service will recover and continue calls over IMS. +     * Per TS 24.237 12.2.4.2, UE shall send SIP UPDATE request containing the reason-text +     * set to "handover canceled". +     * +     * @hide +     */ +    @SystemApi +    public void notifySrvccCanceled() { +        // Base Implementation - Should be overridden by IMS service +    } +      private void setSmsListener(IImsSmsListener listener) {          getSmsImplementation().registerSmsListener(listener);      }  |