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

Commit c25748ff authored by Malcolm Chen's avatar Malcolm Chen
Browse files

Update CarrierServiceBindHelper when multi-SIM config changes.

Register with PhoneConfigurationManager on multi SIM config change.
Then dynamically allocate / de-allocate objects based on current
active modem count.

Bug: 142514392
Test: unittest
Change-Id: I1390eccd0dac56e5367fec1fe3b03a207ac400cc
Merged-In: I1390eccd0dac56e5367fec1fe3b03a207ac400cc
parent dc8d0152
Loading
Loading
Loading
Loading
+52 −20
Original line number Diff line number Diff line
@@ -37,7 +37,9 @@ import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor;

import java.io.FileDescriptor;
@@ -59,8 +61,10 @@ public class CarrierServiceBindHelper {

    @UnsupportedAppUsage
    private Context mContext;
    private AppBinding[] mBindings;
    private String[] mLastSimState;
    @VisibleForTesting
    public SparseArray<AppBinding> mBindings = new SparseArray();
    @VisibleForTesting
    public SparseArray<String> mLastSimState = new SparseArray<>();
    private final PackageMonitor mPackageMonitor = new CarrierServicePackageMonitor();

    private BroadcastReceiver mUserUnlockedReceiver = new BroadcastReceiver() {
@@ -72,8 +76,8 @@ public class CarrierServiceBindHelper {
            if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
                // On user unlock, new components might become available, so reevaluate all
                // bindings.
                for (int phoneId = 0; phoneId < mBindings.length; phoneId++) {
                    mBindings[phoneId].rebind();
                for (int phoneId = 0; phoneId < mBindings.size(); phoneId++) {
                    mBindings.get(phoneId).rebind();
                }
            }
        }
@@ -81,24 +85,34 @@ public class CarrierServiceBindHelper {

    private static final int EVENT_REBIND = 0;
    private static final int EVENT_PERFORM_IMMEDIATE_UNBIND = 1;
    @VisibleForTesting
    public static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 2;

    @UnsupportedAppUsage
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            int phoneId;
            AppBinding binding;
            log("mHandler: " + msg.what);

            switch (msg.what) {
                case EVENT_REBIND:
                    binding = (AppBinding) msg.obj;
                    phoneId = (int) msg.obj;
                    binding = mBindings.get(phoneId);
                    if (binding == null) return;
                    log("Rebinding if necessary for phoneId: " + binding.getPhoneId());
                    binding.rebind();
                    break;
                case EVENT_PERFORM_IMMEDIATE_UNBIND:
                    binding = (AppBinding) msg.obj;
                    phoneId = (int) msg.obj;
                    binding = mBindings.get(phoneId);
                    if (binding == null) return;
                    binding.performImmediateUnbind();
                    break;
                case EVENT_MULTI_SIM_CONFIG_CHANGED:
                    updateBindingsAndSimStates();
                    break;
            }
        }
    };
@@ -106,13 +120,10 @@ public class CarrierServiceBindHelper {
    public CarrierServiceBindHelper(Context context) {
        mContext = context;

        int numPhones = TelephonyManager.from(context).getSupportedModemCount();
        mBindings = new AppBinding[numPhones];
        mLastSimState = new String[numPhones];
        updateBindingsAndSimStates();

        for (int phoneId = 0; phoneId < numPhones; phoneId++) {
            mBindings[phoneId] = new AppBinding(phoneId);
        }
        PhoneConfigurationManager.getInstance().registerForMultiSimConfigChange(
                mHandler, EVENT_MULTI_SIM_CONFIG_CHANGED, null);

        mPackageMonitor.register(
                context, mHandler.getLooper(), UserHandle.ALL, false /* externalStorage */);
@@ -121,19 +132,39 @@ public class CarrierServiceBindHelper {
                mHandler);
    }

    // Create or dispose mBindings and mLastSimState objects.
    private void updateBindingsAndSimStates() {
        int prevLen = mBindings.size();
        int newLen = ((TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE))
                .getActiveModemCount();

        // If prevLen < newLen, allocate AppBinding and simState objects.
        for (int phoneId = prevLen; phoneId < newLen; phoneId++) {
            mBindings.put(phoneId, new AppBinding(phoneId));
            mLastSimState.put(phoneId, new String());
        }

        // If prevLen > newLen, dispose AppBinding and simState objects.
        for (int phoneId = newLen; phoneId < prevLen; phoneId++) {
            mBindings.get(phoneId).unbind(true);
            mBindings.delete(phoneId);
            mLastSimState.delete(phoneId);
        }
    }

    void updateForPhoneId(int phoneId, String simState) {
        log("update binding for phoneId: " + phoneId + " simState: " + simState);
        if (!SubscriptionManager.isValidPhoneId(phoneId)) {
            return;
        }
        if (TextUtils.isEmpty(simState) || phoneId >= mLastSimState.length) return;
        if (simState.equals(mLastSimState[phoneId])) {
        if (TextUtils.isEmpty(simState) || phoneId >= mLastSimState.size()) return;
        if (simState.equals(mLastSimState.get(phoneId))) {
            // ignore consecutive duplicated events
            return;
        } else {
            mLastSimState[phoneId] = simState;
            mLastSimState.put(phoneId, simState);
        }
        mHandler.sendMessage(mHandler.obtainMessage(EVENT_REBIND, mBindings[phoneId]));
        mHandler.sendMessage(mHandler.obtainMessage(EVENT_REBIND, phoneId));
    }

    private class AppBinding {
@@ -274,7 +305,7 @@ public class CarrierServiceBindHelper {
                mUnbindScheduledUptimeMillis = currentUptimeMillis + UNBIND_DELAY_MILLIS;
                log("Scheduling unbind in " + UNBIND_DELAY_MILLIS + " millis");
                mHandler.sendMessageAtTime(
                        mHandler.obtainMessage(EVENT_PERFORM_IMMEDIATE_UNBIND, this),
                        mHandler.obtainMessage(EVENT_PERFORM_IMMEDIATE_UNBIND, phoneId),
                        mUnbindScheduledUptimeMillis);
            }
        }
@@ -365,7 +396,8 @@ public class CarrierServiceBindHelper {
        }

        private void evaluateBinding(String carrierPackageName, boolean forceUnbind) {
            for (AppBinding appBinding : mBindings) {
            for (int i = 0; i < mBindings.size(); i++) {
                AppBinding appBinding = mBindings.get(i);
                String appBindingPackage = appBinding.getPackage();
                boolean isBindingForPackage = carrierPackageName.equals(appBindingPackage);
                // Only log if this package was a carrier package to avoid log spam in the common
@@ -391,8 +423,8 @@ public class CarrierServiceBindHelper {

    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("CarrierServiceBindHelper:");
        for (AppBinding binding : mBindings) {
            binding.dump(fd, pw, args);
        for (int i = 0; i < mBindings.size(); i++) {
            mBindings.get(i).dump(fd, pw, args);
        }
    }
}
+2 −1
Original line number Diff line number Diff line
@@ -385,7 +385,8 @@ public class PhoneConfigurationManager {
        mMi.setMultiSimProperties(numOfActiveModems);
    }

    private static void notifyMultiSimConfigChange(int numOfActiveModems) {
    @VisibleForTesting
    public static void notifyMultiSimConfigChange(int numOfActiveModems) {
        sMultiSimConfigChangeRegistrants.notifyResult(numOfActiveModems);
    }

+84 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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;

import static android.telephony.TelephonyManager.MODEM_COUNT_DUAL_MODEM;
import static android.telephony.TelephonyManager.MODEM_COUNT_SINGLE_MODEM;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doReturn;

import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class CarrierServiceBindHelperTest extends TelephonyTest {
    CarrierServiceBindHelper mCarrierServiceBindHelper;
    @Before
    public void setUp() throws Exception {
        super.setUp(getClass().getSimpleName());
        doReturn(MODEM_COUNT_SINGLE_MODEM).when(mTelephonyManager).getActiveModemCount();
    }

    @After
    public void tearDown() throws Exception {
        // Restore system properties.
        super.tearDown();
    }

    @Test
    @SmallTest
    public void testMultiSimConfigChanged() throws Exception {
        clearInvocations(mPhoneConfigurationManager);
        mCarrierServiceBindHelper = new CarrierServiceBindHelper(mContext);
        assertEquals(MODEM_COUNT_SINGLE_MODEM, mCarrierServiceBindHelper.mBindings.size());
        assertEquals(MODEM_COUNT_SINGLE_MODEM, mCarrierServiceBindHelper.mLastSimState.size());
        assertNotNull(mCarrierServiceBindHelper.mBindings.get(0));
        assertNotNull(mCarrierServiceBindHelper.mLastSimState.get(0));

        // Verify registration of EVENT_MULTI_SIM_CONFIG_CHANGED.
        doReturn(MODEM_COUNT_DUAL_MODEM).when(mTelephonyManager).getActiveModemCount();
        PhoneConfigurationManager.notifyMultiSimConfigChange(MODEM_COUNT_DUAL_MODEM);
        processAllMessages();

        assertEquals(MODEM_COUNT_DUAL_MODEM, mCarrierServiceBindHelper.mBindings.size());
        assertEquals(MODEM_COUNT_DUAL_MODEM, mCarrierServiceBindHelper.mLastSimState.size());
        assertNotNull(mCarrierServiceBindHelper.mBindings.get(0));
        assertNotNull(mCarrierServiceBindHelper.mBindings.get(1));
        assertNotNull(mCarrierServiceBindHelper.mLastSimState.get(0));
        assertNotNull(mCarrierServiceBindHelper.mLastSimState.get(1));

        // Switch back to single SIM.
        doReturn(MODEM_COUNT_SINGLE_MODEM).when(mTelephonyManager).getActiveModemCount();
        PhoneConfigurationManager.notifyMultiSimConfigChange(MODEM_COUNT_SINGLE_MODEM);
        processAllMessages();

        assertEquals(MODEM_COUNT_SINGLE_MODEM, mCarrierServiceBindHelper.mBindings.size());
        assertEquals(MODEM_COUNT_SINGLE_MODEM, mCarrierServiceBindHelper.mLastSimState.size());
        assertNotNull(mCarrierServiceBindHelper.mBindings.get(0));
        assertNotNull(mCarrierServiceBindHelper.mLastSimState.get(0));
    }
}