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

Commit da39b57c authored by Brad Ebinger's avatar Brad Ebinger Committed by android-build-merger
Browse files

Create ImsService API compat layer am: 36b23d5f

am: 7fb771d5

Change-Id: I87dc3dac81338464b44791d4ab374666eaa93e46
parents d6346942 7fb771d5
Loading
Loading
Loading
Loading
+88 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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 com.android.internal.telephony.ims;

import android.os.RemoteException;
import android.telephony.ims.stub.ImsConfigImplBase;
import android.util.Log;

import com.android.ims.internal.IImsConfig;

public class ImsConfigCompatAdapter extends ImsConfigImplBase {

    private static final String TAG = "ImsConfigCompatAdapter";

    private final IImsConfig mOldConfigInterface;

    // Compat constants
    public static final int UNKNOWN = -1;
    public static final int SUCCESS = 0;
    public static final int FAILED =  1;

    public ImsConfigCompatAdapter(IImsConfig config) {
        mOldConfigInterface = config;
    }

    @Override
    public int setConfig(int item, int value) {
        try {
            if (mOldConfigInterface.setProvisionedValue(item, value) == SUCCESS) {
                return CONFIG_RESULT_SUCCESS;
            }
        } catch (RemoteException e) {
            Log.w(TAG, "setConfig: item=" + item + " value=" + value + "failed: "
                    + e.getMessage());
        }
        return CONFIG_RESULT_FAILED;
    }

    @Override
    public int setConfig(int item, String value) {
        try {
            if (mOldConfigInterface.setProvisionedStringValue(item, value) == SUCCESS) {
                return CONFIG_RESULT_SUCCESS;
            }
        } catch (RemoteException e) {
            Log.w(TAG, "setConfig: item=" + item + " value=" + value + "failed: "
                    + e.getMessage());
        }
        return CONFIG_RESULT_FAILED;
    }

    @Override
    public int getConfigInt(int item) {
        try {
            int value = mOldConfigInterface.getProvisionedValue(item);
            if (value != UNKNOWN) {
                return value;
            }
        } catch (RemoteException e) {
            Log.w(TAG, "getConfigInt: item=" + item + "failed: " + e.getMessage());
        }
        return CONFIG_RESULT_UNKNOWN;
    }

    @Override
    public String getConfigString(int item) {
        try {
            return mOldConfigInterface.getProvisionedStringValue(item);
        } catch (RemoteException e) {
            Log.w(TAG, "getConfigInt: item=" + item + "failed: " + e.getMessage());
        }
        return null;
    }
}
+114 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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 com.android.internal.telephony.ims;

import static android.telephony.ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN;
import static android.telephony.ServiceState.RIL_RADIO_TECHNOLOGY_LTE;

import android.net.Uri;
import android.os.RemoteException;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.util.ArrayMap;

import com.android.ims.internal.IImsRegistrationListener;

import java.util.Map;

public class ImsRegistrationCompatAdapter extends ImsRegistrationImplBase {

    // Maps "RAT" based radio technologies to ImsRegistrationImplBase definitions.
    private static final Map<Integer, Integer> RADIO_TECH_MAPPER = new ArrayMap<>(2);
    static {
        RADIO_TECH_MAPPER.put(RIL_RADIO_TECHNOLOGY_LTE, REGISTRATION_TECH_LTE);
        RADIO_TECH_MAPPER.put(RIL_RADIO_TECHNOLOGY_IWLAN, REGISTRATION_TECH_IWLAN);
    }

    // Trampolines "old" listener events to the new interface.
    private final IImsRegistrationListener mListener = new IImsRegistrationListener.Stub() {
        @Override
        public void registrationConnected() throws RemoteException {
            onRegistered(REGISTRATION_TECH_NONE);
        }

        @Override
        public void registrationProgressing() throws RemoteException {
            onRegistering(REGISTRATION_TECH_NONE);
        }

        @Override
        public void registrationConnectedWithRadioTech(int imsRadioTech) throws RemoteException {
            onRegistered(RADIO_TECH_MAPPER.getOrDefault(imsRadioTech, REGISTRATION_TECH_NONE));
        }

        @Override
        public void registrationProgressingWithRadioTech(int imsRadioTech) throws RemoteException {
            onRegistering(RADIO_TECH_MAPPER.getOrDefault(imsRadioTech, REGISTRATION_TECH_NONE));
        }

        @Override
        public void registrationDisconnected(ImsReasonInfo imsReasonInfo) throws RemoteException {
            onDeregistered(imsReasonInfo);
        }

        @Override
        public void registrationResumed() throws RemoteException {
            // Don't care
        }

        @Override
        public void registrationSuspended() throws RemoteException {
            // Don't care
        }

        @Override
        public void registrationServiceCapabilityChanged(int serviceClass, int event)
                throws RemoteException {
            // Don't care
        }

        @Override
        public void registrationFeatureCapabilityChanged(int serviceClass, int[] enabledFeatures,
                int[] disabledFeatures) throws RemoteException {
            // Implemented in the MMTel Adapter
        }

        @Override
        public void voiceMessageCountUpdate(int count) throws RemoteException {
            // Implemented in the MMTel Adapter
        }

        @Override
        public void registrationAssociatedUriChanged(Uri[] uris) throws RemoteException {
            onSubscriberAssociatedUriChanged(uris);
        }

        @Override
        public void registrationChangeFailed(int targetAccessTech, ImsReasonInfo imsReasonInfo)
                throws RemoteException {
            onTechnologyChangeFailed(RADIO_TECH_MAPPER.getOrDefault(targetAccessTech,
                    REGISTRATION_TECH_NONE), imsReasonInfo);
        }
    };

    /**
     * Need access to the listener in order to register for events in MMTelFeature adapter
     */
    public IImsRegistrationListener getRegistrationListener() {
        return mListener;
    }
}
+59 −13
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.ims.ImsService;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsMmTelFeature;
import android.telephony.ims.aidl.IImsRcsFeature;
@@ -73,7 +74,6 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal

    private static final String TAG = "ImsResolver";

    public static final String SERVICE_INTERFACE = "android.telephony.ims.ImsService";
    public static final String METADATA_EMERGENCY_MMTEL_FEATURE =
            "android.telephony.ims.EMERGENCY_MMTEL_FEATURE";
    public static final String METADATA_MMTEL_FEATURE = "android.telephony.ims.MMTEL_FEATURE";
@@ -95,6 +95,7 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
        public ComponentName name;
        public Set<Integer> supportedFeatures;
        public boolean supportsEmergencyMmTel = false;
        public ImsServiceControllerFactory controllerFactory;

        @Override
        public boolean equals(Object o) {
@@ -104,15 +105,19 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
            ImsServiceInfo that = (ImsServiceInfo) o;

            if (name != null ? !name.equals(that.name) : that.name != null) return false;
            return supportedFeatures != null ? supportedFeatures.equals(that.supportedFeatures)
                    : that.supportedFeatures == null;

            if (supportedFeatures != null ? !supportedFeatures.equals(that.supportedFeatures)
                    : that.supportedFeatures != null) {
                return false;
            }
            return controllerFactory != null ? controllerFactory.equals(that.controllerFactory)
                    : that.controllerFactory == null;
        }

        @Override
        public int hashCode() {
            int result = name != null ? name.hashCode() : 0;
            result = 31 * result + (supportedFeatures != null ? supportedFeatures.hashCode() : 0);
            result = 31 * result + (controllerFactory != null ? controllerFactory.hashCode() : 0);
            return result;
        }
    }
@@ -197,14 +202,44 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
    @VisibleForTesting
    public interface ImsServiceControllerFactory {
        /**
         * Returns the ImsServiceController created usiing the context and componentName supplied.
         * Used for DI when testing.
         * @return the Service Interface String used for binding the ImsService.
         */
        ImsServiceController get(Context context, ComponentName componentName);
        String getServiceInterface();
        /**
         * @return the ImsServiceController created using the context and componentName supplied.
         */
        ImsServiceController create(Context context, ComponentName componentName,
                ImsServiceController.ImsServiceControllerCallbacks callbacks);
    }

    private ImsServiceControllerFactory mImsServiceControllerFactory =
            new ImsServiceControllerFactory() {

        @Override
        public String getServiceInterface() {
            return ImsService.SERVICE_INTERFACE;
        }

    private ImsServiceControllerFactory mImsServiceControllerFactory = (context, componentName) ->
            new ImsServiceController(context, componentName, this);
        @Override
        public ImsServiceController create(Context context, ComponentName componentName,
                ImsServiceController.ImsServiceControllerCallbacks callbacks) {
            return new ImsServiceController(context, componentName, callbacks);
        }
    };

    private ImsServiceControllerFactory mImsServiceControllerFactoryCompat =
            new ImsServiceControllerFactory() {
                @Override
                public String getServiceInterface() {
                    return android.telephony.ims.compat.ImsService.SERVICE_INTERFACE;
                }

                @Override
                public ImsServiceController create(Context context, ComponentName componentName,
                        ImsServiceController.ImsServiceControllerCallbacks callbacks) {
                    return new ImsServiceControllerCompat(context, componentName, callbacks);
                }
            };

    private final CarrierConfigManager mCarrierConfigManager;
    private final Context mContext;
@@ -606,7 +641,7 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
        if (info == null) {
            return;
        }
        ImsServiceController controller = mImsServiceControllerFactory.get(mContext, info.name);
        ImsServiceController controller = info.controllerFactory.create(mContext, info.name, this);
        HashSet<Pair<Integer, Integer>> features = calculateFeaturesToCreate(info);
        // Only bind if there are features that will be created by the service.
        if (features.size() > 0) {
@@ -748,8 +783,18 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
    // get all packages that support ImsServices.
    private List<ImsServiceInfo> getImsServiceInfo(String packageName) {
        List<ImsServiceInfo> infos = new ArrayList<>();
        // Search for Current ImsService implementations
        infos.addAll(searchForImsServices(packageName, mImsServiceControllerFactory));
        // Search for compat ImsService Implementations
        infos.addAll(searchForImsServices(packageName, mImsServiceControllerFactoryCompat));
        return infos;
    }

    private List<ImsServiceInfo> searchForImsServices(String packageName,
            ImsServiceControllerFactory controllerFactory) {
        List<ImsServiceInfo> infos = new ArrayList<>();

        Intent serviceIntent = new Intent(SERVICE_INTERFACE);
        Intent serviceIntent = new Intent(controllerFactory.getServiceInterface());
        serviceIntent.setPackage(packageName);

        PackageManager packageManager = mContext.getPackageManager();
@@ -763,6 +808,7 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
                ImsServiceInfo info = new ImsServiceInfo();
                info.name = new ComponentName(serviceInfo.packageName, serviceInfo.name);
                info.supportedFeatures = new HashSet<>(ImsFeature.FEATURE_MAX);
                info.controllerFactory = controllerFactory;
                // Add all supported features
                if (serviceInfo.metaData != null) {
                    if (serviceInfo.metaData.getBoolean(METADATA_EMERGENCY_MMTEL_FEATURE, false)) {
@@ -779,8 +825,8 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
                // permissions.
                if (TextUtils.equals(serviceInfo.permission,
                        Manifest.permission.BIND_IMS_SERVICE)) {
                    Log.d(TAG, "ImsService added to cache: " + info.name + " with features: "
                            + info.supportedFeatures);
                    Log.d(TAG, "ImsService (" + serviceIntent + ") added to cache: "
                            + info.name + " with features: " + info.supportedFeatures);
                    infos.add(info);
                } else {
                    Log.w(TAG, "ImsService does not have BIND_IMS_SERVICE permission: "
+40 −11
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.os.IBinder;
import android.os.IInterface;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.ims.ImsService;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsMmTelFeature;
import android.telephony.ims.aidl.IImsRcsFeature;
@@ -95,7 +96,7 @@ public class ImsServiceController {
                    try {
                        service.linkToDeath(mImsDeathRecipient, 0);
                        mImsServiceControllerBinder = service;
                        mIImsServiceController = IImsServiceController.Stub.asInterface(service);
                        setServiceController(service);
                        // create all associated features in the ImsService
                        for (Pair<Integer, Integer> i : mImsFeatures) {
                            addImsServiceFeature(i);
@@ -119,7 +120,7 @@ public class ImsServiceController {
            synchronized (mLock) {
                mIsBinding = false;
            }
            if (mIImsServiceController != null) {
            if (isServiceControllerAvailable()) {
                mImsServiceControllerBinder.unlinkToDeath(mImsDeathRecipient, 0);
            }
            notifyAllFeaturesRemoved();
@@ -165,9 +166,7 @@ public class ImsServiceController {
    private static final String LOG_TAG = "ImsServiceController";
    private static final int REBIND_START_DELAY_MS = 2 * 1000; // 2 seconds
    private static final int REBIND_MAXIMUM_DELAY_MS = 60 * 1000; // 1 minute
    private final Context mContext;
    private final ComponentName mComponentName;
    private final Object mLock = new Object();
    private final HandlerThread mHandlerThread = new HandlerThread("ImsServiceControllerHandler");
    private final IPackageManager mPackageManager;
    private ImsServiceControllerCallbacks mCallbacks;
@@ -188,6 +187,9 @@ public class ImsServiceController {
    // Only added or removed, never accessed on purpose.
    private Set<ImsFeatureStatusCallback> mFeatureStatusCallbacks = new HashSet<>();

    protected final Object mLock = new Object();
    protected final Context mContext;

    private class ImsFeatureContainer {
        public int slotId;
        public int featureType;
@@ -325,7 +327,7 @@ public class ImsServiceController {
            if (!mIsBound && !mIsBinding) {
                mIsBinding = true;
                mImsFeatures = imsFeatureSet;
                Intent imsServiceIntent = new Intent(ImsResolver.SERVICE_INTERFACE).setComponent(
                Intent imsServiceIntent = new Intent(getServiceInterface()).setComponent(
                        mComponentName);
                mImsServiceConnection = new ImsServiceConnection();
                int serviceFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
@@ -485,6 +487,26 @@ public class ImsServiceController {
        }
    }

    protected String getServiceInterface() {
        return ImsService.SERVICE_INTERFACE;
    }

    /**
     * Sets the IImsServiceController instance. Overridden by compat layers to set compatibility
     * versions of this service controller.
     */
    protected void setServiceController(IBinder serviceController) {
        mIImsServiceController = IImsServiceController.Stub.asInterface(serviceController);
    }

    /**
     * Check to see if the service controller is available, overridden for compat versions,
     * @return true if available, false otherwise;
     */
    protected boolean isServiceControllerAvailable() {
        return mIImsServiceController != null;
    }

    private void removeImsServiceFeatureListener() {
        synchronized (mLock) {
            mImsStatusCallbacks.clear();
@@ -564,7 +586,7 @@ public class ImsServiceController {

    // This method should only be called when synchronized on mLock
    private void addImsServiceFeature(Pair<Integer, Integer> featurePair) throws RemoteException {
        if (mIImsServiceController == null || mCallbacks == null) {
        if (!isServiceControllerAvailable() || mCallbacks == null) {
            Log.w(LOG_TAG, "addImsServiceFeature called with null values.");
            return;
        }
@@ -582,7 +604,7 @@ public class ImsServiceController {
    // This method should only be called when synchronized on mLock
    private void removeImsServiceFeature(Pair<Integer, Integer> featurePair)
            throws RemoteException {
        if (mIImsServiceController == null || mCallbacks == null) {
        if (!isServiceControllerAvailable() || mCallbacks == null) {
            Log.w(LOG_TAG, "removeImsServiceFeature called with null values.");
            return;
        }
@@ -593,7 +615,7 @@ public class ImsServiceController {
        if (callbackToRemove != null) {
            mFeatureStatusCallbacks.remove(callbackToRemove);
        }
        mIImsServiceController.removeImsFeature(featurePair.first, featurePair.second,
        removeImsFeature(featurePair.first, featurePair.second,
                (callbackToRemove != null ? callbackToRemove.getCallback() : null));
        removeImsFeatureBinder(featurePair.first, featurePair.second);
        // Signal ImsResolver to change supported ImsFeatures for this ImsServiceController
@@ -605,8 +627,9 @@ public class ImsServiceController {
        sendImsFeatureRemovedCallback(featurePair.first, featurePair.second);
    }

    // This method should only be called when already synchronized on mLock;
    private IInterface createImsFeature(int slotId, int featureType, IImsFeatureStatusCallback c)
    // This method should only be called when already synchronized on mLock.
    // overridden by compat layer to create features
    protected IInterface createImsFeature(int slotId, int featureType, IImsFeatureStatusCallback c)
            throws RemoteException {
        switch (featureType) {
            case ImsFeature.FEATURE_MMTEL: {
@@ -620,6 +643,12 @@ public class ImsServiceController {
        }
    }

    // overridden by compat layer to remove features
    protected void removeImsFeature(int slotId, int featureType, IImsFeatureStatusCallback c)
            throws RemoteException {
        mIImsServiceController.removeImsFeature(slotId, featureType, c);
    }

    // This method should only be called when synchronized on mLock
    private void addImsFeatureBinder(int slotId, int featureType, IInterface b) {
        mImsFeatureBinders.add(new ImsFeatureContainer(slotId, featureType, b));
@@ -659,7 +688,7 @@ public class ImsServiceController {
            mImsDeathRecipient = null;
            mImsServiceConnection = null;
            mImsServiceControllerBinder = null;
            mIImsServiceController = null;
            setServiceController(null);
            mIsBound = false;
        }
    }
+185 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading