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

Commit a81a3f92 authored by Nazanin Bakhshi's avatar Nazanin Bakhshi
Browse files

Add telephony API to switch multi sim config

Bug: 122115649
Test: sanity
Change-Id: I5e52a6a57b88e6d79454dde859d4477cfca10949
parent 4b288b31
Loading
Loading
Loading
Loading
+99 −5
Original line number Diff line number Diff line
@@ -17,7 +17,10 @@
package com.android.internal.telephony;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
import android.os.SystemProperties;
import android.telephony.PhoneCapability;
import android.telephony.Rlog;
import android.telephony.TelephonyManager;
@@ -30,12 +33,19 @@ import android.util.Log;
 * if they change, and and sends commands to modem to enable or disable phones.
 */
public class PhoneConfigurationManager {
    public static final String DSDA = "dsda";
    public static final String DSDS = "dsds";
    public static final String TSTS = "tsts";
    public static final String SSSS = "";
    private static final String LOG_TAG = "PhoneCfgMgr";
    private static final int EVENT_SWITCH_DSDS_CONFIG_DONE = 100;

    private static PhoneConfigurationManager sInstance = null;
    private final Context mContext;
    private PhoneCapability mStaticCapability;
    private PhoneCapability mCurrentCapability;
    private final RadioConfig mRadioConfig;
    private final MainThreadHandler mHandler;

    /**
     * Init method to instantiate the object
@@ -60,10 +70,10 @@ public class PhoneConfigurationManager {
        mContext = context;
        // TODO: send commands to modem once interface is ready.
        TelephonyManager telephonyManager = new TelephonyManager(context);
        mStaticCapability = telephonyManager.getPhoneCount() == 1
                ? PhoneConfigurationModels.SSSS_CAPABILITY
                : PhoneConfigurationModels.DSDS_CAPABILITY;
        mStaticCapability = PhoneConfigurationModels.DSDS_CAPABILITY;
        mCurrentCapability = mStaticCapability;
        mRadioConfig = RadioConfig.getInstance(mContext);
        mHandler = new MainThreadHandler();

        notifyCapabilityChanged();
    }
@@ -79,6 +89,24 @@ public class PhoneConfigurationManager {
        return sInstance;
    }

    /**
     * Handler class to handle callbacks
     */
    private final class MainThreadHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case EVENT_SWITCH_DSDS_CONFIG_DONE:
                    if (msg.obj != null) {
                        int numOfLiveModems = msg.arg1;
                        setMultiSimProperties(numOfLiveModems);
                    } else {
                        log(msg.what + " failure. Not switching multi-sim config.");
                    }
                    break;
            }
        }
    }

    /**
     * Enable or disable phone
@@ -105,7 +133,6 @@ public class PhoneConfigurationManager {

    /**
     * get static overall phone capabilities for all phones.
     *
     */
    public PhoneCapability getStaticPhoneCapability() {
        return mStaticCapability;
@@ -113,7 +140,6 @@ public class PhoneConfigurationManager {

    /**
     * get configuration related status of each phone.
     *
     */
    public PhoneCapability getCurrentPhoneCapability() {
        return mCurrentCapability;
@@ -129,6 +155,74 @@ public class PhoneConfigurationManager {
        notifier.notifyPhoneCapabilityChanged(mCurrentCapability);
    }

    /**
     * Switch configs to enable multi-sim or switch back to single-sim
     * @param numOfSims number of active sims we want to switch to
     */
    public void switchMultiSimConfig(int numOfSims) {
        if (getStaticPhoneCapability().logicalModemList.size() < numOfSims) {
            log("switchMultiSimConfig: Phone is not capable of enabling "
                    + numOfSims + " sims, exiting!");
            return;
        }
        if (getNumOfActiveSims() != numOfSims) {
            Message callback = Message.obtain(
                    mHandler, EVENT_SWITCH_DSDS_CONFIG_DONE, numOfSims);
            mRadioConfig.setModemsConfig(numOfSims, callback);
        } else {
            log("switchMultiSimConfig: No need to switch. getNumOfActiveSims is already "
                    + numOfSims);
        }
    }

    /**
     * Get how many sims have been activated on the phone
     * NOTE: In order to support more than 3 sims, we need to change this method.
     */
    public int getNumOfActiveSims() {
        String mSimConfig =
                SystemProperties.get(TelephonyProperties.PROPERTY_MULTI_SIM_CONFIG);
        int numOfSims;
        switch (mSimConfig) {
            case TSTS:
                numOfSims = 3;
                break;
            case DSDA:
            case DSDS:
                numOfSims = 2;
                break;
            default:
                numOfSims = 1;
        }
        return numOfSims;
    }

    /**
     * Helper method to set system properties for setting multi sim configs,
     * as well as doing the phone reboot
     * NOTE: In order to support more than 3 sims, we need to change this method.
     * @param numOfSims number of active sims
     */
    private void setMultiSimProperties(int numOfSims) {
        String finalMultiSimConfig;
        switch(numOfSims) {
            case 3:
                finalMultiSimConfig = TSTS;
                break;
            case 2:
                finalMultiSimConfig = DSDS;
                break;
            default:
                finalMultiSimConfig = SSSS;
        }

        SystemProperties.set(TelephonyProperties.PROPERTY_MULTI_SIM_CONFIG, finalMultiSimConfig);
        log("setMultiSimProperties: Rebooting due to switching multi-sim config to "
                + finalMultiSimConfig);
        PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        pm.reboot("Switching to " + finalMultiSimConfig);
    }

    private static void log(String s) {
        Rlog.d(LOG_TAG, s);
    }
+35 −0
Original line number Diff line number Diff line
@@ -23,11 +23,13 @@ import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_SLOT_S
import static com.android.internal.telephony.RILConstants
        .RIL_REQUEST_SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_PREFERRED_DATA_MODEM;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SWITCH_DUAL_SIM_CONFIG;

import android.content.Context;
import android.hardware.radio.V1_0.RadioResponseInfo;
import android.hardware.radio.V1_0.RadioResponseType;
import android.hardware.radio.config.V1_0.IRadioConfig;
import android.hardware.radio.config.V1_1.ModemsConfig;
import android.net.ConnectivityManager;
import android.os.AsyncResult;
import android.os.Handler;
@@ -395,11 +397,44 @@ public class RadioConfig extends Handler {
                return "GET_SLOT_STATUS";
            case RIL_REQUEST_SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING:
                return "SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING";
            case RIL_REQUEST_SWITCH_DUAL_SIM_CONFIG:
                return "RIL_REQUEST_SWITCH_DUAL_SIM_CONFIG";
            default:
                return "<unknown request>";
        }
    }

    /**
     * Wrapper function for using IRadioConfig.setModemsConfig(int32_t serial,
     * ModemsConfig modemsConfig) to switch between single-sim and multi-sim.
     */
    public void setModemsConfig(int numOfLiveModems, Message result) {
        IRadioConfig radioConfigProxy = getRadioConfigProxy(result);
        if (radioConfigProxy != null
                && mRadioConfigVersion.greaterOrEqual(RADIO_CONFIG_HAL_VERSION_1_1)) {
            android.hardware.radio.config.V1_1.IRadioConfig radioConfigProxy11 =
                    (android.hardware.radio.config.V1_1.IRadioConfig) radioConfigProxy;
            RILRequest rr = obtainRequest(RIL_REQUEST_SWITCH_DUAL_SIM_CONFIG,
                    result, mDefaultWorkSource);

            if (DBG) {
                logd(rr.serialString() + "> " + requestToString(rr.mRequest)
                        + "numOfLiveModems = " + numOfLiveModems);
            }

            try {
                ModemsConfig modemsConfig = new ModemsConfig();
                modemsConfig.numOfLiveModems = (byte) numOfLiveModems;
                radioConfigProxy11.setModemsConfig(rr.mSerial, modemsConfig);
            } catch (RemoteException | RuntimeException e) {
                resetProxyAndRequestList("setModemsConfig", e);
            }
        }
    }

    // TODO: not needed for now, but if we don't want to use System Properties any more,
    // we need to implement a wrapper function for getModemsConfig as well

    /**
     * Register a handler to get SIM slot status changed notifications.
     */
+38 −6
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.internal.telephony;

import android.hardware.radio.V1_0.RadioError;
import android.hardware.radio.V1_0.RadioResponseInfo;
import android.hardware.radio.config.V1_1.ModemsConfig;
import android.hardware.radio.config.V1_2.IRadioConfigResponse;
import android.telephony.ModemInfo;
import android.telephony.PhoneCapability;
@@ -32,9 +33,10 @@ import java.util.List;
 * This class is the implementation of IRadioConfigResponse interface.
 */
public class RadioConfigResponse extends IRadioConfigResponse.Stub {
    private final RadioConfig mRadioConfig;
    private static final String TAG = "RadioConfigResponse";

    private final RadioConfig mRadioConfig;

    public RadioConfigResponse(RadioConfig radioConfig) {
        mRadioConfig = radioConfig;
    }
@@ -180,18 +182,48 @@ public class RadioConfigResponse extends IRadioConfigResponse.Stub {

    /**
     * Response function for IRadioConfig.setModemsConfigResponse()
     *
     * Currently this is being used as the callback for RadioConfig.setModemsConfig() method
     */
    public void setModemsConfigResponse(RadioResponseInfo info) {
    public void setModemsConfigResponse(RadioResponseInfo responseInfo) {
        RILRequest rr = mRadioConfig.processResponse(responseInfo);

        if (rr != null) {
            if (responseInfo.error == RadioError.NONE) {
                // send response
                RadioResponse.sendMessageResponse(rr.mResult, rr.mRequest);
                Rlog.d(TAG, rr.serialString() + "< "
                        + mRadioConfig.requestToString(rr.mRequest));
            } else {
                rr.onError(responseInfo.error, null);
                Rlog.e(TAG, rr.serialString() + "< "
                        + mRadioConfig.requestToString(rr.mRequest) + " error "
                        + responseInfo.error);
            }
        } else {
            Rlog.e(TAG, "setModemsConfigResponse: Error " + responseInfo.toString());
        }
    }

    /**
     * Response function for IRadioConfig.getModemsConfigResponse()
     *
     */
    public void getModemsConfigResponse(RadioResponseInfo info,
            android.hardware.radio.config.V1_1.ModemsConfig modemsConfig) {
    public void getModemsConfigResponse(RadioResponseInfo responseInfo, ModemsConfig modemsConfig) {
        RILRequest rr = mRadioConfig.processResponse(responseInfo);

        if (rr != null) {
            if (responseInfo.error == RadioError.NONE) {
                // send response
                RadioResponse.sendMessageResponse(rr.mResult, modemsConfig);
                Rlog.d(TAG, rr.serialString() + "< "
                        + mRadioConfig.requestToString(rr.mRequest));
            } else {
                rr.onError(responseInfo.error, modemsConfig);
                Rlog.e(TAG, rr.serialString() + "< "
                        + mRadioConfig.requestToString(rr.mRequest) + " error "
                        + responseInfo.error);
            }
        } else {
            Rlog.e(TAG, "getModemsConfigResponse: Error " + responseInfo.toString());
        }
    }
}