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

Commit 1ae4f53a authored by Brad Ebinger's avatar Brad Ebinger
Browse files

Integrate new MMTel APIs into the platform

Integrates the new ImsService APIs into telephony
and updates the Telephony unit tests to
test the new APIs as well.

Bug: 63987047
Test: Telephony unit tests; Telephony test ImsService
Merged-In: Iaf40fc2a14d2b8e99fb0d08284987c9cf9cd3b2c
Change-Id: Iaf40fc2a14d2b8e99fb0d08284987c9cf9cd3b2c
parent 420041b5
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -2294,8 +2294,14 @@ public class GsmCdmaPhone extends Phone {
                        config_switch_phone_on_voice_reg_state_change)) {
                    mCi.getVoiceRadioTechnology(obtainMessage(EVENT_REQUEST_VOICE_RADIO_TECH_DONE));
                }
                // Force update IMS service
                ImsManager.getInstance(mContext, mPhoneId).updateImsServiceConfig(true);
                // Force update IMS service if it is available, if it isn't the config will be
                // updated when ImsPhoneCallTracker opens a connection.
                ImsManager imsManager = ImsManager.getInstance(mContext, mPhoneId);
                if (imsManager.isServiceAvailable()) {
                    imsManager.updateImsServiceConfig(true);
                } else {
                    logd("ImsManager is not available to update CarrierConfig.");
                }

                // Update broadcastEmergencyCallStateChanges
                CarrierConfigManager configMgr = (CarrierConfigManager)
+15 −24
Original line number Diff line number Diff line
@@ -16,32 +16,22 @@

package com.android.internal.telephony;

import android.app.Activity;
import android.os.RemoteException;
import android.os.Message;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.provider.Telephony.Sms;
import android.content.Intent;
import android.telephony.Rlog;
import android.telephony.ims.aidl.IImsSmsListener;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.telephony.ims.stub.ImsSmsImplBase;
import android.telephony.ims.stub.ImsSmsImplBase.SendStatusResult;
import android.provider.Telephony.Sms.Intents;
import android.util.Pair;

import com.android.ims.ImsException;
import com.android.ims.ImsManager;
import com.android.ims.ImsServiceProxy;
import com.android.ims.internal.IImsSmsListener;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
import com.android.internal.telephony.util.SMSDispatcherUtil;
import com.android.internal.telephony.gsm.SmsMessage;

import android.telephony.ims.internal.feature.ImsFeature;
import android.telephony.ims.internal.feature.MmTelFeature;
import android.telephony.ims.internal.stub.SmsImplBase;
import android.telephony.ims.internal.stub.SmsImplBase.SendStatusResult;
import android.telephony.ims.internal.stub.SmsImplBase.StatusReportResult;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.provider.Telephony.Sms.Intents;
import android.util.Pair;

import java.util.HashMap;
import java.util.Map;
@@ -51,6 +41,7 @@ import java.util.concurrent.atomic.AtomicInteger;
/**
 * Responsible for communications with {@link com.android.ims.ImsManager} to send/receive messages
 * over IMS.
 * @hide
 */
public class ImsSmsDispatcher extends SMSDispatcher {
    // Initial condition for ims connection retry.
@@ -174,18 +165,18 @@ public class ImsSmsDispatcher extends SMSDispatcher {
                throw new IllegalArgumentException("Invalid token.");
            }
            switch(reason) {
                case SmsImplBase.SEND_STATUS_OK:
                case ImsSmsImplBase.SEND_STATUS_OK:
                    tracker.onSent(mContext);
                    break;
                case SmsImplBase.SEND_STATUS_ERROR:
                case ImsSmsImplBase.SEND_STATUS_ERROR:
                    tracker.onFailed(mContext, reason, 0 /* errorCode */);
                    mTrackers.remove(token);
                    break;
                case SmsImplBase.SEND_STATUS_ERROR_RETRY:
                case ImsSmsImplBase.SEND_STATUS_ERROR_RETRY:
                    tracker.mRetryCount += 1;
                    sendSms(tracker);
                    break;
                case SmsImplBase.SEND_STATUS_ERROR_FALLBACK:
                case ImsSmsImplBase.SEND_STATUS_ERROR_FALLBACK:
                    fallbackToPstn(token, tracker);
                    break;
                default:
@@ -208,8 +199,8 @@ public class ImsSmsDispatcher extends SMSDispatcher {
                getImsManager().acknowledgeSmsReport(
                        token,
                        messageRef,
                        result.first ? SmsImplBase.STATUS_REPORT_STATUS_OK
                                : SmsImplBase.STATUS_REPORT_STATUS_ERROR);
                        result.first ? ImsSmsImplBase.STATUS_REPORT_STATUS_OK
                                : ImsSmsImplBase.STATUS_REPORT_STATUS_ERROR);
            } catch (ImsException e) {
                Rlog.e(TAG, "Failed to acknowledgeSmsReport(). Error: "
                        + e.getMessage());
@@ -229,8 +220,8 @@ public class ImsSmsDispatcher extends SMSDispatcher {
                    getImsManager().acknowledgeSms(token,
                            0,
                            result == Intents.RESULT_SMS_HANDLED
                                    ? SmsImplBase.STATUS_REPORT_STATUS_OK
                                    : SmsImplBase.DELIVER_STATUS_ERROR);
                                    ? ImsSmsImplBase.STATUS_REPORT_STATUS_OK
                                    : ImsSmsImplBase.DELIVER_STATUS_ERROR);
                } catch (ImsException e) {
                    Rlog.e(TAG, "Failed to acknowledgeSms(). Error: " + e.getMessage());
                }
+76 −38
Original line number Diff line number Diff line
@@ -32,6 +32,10 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsMmTelFeature;
import android.telephony.ims.aidl.IImsRcsFeature;
import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.feature.ImsFeature;
import android.text.TextUtils;
import android.util.ArraySet;
@@ -39,9 +43,6 @@ import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;

import com.android.ims.internal.IImsMMTelFeature;
import com.android.ims.internal.IImsRcsFeature;
import com.android.ims.internal.IImsRegistration;
import com.android.ims.internal.IImsServiceFeatureCallback;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.PhoneConstants;
@@ -93,6 +94,7 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
    public static class ImsServiceInfo {
        public ComponentName name;
        public Set<Integer> supportedFeatures;
        public boolean supportsEmergencyMmTel = false;

        @Override
        public boolean equals(Object o) {
@@ -298,51 +300,62 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
    }

    /**
     * Returns the {@link IImsMMTelFeature} that corresponds to the given slot Id or {@link null} if
     * the service is not available. If an IImsMMTelFeature is available, the
     * {@link IImsServiceFeatureCallback} callback is registered as a listener for feature updates.
     * @param slotId The SIM slot that we are requesting the {@link IImsMMTelFeature} for.
     * @param callback Listener that will send updates to ImsManager when there are updates to
     * the feature.
     * @return {@link IImsMMTelFeature} interface or {@link null} if it is unavailable.
     * Notify ImsService to enable IMS for the framework. This will trigger IMS registration and
     * trigger ImsFeature status updates.
     */
    public IImsMMTelFeature getMMTelFeatureAndListen(int slotId,
            IImsServiceFeatureCallback callback) {
        ImsServiceController controller = getImsServiceControllerAndListen(slotId, ImsFeature.MMTEL,
                callback);
        return (controller != null) ? controller.getMMTelFeature(slotId) : null;
    public void enableIms(int slotId) {
        SparseArray<ImsServiceController> controllers = getImsServiceControllers(slotId);
        if (controllers != null) {
            for (int i = 0; i < controllers.size(); i++) {
                int key = controllers.keyAt(i);
                controllers.get(key).enableIms(slotId);
            }
        }
    }

    /**
     * Returns the {@link IImsMMTelFeature} that corresponds to the given slot Id for emergency
     * calling or {@link null} if the service is not available. If an IImsMMTelFeature is
     * available, the {@link IImsServiceFeatureCallback} callback is registered as a listener for
     * feature updates.
     * @param slotId The SIM slot that we are requesting the {@link IImsMMTelFeature} for.
     * @param callback listener that will send updates to ImsManager when there are updates to
     * Notify ImsService to disable IMS for the framework. This will trigger IMS de-registration and
     * trigger ImsFeature capability status to become false.
     */
    public void disableIms(int slotId) {
        SparseArray<ImsServiceController> controllers = getImsServiceControllers(slotId);
        if (controllers != null) {
            for (int i = 0; i < controllers.size(); i++) {
                int key = controllers.keyAt(i);
                controllers.get(key).disableIms(slotId);
            }
        }
    }

    /**
     * Returns the {@link IImsMmTelFeature} that corresponds to the given slot Id or {@link null} if
     * the service is not available. If an IImsMMTelFeature is available, the
     * {@link IImsServiceFeatureCallback} callback is registered as a listener for feature updates.
     * @param slotId The SIM slot that we are requesting the {@link IImsMmTelFeature} for.
     * @param callback Listener that will send updates to ImsManager when there are updates to
     * the feature.
     * @return {@link IImsMMTelFeature} interface or {@link null} if it is unavailable.
     * @return {@link IImsMmTelFeature} interface or {@link null} if it is unavailable.
     */
    public IImsMMTelFeature getEmergencyMMTelFeatureAndListen(int slotId,
    public IImsMmTelFeature getMmTelFeatureAndListen(int slotId,
            IImsServiceFeatureCallback callback) {
        ImsServiceController controller = getImsServiceControllerAndListen(slotId,
                ImsFeature.EMERGENCY_MMTEL, callback);
        return (controller != null) ? controller.getEmergencyMMTelFeature(slotId) : null;
                ImsFeature.FEATURE_MMTEL, callback);
        return (controller != null) ? controller.getMmTelFeature(slotId) : null;
    }

    /**
     * Returns the {@link IImsMMTelFeature} that corresponds to the given slot Id for emergency
     * Returns the {@link IImsRcsFeature} that corresponds to the given slot Id for emergency
     * calling or {@link null} if the service is not available. If an IImsMMTelFeature is
     * available, the {@link IImsServiceFeatureCallback} callback is registered as a listener for
     * feature updates.
     * @param slotId The SIM slot that we are requesting the {@link IImsMMTelFeature} for.
     * @param slotId The SIM slot that we are requesting the {@link IImsRcsFeature} for.
     * @param callback listener that will send updates to ImsManager when there are updates to
     * the feature.
     * @return {@link IImsMMTelFeature} interface or {@link null} if it is unavailable.
     * @return {@link IImsRcsFeature} interface or {@link null} if it is unavailable.
     */
    public IImsRcsFeature getRcsFeatureAndListen(int slotId, IImsServiceFeatureCallback callback) {
        ImsServiceController controller = getImsServiceControllerAndListen(slotId, ImsFeature.RCS,
                callback);
        ImsServiceController controller = getImsServiceControllerAndListen(slotId,
                ImsFeature.FEATURE_RCS, callback);
        return (controller != null) ? controller.getRcsFeature(slotId) : null;
    }

@@ -358,6 +371,18 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
        return null;
    }

    /**
     * Returns the ImsConfig structure associated with the slotId and feature specified.
     */
    public @Nullable IImsConfig getImsConfig(int slotId, int feature)
            throws RemoteException {
        ImsServiceController controller = getImsServiceController(slotId, feature);
        if (controller != null) {
            return controller.getConfig(slotId);
        }
        return null;
    }

    @VisibleForTesting
    public ImsServiceController getImsServiceController(int slotId, int feature) {
        if (slotId < 0 || slotId >= mNumSlots) {
@@ -374,6 +399,19 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
        return controller;
    }

    private  SparseArray<ImsServiceController> getImsServiceControllers(int slotId) {
        if (slotId < 0 || slotId >= mNumSlots) {
            return null;
        }
        synchronized (mBoundServicesLock) {
            SparseArray<ImsServiceController> services = mBoundImsServicesByFeature.get(slotId);
            if (services == null) {
                return null;
            }
            return services;
        }
    }

    @VisibleForTesting
    public ImsServiceController getImsServiceControllerAndListen(int slotId, int feature,
            IImsServiceFeatureCallback callback) {
@@ -387,8 +425,8 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
    }

    private void putImsController(int slotId, int feature, ImsServiceController controller) {
        if (slotId < 0 || slotId >= mNumSlots || feature <= ImsFeature.INVALID
                || feature >= ImsFeature.MAX) {
        if (slotId < 0 || slotId >= mNumSlots || feature <= ImsFeature.FEATURE_INVALID
                || feature >= ImsFeature.FEATURE_MAX) {
            Log.w(TAG, "putImsController received invalid parameters - slot: " + slotId
                    + ", feature: " + feature);
            return;
@@ -406,8 +444,8 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
    }

    private ImsServiceController removeImsController(int slotId, int feature) {
        if (slotId < 0 || slotId >= mNumSlots || feature <= ImsFeature.INVALID
                || feature >= ImsFeature.MAX) {
        if (slotId < 0 || slotId >= mNumSlots || feature <= ImsFeature.FEATURE_INVALID
                || feature >= ImsFeature.FEATURE_MAX) {
            Log.w(TAG, "removeImsController received invalid parameters - slot: " + slotId
                    + ", feature: " + feature);
            return null;
@@ -724,17 +762,17 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
            if (serviceInfo != null) {
                ImsServiceInfo info = new ImsServiceInfo();
                info.name = new ComponentName(serviceInfo.packageName, serviceInfo.name);
                info.supportedFeatures = new HashSet<>(ImsFeature.MAX);
                info.supportedFeatures = new HashSet<>(ImsFeature.FEATURE_MAX);
                // Add all supported features
                if (serviceInfo.metaData != null) {
                    if (serviceInfo.metaData.getBoolean(METADATA_EMERGENCY_MMTEL_FEATURE, false)) {
                        info.supportedFeatures.add(ImsFeature.EMERGENCY_MMTEL);
                        info.supportsEmergencyMmTel = true;
                    }
                    if (serviceInfo.metaData.getBoolean(METADATA_MMTEL_FEATURE, false)) {
                        info.supportedFeatures.add(ImsFeature.MMTEL);
                        info.supportedFeatures.add(ImsFeature.FEATURE_MMTEL);
                    }
                    if (serviceInfo.metaData.getBoolean(METADATA_RCS_FEATURE, false)) {
                        info.supportedFeatures.add(ImsFeature.RCS);
                        info.supportedFeatures.add(ImsFeature.FEATURE_RCS);
                    }
                }
                // Check manifest permission to be sure that the service declares the correct
+36 −28
Original line number Diff line number Diff line
@@ -27,15 +27,16 @@ import android.os.IBinder;
import android.os.IInterface;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsMmTelFeature;
import android.telephony.ims.aidl.IImsRcsFeature;
import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.aidl.IImsServiceController;
import android.telephony.ims.feature.ImsFeature;
import android.util.Log;
import android.util.Pair;

import com.android.ims.internal.IImsFeatureStatusCallback;
import com.android.ims.internal.IImsMMTelFeature;
import com.android.ims.internal.IImsRcsFeature;
import com.android.ims.internal.IImsRegistration;
import com.android.ims.internal.IImsServiceController;
import com.android.ims.internal.IImsServiceFeatureCallback;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.ExponentialBackoff;
@@ -421,33 +422,34 @@ public class ImsServiceController {
        }
    }

    /**
     * Return the {@Link MMTelFeature} binder on the slot associated with the slotId.
     * Used for normal calling.
     */
    public IImsMMTelFeature getMMTelFeature(int slotId) {
        synchronized (mLock) {
            ImsFeatureContainer f = getImsFeatureContainer(slotId, ImsFeature.MMTEL);
            if (f == null) {
                Log.w(LOG_TAG, "Requested null MMTelFeature on slot " + slotId);
                return null;
    public void enableIms(int slotId) {
        try {
            mIImsServiceController.enableIms(slotId);
        } catch (RemoteException e) {
            Log.w(LOG_TAG, "Couldn't enable IMS: " + e.getMessage());
        }
            return f.resolve(IImsMMTelFeature.class);
    }

    public void disableIms(int slotId) {
        try {
            mIImsServiceController.disableIms(slotId);
        } catch (RemoteException e) {
            Log.w(LOG_TAG, "Couldn't disable IMS: " + e.getMessage());
        }
    }

    /**
     * Return the {@Link MMTelFeature} binder on the slot associated with the slotId.
     * Used for emergency calling only.
     * Used for normal calling.
     */
    public IImsMMTelFeature getEmergencyMMTelFeature(int slotId) {
    public IImsMmTelFeature getMmTelFeature(int slotId) {
        synchronized (mLock) {
            ImsFeatureContainer f = getImsFeatureContainer(slotId, ImsFeature.EMERGENCY_MMTEL);
            ImsFeatureContainer f = getImsFeatureContainer(slotId, ImsFeature.FEATURE_MMTEL);
            if (f == null) {
                Log.w(LOG_TAG, "Requested null Emergency MMTelFeature on slot " + slotId);
                Log.w(LOG_TAG, "Requested null MMTelFeature on slot " + slotId);
                return null;
            }
            return f.resolve(IImsMMTelFeature.class);
            return f.resolve(IImsMmTelFeature.class);
        }
    }

@@ -456,7 +458,7 @@ public class ImsServiceController {
     */
    public IImsRcsFeature getRcsFeature(int slotId) {
        synchronized (mLock) {
            ImsFeatureContainer f = getImsFeatureContainer(slotId, ImsFeature.RCS);
            ImsFeatureContainer f = getImsFeatureContainer(slotId, ImsFeature.FEATURE_RCS);
            if (f == null) {
                Log.w(LOG_TAG, "Requested null RcsFeature on slot " + slotId);
                return null;
@@ -474,6 +476,15 @@ public class ImsServiceController {
        }
    }

    /**
     * @return the IImsConfig that corresponds to the slot id specified.
     */
    public IImsConfig getConfig(int slotId) throws RemoteException {
        synchronized (mLock) {
            return mIImsServiceController.getConfig(slotId);
        }
    }

    private void removeImsServiceFeatureListener() {
        synchronized (mLock) {
            mImsStatusCallbacks.clear();
@@ -598,13 +609,10 @@ public class ImsServiceController {
    private IInterface createImsFeature(int slotId, int featureType, IImsFeatureStatusCallback c)
            throws RemoteException {
        switch (featureType) {
            case ImsFeature.EMERGENCY_MMTEL: {
                return mIImsServiceController.createEmergencyMMTelFeature(slotId, c);
            }
            case ImsFeature.MMTEL: {
                return mIImsServiceController.createMMTelFeature(slotId, c);
            case ImsFeature.FEATURE_MMTEL: {
                return mIImsServiceController.createMmTelFeature(slotId, c);
            }
            case ImsFeature.RCS: {
            case ImsFeature.FEATURE_RCS: {
                return mIImsServiceController.createRcsFeature(slotId, c);
            }
            default:
+234 −253

File changed.

Preview size limit exceeded, changes collapsed.

Loading