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

Commit 0cd54345 authored by Brad Ebinger's avatar Brad Ebinger
Browse files

Adds compat layer for older devices when IMS binding

Modifies the ImsResolver to support binding to older
IMS implementations that use the ServiceManager
to expose IMS implementation.

Bug: 63987047
Test: Telephony Unit Tests
Merged-In: I4d7ccbad9f4aed310af92f4832e51ec6bbeec27d
Change-Id: I4d7ccbad9f4aed310af92f4832e51ec6bbeec27d
parent 36b23d5f
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -150,11 +150,17 @@ public class PhoneFactory {
                   where as in single SIM mode only instance. isMultiSimEnabled() function checks
                   whether it is single SIM or multi SIM mode */
                int numPhones = TelephonyManager.getDefault().getPhoneCount();
                // Start ImsResolver and bind to ImsServices.
                // Return whether or not the device should use dynamic binding or the static
                // implementation (deprecated)
                boolean isDynamicBinding = sContext.getResources().getBoolean(
                        com.android.internal.R.bool.config_dynamic_bind_ims);
                // Get the package name of the default IMS implementation.
                String defaultImsPackage = sContext.getResources().getString(
                        com.android.internal.R.string.config_ims_package);
                // Start ImsResolver and bind to ImsServices.
                Rlog.i(LOG_TAG, "ImsResolver: defaultImsPackage: " + defaultImsPackage);
                sImsResolver = new ImsResolver(sContext, defaultImsPackage, numPhones);
                sImsResolver = new ImsResolver(sContext, defaultImsPackage, numPhones,
                        isDynamicBinding);
                sImsResolver.populateCacheAndStartBind();

                int[] networkModes = new int[numPhones];
+61 −15
Original line number Diff line number Diff line
@@ -241,12 +241,28 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
                }
            };

    private ImsServiceControllerFactory mImsServiceControllerFactoryStaticBindingCompat =
            new ImsServiceControllerFactory() {
                @Override
                public String getServiceInterface() {
                    // The static method of binding does not use service interfaces.
                    return null;
                }

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

    private final CarrierConfigManager mCarrierConfigManager;
    private final Context mContext;
    // Locks mBoundImsServicesByFeature only. Be careful to avoid deadlocks from
    // ImsServiceController callbacks.
    private final Object mBoundServicesLock = new Object();
    private final int mNumSlots;
    private final boolean mIsDynamicBinding;

    // Synchronize all messages on a handler to ensure that the cache includes the most recent
    // version of the installed ImsServices.
@@ -284,28 +300,41 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
    private Set<ImsServiceInfo> mInstalledServicesCache = new ArraySet<>();
    // not locked, only accessed on a handler thread.
    private Set<ImsServiceController> mActiveControllers = new ArraySet<>();
    // Only used as the
    private final ComponentName mStaticComponent;

    public ImsResolver(Context context, String defaultImsPackageName, int numSlots) {
    public ImsResolver(Context context, String defaultImsPackageName, int numSlots,
            boolean isDynamicBinding) {
        mContext = context;
        mDeviceService = defaultImsPackageName;
        mNumSlots = numSlots;
        mIsDynamicBinding = isDynamicBinding;
        mStaticComponent = new ComponentName(mContext, ImsResolver.class);
        if (!mIsDynamicBinding) {
            Log.i(TAG, "ImsResolver initialized with static binding.");
            mDeviceService = mStaticComponent.getPackageName();
        }
        mCarrierConfigManager = (CarrierConfigManager) mContext.getSystemService(
                Context.CARRIER_CONFIG_SERVICE);
        mCarrierServices = new String[numSlots];
        mBoundImsServicesByFeature = Stream.generate(SparseArray<ImsServiceController>::new)
                .limit(mNumSlots).collect(Collectors.toList());

        // Only register for Package/CarrierConfig updates if dynamic binding.
        if(mIsDynamicBinding) {
            IntentFilter appChangedFilter = new IntentFilter();
            appChangedFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
            appChangedFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
            appChangedFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
            appChangedFilter.addDataScheme("package");
        context.registerReceiverAsUser(mAppChangedReceiver, UserHandle.ALL, appChangedFilter, null,
            context.registerReceiverAsUser(mAppChangedReceiver, UserHandle.ALL, appChangedFilter,
                    null,
                    null);

            context.registerReceiver(mConfigChangedReceiver, new IntentFilter(
                    CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
        }
    }

    @VisibleForTesting
    public void setSubscriptionManagerProxy(SubscriptionManagerProxy proxy) {
@@ -500,7 +529,6 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
        }
    }


    // Update the current cache with the new ImsService(s) if it has been added or update the
    // supported IMS features if they have changed.
    // Called from the handler ONLY
@@ -783,10 +811,28 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
    // get all packages that support ImsServices.
    private List<ImsServiceInfo> getImsServiceInfo(String packageName) {
        List<ImsServiceInfo> infos = new ArrayList<>();
        if (!mIsDynamicBinding) {
            // always return the same ImsService info.
            infos.addAll(getStaticImsService());
        } else {
            // 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> getStaticImsService() {
        List<ImsServiceInfo> infos = new ArrayList<>();

        ImsServiceInfo info = new ImsServiceInfo();
        info.name = mStaticComponent;
        info.supportedFeatures = new HashSet<>(ImsFeature.FEATURE_MAX);
        info.controllerFactory = mImsServiceControllerFactoryStaticBindingCompat;
        info.supportsEmergencyMmTel = true;
        info.supportedFeatures.add(ImsFeature.FEATURE_MMTEL);
        infos.add(info);
        return infos;
    }

+15 −2
Original line number Diff line number Diff line
@@ -334,8 +334,12 @@ public class ImsServiceController {
                        | Context.BIND_IMPORTANT;
                Log.i(LOG_TAG, "Binding ImsService:" + mComponentName);
                try {
                    return mContext.bindService(imsServiceIntent, mImsServiceConnection,
                            serviceFlags);
                    boolean bindSucceeded = startBindToService(imsServiceIntent,
                            mImsServiceConnection, serviceFlags);
                    if (!bindSucceeded) {
                        mBackoff.notifyFailed();
                    }
                    return bindSucceeded;
                } catch (Exception e) {
                    mBackoff.notifyFailed();
                    Log.e(LOG_TAG, "Error binding (" + mComponentName + ") with exception: "
@@ -349,6 +353,15 @@ public class ImsServiceController {
        }
    }

    /**
     * Starts the bind to the ImsService. Overridden by subclasses that need to access the service
     * in a different fashion.
     */
    protected boolean startBindToService(Intent intent, ImsServiceConnection connection,
            int flags) {
        return mContext.bindService(intent, connection, flags);
    }

    /**
     * Calls {@link IImsServiceController#removeImsFeature} on all features that the
     * ImsService supports and then unbinds the service.
+8 −2
Original line number Diff line number Diff line
@@ -160,15 +160,21 @@ public class ImsServiceControllerCompat extends ImsServiceController {
        return mServiceController != null;
    }

    private IImsMmTelFeature createMMTelCompat(int slotId, IImsFeatureStatusCallback c)
    protected MmTelInterfaceAdapter getInterface(int slotId, IImsFeatureStatusCallback c)
            throws RemoteException {
        IImsMMTelFeature feature = mServiceController.createMMTelFeature(slotId, c);
        if (feature == null) {
            Log.w(TAG, "createMMTelCompat: createMMTelFeature returned null.");
            return null;
        }
        return new MmTelInterfaceAdapter(slotId, feature.asBinder());
    }

    private IImsMmTelFeature createMMTelCompat(int slotId, IImsFeatureStatusCallback c)
            throws RemoteException {
        MmTelInterfaceAdapter interfaceAdapter = getInterface(slotId, c);
        MmTelFeatureCompatAdapter mmTelAdapter = new MmTelFeatureCompatAdapter(mContext, slotId,
                feature);
                interfaceAdapter);
        mMmTelCompatAdapters.put(slotId, mmTelAdapter);
        ImsRegistrationCompatAdapter regAdapter = new ImsRegistrationCompatAdapter();
        mmTelAdapter.addRegistrationAdapter(regAdapter);
+77 −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.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;

import com.android.ims.internal.IImsFeatureStatusCallback;
import com.android.ims.internal.IImsService;

/**
 * A compat layer for communicating with older devices that still used the ServiceManager to get
 * the ImsService.
 */

public class ImsServiceControllerStaticCompat extends ImsServiceControllerCompat {

    private static final String TAG = "ImsSCStaticCompat";

    private static final String IMS_SERVICE_NAME = "ims";

    private IImsService mImsServiceCompat = null;

    public ImsServiceControllerStaticCompat(Context context, ComponentName componentName,
            ImsServiceController.ImsServiceControllerCallbacks callbacks) {
        super(context, componentName, callbacks);
    }

    @Override
    public boolean startBindToService(Intent intent, ImsServiceConnection connection, int flags) {
        IBinder binder = ServiceManager.checkService(IMS_SERVICE_NAME);

        if (binder == null) {
            return false;
        }
        // This is a little hacky, but we are going to call the onServiceConnected to "pretend" like
        // bindService has completed here, which will pass the binder to setServiceController and
        // set up all supporting structures.
        connection.onServiceConnected(new ComponentName(mContext,
                ImsServiceControllerStaticCompat.class), binder);
        return true;
    }

    @Override
    protected void setServiceController(IBinder serviceController) {
        mImsServiceCompat = IImsService.Stub.asInterface(serviceController);
    }

    @Override
    protected MmTelInterfaceAdapter getInterface(int slotId, IImsFeatureStatusCallback c)
            throws RemoteException {
        if (mImsServiceCompat == null) {
            Log.w(TAG, "getInterface: IImsService returned null.");
            return null;
        }
        return new ImsServiceInterfaceAdapter(slotId, mImsServiceCompat.asBinder());
    }
}
Loading