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

Commit 9a4a11e1 authored by Brad Ebinger's avatar Brad Ebinger
Browse files

When BOOT_COMPLETE occurs, recalculate ImsServices

When the ImsResolver queries PM for ImsServices, apps
that are not FBE enabled do not get returned. This
means that the apps will not be bound. This change
enabled the ImsResolver to requery ImsServices after
BOOT_COMPLETE to pick up the new ImsServices and
bind to them if needed.

Also adds better logging

Bug: 118343976
Test: TestImsApp; atest FrameworksTelephonyTests
Change-Id: If52a8a4cf44b7b19373048017352a864e419c621
parent b9f7786f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -243,7 +243,7 @@ public class PhoneFactory {
                    Rlog.i(LOG_TAG, "ImsResolver: defaultImsPackage: " + defaultImsPackage);
                    sImsResolver = new ImsResolver(sContext, defaultImsPackage, numPhones,
                            isDynamicBinding);
                    sImsResolver.initPopulateCacheAndStartBind();
                    sImsResolver.initialize();
                    // Start monitoring after defaults have been made.
                    // Default phone must be ready before ImsPhone is created because ImsService
                    // might need it when it is being opened. This should initialize multiple
+53 −21
Original line number Diff line number Diff line
@@ -97,6 +97,9 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
    private static final int HANDLER_DYNAMIC_FEATURE_CHANGE = 4;
    // Testing: Overrides the current configuration for ImsService binding
    private static final int HANDLER_OVERRIDE_IMS_SERVICE_CONFIG = 5;
    // Based on boot complete indication. When this happens, there may be ImsServices that are not
    // direct boot aware that need to be started.
    private static final int HANDLER_BOOT_COMPLETE = 6;

    // Delay between dynamic ImsService queries.
    private static final int DELAY_DYNAMIC_QUERY_MS = 5000;
@@ -173,7 +176,7 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
                res.append("(");
                res.append(feature.slotId);
                res.append(",");
                res.append(feature.featureType);
                res.append(ImsFeature.FEATURE_LOG_MAP.get(feature.featureType));
                res.append(") ");
            }
            return res.toString();
@@ -224,6 +227,18 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
        }
    };

    // Receives the broadcast that the device has finished booting (and the device is no longer
    // encrypted).
    private BroadcastReceiver mBootCompleted = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i(TAG, "Received BOOT_COMPLETED");
            // Recalculate all cached services to pick up ones that have just been enabled since
            // boot complete.
            mHandler.obtainMessage(HANDLER_BOOT_COMPLETE, null).sendToTarget();
        }
    };

    /**
     * Testing interface used to mock SubscriptionManager in testing
     */
@@ -352,6 +367,11 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
                maybeRemovedImsService(packageName);
                break;
            }
            case HANDLER_BOOT_COMPLETE: {
                // Re-evaluate bound services for all slots after requerying packagemanager
                maybeAddedImsService(null);
                break;
            }
            case HANDLER_CONFIG_CHANGED: {
                int slotId = (Integer) msg.obj;
                carrierConfigChanged(slotId);
@@ -379,7 +399,7 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
                if (isCarrierImsService) {
                    Log.i(TAG, "overriding carrier ImsService - slot=" + slotId + " packageName="
                            + packageName);
                    maybeRebindService(slotId, packageName);
                    overrideService(slotId, packageName);
                } else {
                    Log.i(TAG, "overriding device ImsService -  packageName=" + packageName);
                    if (TextUtils.equals(mDeviceService, packageName)) {
@@ -417,8 +437,7 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
                @Override
                public void onComplete(ComponentName name,
                        Set<ImsFeatureConfiguration.FeatureSlotPair> features) {
                    Log.d(TAG, "onComplete called for name: " + name + "features:"
                            + printFeatures(features));
                    Log.d(TAG, "onComplete called for name: " + name + printFeatures(features));
                    handleFeaturesChanged(name, features);
                }

@@ -472,6 +491,8 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal

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

@@ -496,10 +517,9 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
    }

    /**
     * Needs to be called after the constructor to first populate the cache and possibly bind to
     * ImsServices.
     * Needs to be called after the constructor to kick off the process of binding to ImsServices.
     */
    public void initPopulateCacheAndStartBind() {
    public void initialize() {
        Log.i(TAG, "Initializing cache and binding.");
        mFeatureQueryManager = mDynamicQueryManagerFactory.create(mContext, mDynamicQueryListener);
        // Populates the CarrierConfig override package names for each slot
@@ -678,7 +698,8 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
                mBoundImsServicesByFeature.add(slotId, services);
            }
            Log.i(TAG, "ImsServiceController added on slot: " + slotId + " with feature: "
                    + feature + " using package: " + controller.getComponentName());
                    + ImsFeature.FEATURE_LOG_MAP.get(feature) + " using package: "
                    + controller.getComponentName());
            services.put(feature, controller);
        }
    }
@@ -698,7 +719,8 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
            ImsServiceController c = services.get(feature, null);
            if (c != null) {
                Log.i(TAG, "ImsServiceController removed on slot: " + slotId + " with feature: "
                        + feature + " using package: " + c.getComponentName());
                        + ImsFeature.FEATURE_LOG_MAP.get(feature) + " using package: "
                        + c.getComponentName());
                services.remove(feature);
            }
            return c;
@@ -999,10 +1021,9 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
        return bindableFeatures > 0;
    }

    // Possibly rebind to another ImsService if currently installed ImsServices were changed or if
    // the SIM card has changed.
    // Possibly rebind to another ImsService for testing.
    // Called from the handler ONLY
    private void maybeRebindService(int slotId, String newPackageName) {
    private void overrideService(int slotId, String newPackageName) {
        if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
            // not specified, replace package on all slots.
            for (int i = 0; i < mNumSlots; i++) {
@@ -1014,18 +1035,29 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal

    }

    // Called from handler ONLY.
    private void carrierConfigChanged(int slotId) {
        if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
            // not specified, update carrier override cache and possibly rebind on all slots.
            for (int i = 0; i < mNumSlots; i++) {
                updateBoundCarrierServices(i, getImsPackageOverrideConfig(i));
            }
        }
        updateBoundCarrierServices(slotId, getImsPackageOverrideConfig(slotId));
    }

    private String getImsPackageOverrideConfig(int slotId) {
        int subId = mSubscriptionManagerProxy.getSubId(slotId);
        PersistableBundle config = mCarrierConfigManager.getConfigForSubId(subId);
        if (config != null) {
            String newPackageName = config.getString(
                    CarrierConfigManager.KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING, null);
            maybeRebindService(slotId, newPackageName);
        } else {
            Log.w(TAG, "carrierConfigChanged: CarrierConfig is null!");
        }
        if (config == null) return null;
        return config.getString(CarrierConfigManager.KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING, null);
    }

    /**
     * Use the slotId specified to update the carrier override cache with the new package name.
     * If it has changed, trigger an unbind from the old service kick off the process to recalculate
     * features supported on the new service.
     */
    private void updateBoundCarrierServices(int slotId, String newPackageName) {
        if (slotId > SubscriptionManager.INVALID_SIM_SLOT_INDEX && slotId < mNumSlots) {
            String oldPackageName = mCarrierServices[slotId];
@@ -1142,7 +1174,7 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
                featureString.append("{");
                featureString.append(feature.slotId);
                featureString.append(",");
                featureString.append(feature.featureType);
                featureString.append(ImsFeature.FEATURE_LOG_MAP.get(feature.featureType));
                featureString.append("} ");
            }
            featureString.append("]");
+4 −2
Original line number Diff line number Diff line
@@ -246,7 +246,8 @@ public class ImsServiceController {
            @Override
            public void notifyImsFeatureStatus(int featureStatus) throws RemoteException {
                Log.i(LOG_TAG, "notifyImsFeatureStatus: slot=" + mSlotId + ", feature="
                        + mFeatureType + ", status=" + featureStatus);
                        + ImsFeature.FEATURE_LOG_MAP.get(mFeatureType) + ", status="
                        + ImsFeature.STATE_LOG_MAP.get(featureStatus));
                sendImsFeatureStatusChanged(mSlotId, mFeatureType, featureStatus);
            }
        };
@@ -692,7 +693,8 @@ public class ImsServiceController {
            } catch (RemoteException e) {
                // The connection to this ImsService doesn't exist. This may happen if the service
                // has died and we are removing features.
                Log.i(LOG_TAG, "Couldn't remove feature {" + featurePair.featureType
                Log.i(LOG_TAG, "Couldn't remove feature {"
                        + ImsFeature.FEATURE_LOG_MAP.get(featurePair.featureType)
                        + "}, connection is down: " + e.getMessage());
            }
        } else {
+52 −6
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@@ -58,7 +59,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;

import java.util.ArrayList;
import java.util.HashSet;
@@ -96,6 +96,7 @@ public class ImsResolverTest extends ImsTestBase {
    private ImsResolver mTestImsResolver;
    private BroadcastReceiver mTestPackageBroadcastReceiver;
    private BroadcastReceiver mTestCarrierConfigReceiver;
    private BroadcastReceiver mTestBootCompleteReceiver;
    private ImsServiceFeatureQueryManager.Listener mDynamicQueryListener;
    private PersistableBundle[] mCarrierConfigs;

@@ -793,6 +794,50 @@ public class ImsResolverTest extends ImsTestBase {
        verify(deviceController).changeImsServiceFeatures(deviceFeatureSet);
    }

    /**
     * Inform the ImsResolver that BOOT_COMPLETE has happened. A non-FBE enabled ImsService is now
     * available to be bound.
     */
    @Test
    @SmallTest
    public void testBootCompleteNonFbeEnabledCarrierImsService() throws RemoteException {
        setupResolver(2/*numSlots*/);
        List<ResolveInfo> info = new ArrayList<>();
        Set<String> deviceFeatures = new HashSet<>();
        deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE);
        deviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE);
        // Set the carrier override package for slot 0
        setConfigCarrierString(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
        // Use device default package, which will load the ImsService that the device provides
        info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true));
        setupPackageQuery(info);
        ImsServiceController deviceController = mock(ImsServiceController.class);
        ImsServiceController carrierController = mock(ImsServiceController.class);
        setImsServiceControllerFactory(deviceController, carrierController);

        // Bind with device ImsService
        startBind();

        // Boot complete happens and the Carrier ImsService is now available.
        HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>();
        // Carrier service doesn't support the voice feature.
        carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
        info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
        // Boot complete has happened and the carrier ImsService is now available.
        mTestBootCompleteReceiver.onReceive(null, new Intent(Intent.ACTION_BOOT_COMPLETED));
        waitForHandlerAction(mTestImsResolver.getHandler(), TEST_TIMEOUT);
        setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);

        // Verify that all features that have been defined for the carrier override are bound
        verify(carrierController).bind(carrierFeatures);
        // device features change
        HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
                convertToHashSet(deviceFeatures, 1);
        deviceFeatureSet.addAll(convertToHashSet(deviceFeatures, 0));
        deviceFeatureSet.removeAll(carrierFeatures);
        verify(deviceController).changeImsServiceFeatures(deviceFeatureSet);
    }

    private void setupResolver(int numSlots) {
        when(mMockContext.getSystemService(eq(Context.CARRIER_CONFIG_SERVICE))).thenReturn(
                mMockCarrierConfigManager);
@@ -811,13 +856,14 @@ public class ImsResolverTest extends ImsTestBase {

        ArgumentCaptor<BroadcastReceiver> packageBroadcastCaptor =
                ArgumentCaptor.forClass(BroadcastReceiver.class);
        ArgumentCaptor<BroadcastReceiver> carrierConfigCaptor =
        ArgumentCaptor<BroadcastReceiver> receiversCaptor =
                ArgumentCaptor.forClass(BroadcastReceiver.class);
        verify(mMockContext).registerReceiverAsUser(packageBroadcastCaptor.capture(), any(),
                any(), any(), any());
        verify(mMockContext).registerReceiver(carrierConfigCaptor.capture(), any());
        mTestCarrierConfigReceiver = carrierConfigCaptor.getValue();
        mTestPackageBroadcastReceiver = packageBroadcastCaptor.getValue();
        verify(mMockContext, times(2)).registerReceiver(receiversCaptor.capture(), any());
        mTestCarrierConfigReceiver = receiversCaptor.getAllValues().get(0);
        mTestBootCompleteReceiver = receiversCaptor.getAllValues().get(1);
        mTestImsResolver.setSubscriptionManagerProxy(mTestSubscriptionManagerProxy);
        when(mMockQueryManagerFactory.create(any(Context.class),
                any(ImsServiceFeatureQueryManager.Listener.class))).thenReturn(mMockQueryManager);
@@ -861,7 +907,7 @@ public class ImsResolverTest extends ImsTestBase {
    }

    private void startBind() {
        mTestImsResolver.initPopulateCacheAndStartBind();
        mTestImsResolver.initialize();
        ArgumentCaptor<ImsServiceFeatureQueryManager.Listener> queryManagerCaptor =
                ArgumentCaptor.forClass(ImsServiceFeatureQueryManager.Listener.class);
        verify(mMockQueryManagerFactory).create(any(Context.class), queryManagerCaptor.capture());
@@ -876,7 +922,7 @@ public class ImsResolverTest extends ImsTestBase {
        // ensure that startQuery was called
        when(mMockQueryManager.startQuery(any(ComponentName.class), any(String.class)))
                .thenReturn(true);
        verify(mMockQueryManager, Mockito.times(times)).startQuery(eq(name), any(String.class));
        verify(mMockQueryManager, times(times)).startQuery(eq(name), any(String.class));
        mDynamicQueryListener.onComplete(name, features);
        // wait for handling of onComplete
        waitForHandlerAction(mTestImsResolver.getHandler(), TEST_TIMEOUT);