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

Commit e2dc47fe authored by Brad Ebinger's avatar Brad Ebinger Committed by Android (Google) Code Review
Browse files

Merge "Ensure BOOT_COMPLETE doesn't cause Bind before CARRIER_CONFIG_CHANGED" into sc-dev

parents 049863d4 1e1680eb
Loading
Loading
Loading
Loading
+69 −41
Original line number Diff line number Diff line
@@ -234,7 +234,7 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal

    // Receives broadcasts from the system involving changes to the installed applications. If
    // an ImsService that we are configured to use is installed, we must bind to it.
    private BroadcastReceiver mAppChangedReceiver = new BroadcastReceiver() {
    private final BroadcastReceiver mAppChangedReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
@@ -258,7 +258,7 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal

    // Receives the broadcast that a new Carrier Config has been loaded in order to possibly
    // unbind from one service and bind to another.
    private BroadcastReceiver mConfigChangedReceiver = new BroadcastReceiver() {
    private final BroadcastReceiver mConfigChangedReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

@@ -290,7 +290,7 @@ 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() {
    private final BroadcastReceiver mBootCompleted = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i(TAG, "Received BOOT_COMPLETED");
@@ -396,7 +396,7 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
                ImsServiceFeatureQueryManager.Listener listener);
    }

    private ImsServiceControllerFactory mImsServiceControllerFactoryCompat =
    private final ImsServiceControllerFactory mImsServiceControllerFactoryCompat =
            new ImsServiceControllerFactory() {
                @Override
                public String getServiceInterface() {
@@ -428,7 +428,7 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
    private int mNumSlots;
    // Array index corresponds to slot, per slot there is a feature->package name mapping.
    // should only be accessed from handler
    private SparseArray<Map<Integer, String>> mCarrierServices;
    private final SparseArray<Map<Integer, String>> mCarrierServices;
    // Package name of the default device services, Maps ImsFeature -> packageName.
    // Must synchronize on this object to access.
    private final Map<Integer, String> mDeviceServices = new ArrayMap<>();
@@ -436,10 +436,11 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
    private final LocalLog mEventLog = new LocalLog(50);

    private boolean mBootCompletedHandlerRan = false;
    private boolean mCarrierConfigReceived = false;

    // Synchronize all events on a handler to ensure that the cache includes the most recent
    // version of the installed ImsServices.
    private Handler mHandler = new Handler(Looper.getMainLooper(), (msg) -> {
    private final Handler mHandler = new Handler(Looper.getMainLooper(), (msg) -> {
        switch (msg.what) {
            case HANDLER_ADD_PACKAGE: {
                String packageName = (String) msg.obj;
@@ -455,8 +456,16 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
                if (!mBootCompletedHandlerRan) {
                    mBootCompletedHandlerRan = true;
                    mEventLog.log("handling BOOT_COMPLETE");
                    if (mCarrierConfigReceived) {
                        mEventLog.log("boot complete - reeval");
                        // Re-evaluate bound services for all slots after requerying packagemanager
                        maybeAddedImsService(null /*packageName*/);
                    } else {
                        mEventLog.log("boot complete - update cache");
                        // Do not bind any ImsServices yet, just update the cache to include new
                        // services. All will be re-evaluated after first carrier config changed.
                        updateInstalledServicesCache();
                    }
                }
                break;
            }
@@ -468,6 +477,7 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
                    Log.w(TAG, "HANDLER_CONFIG_CHANGED for invalid slotid=" + slotId);
                    break;
                }
                mCarrierConfigReceived = true;
                carrierConfigChanged(slotId);
                break;
            }
@@ -510,10 +520,10 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
        return true;
    });

    private HandlerExecutor mRunnableExecutor = new HandlerExecutor(mHandler);
    private final HandlerExecutor mRunnableExecutor = new HandlerExecutor(mHandler);

    // Results from dynamic queries to ImsService regarding the features they support.
    private ImsServiceFeatureQueryManager.Listener mDynamicQueryListener =
    private final ImsServiceFeatureQueryManager.Listener mDynamicQueryListener =
            new ImsServiceFeatureQueryManager.Listener() {

                @Override
@@ -542,16 +552,16 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
    // Used during testing, overrides the carrier services while non-empty.
    // Array index corresponds to slot, per slot there is a feature->package name mapping.
    // should only be accessed from handler
    private SparseArray<SparseArray<String>> mOverrideServices;
    private final SparseArray<SparseArray<String>> mOverrideServices;
    // Outer array index corresponds to Slot Id, Maps ImsFeature.FEATURE->bound ImsServiceController
    // Locked on mBoundServicesLock
    private SparseArray<SparseArray<ImsServiceController>> mBoundImsServicesByFeature;
    private final SparseArray<SparseArray<ImsServiceController>> mBoundImsServicesByFeature;
    // not locked, only accessed on a handler thread.
    // Tracks list of all installed ImsServices
    private Map<ComponentName, ImsServiceInfo> mInstalledServicesCache = new HashMap<>();
    private final Map<ComponentName, ImsServiceInfo> mInstalledServicesCache = new HashMap<>();
    // not locked, only accessed on a handler thread.
    // Active ImsServiceControllers, which are bound to ImsServices.
    private Map<ComponentName, ImsServiceController> mActiveControllers = new HashMap<>();
    private final Map<ComponentName, ImsServiceController> mActiveControllers = new HashMap<>();
    private ImsServiceFeatureQueryManager mFeatureQueryManager;

    public ImsResolver(Context context, String defaultMmTelPackageName,
@@ -571,26 +581,6 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
                Context.CARRIER_CONFIG_SERVICE);
        mOverrideServices = new SparseArray<>(0 /*initial size*/);
        mBoundImsServicesByFeature = new SparseArray<>(mNumSlots);

        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");
        mReceiverContext.registerReceiver(mAppChangedReceiver, appChangedFilter);
        mReceiverContext.registerReceiver(mConfigChangedReceiver, new IntentFilter(
                CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));

        UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        if (userManager.isUserUnlocked()) {
            mHandler.obtainMessage(HANDLER_BOOT_COMPLETE, null).sendToTarget();
        } else {
            mReceiverContext.registerReceiver(mBootCompleted, new IntentFilter(
                    Intent.ACTION_BOOT_COMPLETED));
            if (userManager.isUserUnlocked()) {
                mHandler.obtainMessage(HANDLER_BOOT_COMPLETE, null).sendToTarget();
            }
        }
    }

    @VisibleForTesting
@@ -628,19 +618,47 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
                HANDLER_MSIM_CONFIGURATION_CHANGE, null);
        mFeatureQueryManager = mDynamicQueryManagerFactory.create(mContext, mDynamicQueryListener);

        // This will get all services with the correct intent filter from PackageManager
        List<ImsServiceInfo> infos = getImsServiceInfo(null);
        for (ImsServiceInfo info : infos) {
            if (!mInstalledServicesCache.containsKey(info.name)) {
                mInstalledServicesCache.put(info.name, info);
        updateInstalledServicesCache();

        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");
        mReceiverContext.registerReceiver(mAppChangedReceiver, appChangedFilter);
        mReceiverContext.registerReceiver(mConfigChangedReceiver, new IntentFilter(
                CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));

        UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        if (userManager.isUserUnlocked()) {
            mHandler.obtainMessage(HANDLER_BOOT_COMPLETE, null).sendToTarget();
        } else {
            mReceiverContext.registerReceiver(mBootCompleted, new IntentFilter(
                    Intent.ACTION_BOOT_COMPLETED));
            if (userManager.isUserUnlocked()) {
                mHandler.obtainMessage(HANDLER_BOOT_COMPLETE, null).sendToTarget();
            }
        }

        // Update the package names of the carrier ImsServices if they do not exist already and
        // possibly bind if carrier configs exist. Otherwise wait for CarrierConfigChanged
        // indication.
        bindCarrierServicesIfAvailable();
    }

    /**
     * Query the system for all registered ImsServices and add them to the cache if there are any
     * new ones that are not tracked.
     */
    private void updateInstalledServicesCache() {
        // This will get all services with the correct intent filter from PackageManager
        for (ImsServiceInfo info : getImsServiceInfo(null)) {
            if (!mInstalledServicesCache.containsKey(info.name)) {
                mInstalledServicesCache.put(info.name, info);
            }
        }
    }

    /**
     * Destroys this ImsResolver. Used for tearing down static resources during testing.
     */
@@ -661,6 +679,8 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
                if (!TextUtils.isEmpty(newPackageName)) {
                    mEventLog.log("bindCarrierServicesIfAvailable - carrier package found: "
                            + newPackageName + " on slot " + slotId);
                    // Carrier configs are already available, so mark received.
                    mCarrierConfigReceived = true;
                    setCarrierConfiguredPackageName(newPackageName, slotId, f);
                    ImsServiceInfo info = getImsServiceInfoFromCache(newPackageName);
                    // We do not want to trigger feature configuration changes unless there is
@@ -1571,9 +1591,9 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
                    + name);
            return;
        }
        sanitizeFeatureConfig(features);
        mEventLog.log("dynamicQueryComplete: for package " + name + ", features: "
                + printFeatures(service.getSupportedFeatures()) + " -> " + printFeatures(features));
        sanitizeFeatureConfig(features);
        // Add features to service
        service.replaceFeatures(features);
        // Wait until all queries have completed before changing the configuration to reduce churn.
@@ -1587,9 +1607,17 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
    }

    /**
     * Ensure the feature includes MMTEL when it supports EMERGENCY_MMTEL, if not, remove.
     * Sanitize feature configurations from the ImsService.
     * <ul>
     *     <li> Strip out feature configs for inactive slots.</li>
     *     <li> Ensure the feature includes MMTEL when it supports EMERGENCY_MMTEL, if not, remove.
     *     </li>
     * </ul>
     */
    private void sanitizeFeatureConfig(Set<ImsFeatureConfiguration.FeatureSlotPair> features) {
        // remove configs for slots that are mot active.
        features.removeIf(f -> f.slotId >= mNumSlots);
        // Ensure that if EMERGENCY_MMTEL is defined for a slot, MMTEL is also defined.
        Set<ImsFeatureConfiguration.FeatureSlotPair> emergencyMmtelFeatures = features.stream()
                .filter(feature -> feature.featureType == ImsFeature.FEATURE_EMERGENCY_MMTEL)
                .collect(Collectors.toSet());
+12 −6
Original line number Diff line number Diff line
@@ -1872,12 +1872,6 @@ public class ImsResolverTest extends ImsTestBase {
            fail("Unable to create looper from handler.");
        }

        ArgumentCaptor<BroadcastReceiver> receiversCaptor =
                ArgumentCaptor.forClass(BroadcastReceiver.class);
        verify(mMockContext, times(3)).registerReceiver(receiversCaptor.capture(), any());
        mTestPackageBroadcastReceiver = receiversCaptor.getAllValues().get(0);
        mTestCarrierConfigReceiver = receiversCaptor.getAllValues().get(1);
        mTestBootCompleteReceiver = receiversCaptor.getAllValues().get(2);
        mTestImsResolver.setSubscriptionManagerProxy(mTestSubscriptionManagerProxy);
        mTestImsResolver.setTelephonyManagerProxy(mTestTelephonyManagerProxy);
        when(mMockQueryManagerFactory.create(any(Context.class),
@@ -1929,6 +1923,12 @@ public class ImsResolverTest extends ImsTestBase {
     */
    private void startBindCarrierConfigAlreadySet() {
        mTestImsResolver.initialize();
        ArgumentCaptor<BroadcastReceiver> receiversCaptor =
                ArgumentCaptor.forClass(BroadcastReceiver.class);
        verify(mMockContext, times(3)).registerReceiver(receiversCaptor.capture(), any());
        mTestPackageBroadcastReceiver = receiversCaptor.getAllValues().get(0);
        mTestCarrierConfigReceiver = receiversCaptor.getAllValues().get(1);
        mTestBootCompleteReceiver = receiversCaptor.getAllValues().get(2);
        ArgumentCaptor<ImsServiceFeatureQueryManager.Listener> queryManagerCaptor =
                ArgumentCaptor.forClass(ImsServiceFeatureQueryManager.Listener.class);
        verify(mMockQueryManagerFactory).create(any(Context.class), queryManagerCaptor.capture());
@@ -1944,6 +1944,12 @@ public class ImsResolverTest extends ImsTestBase {
     */
    private void startBindNoCarrierConfig(int numSlots) {
        mTestImsResolver.initialize();
        ArgumentCaptor<BroadcastReceiver> receiversCaptor =
                ArgumentCaptor.forClass(BroadcastReceiver.class);
        verify(mMockContext, times(3)).registerReceiver(receiversCaptor.capture(), any());
        mTestPackageBroadcastReceiver = receiversCaptor.getAllValues().get(0);
        mTestCarrierConfigReceiver = receiversCaptor.getAllValues().get(1);
        mTestBootCompleteReceiver = receiversCaptor.getAllValues().get(2);
        ArgumentCaptor<ImsServiceFeatureQueryManager.Listener> queryManagerCaptor =
                ArgumentCaptor.forClass(ImsServiceFeatureQueryManager.Listener.class);
        verify(mMockQueryManagerFactory).create(any(Context.class), queryManagerCaptor.capture());