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

Commit c10a3e2f authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Change to use new slot related RIL APIs."

parents 74f2b39b ce32bfe7
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -662,7 +662,7 @@ public class RadioIndication extends IRadioIndication.Stub {

        if (RIL.RILJ_LOGD) mRil.unsljLogRet(RIL_UNSOL_ICC_SLOT_STATUS, iccSlotStatus);

        mRil.mIccStatusChangedRegistrants.notifyRegistrants(
        mRil.mIccSlotStatusChangedRegistrants.notifyRegistrants(
                new AsyncResult(null, iccSlotStatus, null));
    }

+4 −1
Original line number Diff line number Diff line
@@ -172,6 +172,7 @@ public class SimulatedCommands extends BaseCommands

    @Override
    public void getIccCardStatus(Message result) {
        SimulatedCommandsVerifier.getInstance().getIccCardStatus(result);
        if (mIccCardStatus != null) {
            resultSuccess(result, mIccCardStatus);
        } else {
@@ -185,10 +186,12 @@ public class SimulatedCommands extends BaseCommands

    @Override
    public void getIccSlotsStatus(Message result) {
        SimulatedCommandsVerifier.getInstance().getIccSlotsStatus(result);
        if (mIccSlotStatus != null) {
            resultSuccess(result, mIccSlotStatus);
        } else {
            resultFail(result, null, new RuntimeException("IccSlotStatus not set"));
            resultFail(result, null,
                    new CommandException(CommandException.Error.REQUEST_NOT_SUPPORTED));
        }
    }

+1 −1
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ public class IccCardStatus {
    public int        mGsmUmtsSubscriptionAppIndex;
    public int        mCdmaSubscriptionAppIndex;
    public int        mImsSubscriptionAppIndex;
    public int        physicalSlotIndex;
    public int        physicalSlotIndex = UiccController.INVALID_SLOT_ID;
    public String     atr;
    public String     iccid;

+178 −49
Original line number Diff line number Diff line
@@ -27,12 +27,17 @@ import android.telephony.Rlog;
import android.telephony.TelephonyManager;
import android.text.format.Time;

import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.PhoneConstants;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;

/**
 * This class is responsible for keeping all knowledge about
@@ -76,28 +81,29 @@ import java.util.LinkedList;
 */
public class UiccController extends Handler {
    private static final boolean DBG = true;
    private static final boolean VDBG = false; //STOPSHIP if true
    private static final String LOG_TAG = "UiccController";

    public static final int INVALID_SLOT_ID = -1;

    public static final int APP_FAM_3GPP =  1;
    public static final int APP_FAM_3GPP2 = 2;
    public static final int APP_FAM_IMS   = 3;

    private static final int EVENT_ICC_STATUS_CHANGED = 1;
    private static final int EVENT_SLOT_STATUS_CHANGED = 2;
    private static final int EVENT_ICC_OR_SLOT_STATUS_CHANGED = 3;
    private static final int EVENT_GET_ICC_STATUS_DONE = 4;
    private static final int EVENT_RADIO_UNAVAILABLE = 5;
    private static final int EVENT_SIM_REFRESH = 6;

    // this still needs to be here, because on bootup we dont know which index maps to which
    // UiccSlot
    private static final int EVENT_GET_ICC_STATUS_DONE = 3;
    private static final int EVENT_GET_SLOT_STATUS_DONE = 4;
    private static final int EVENT_RADIO_ON = 5;
    private static final int EVENT_RADIO_AVAILABLE = 6;
    private static final int EVENT_RADIO_UNAVAILABLE = 7;
    private static final int EVENT_SIM_REFRESH = 8;

    // this needs to be here, because on bootup we dont know which index maps to which UiccSlot
    private CommandsInterface[] mCis;
    // todo: add a system property/mk file constant for this
    private UiccSlot[] mUiccSlots = new UiccSlot[TelephonyManager.getDefault().getPhoneCount()];
    // flag to indicate if UiccSlots have been initialized. This will be set to true only after the
    // first slots status is received. That is when phoneId to slotId mapping is known as well.
    // todo: assuming true for now and hardcoding the mapping between UiccSlot index and phoneId
    private boolean mUiccSlotsInitialized = true;
    private UiccSlot[] mUiccSlots;
    private int[] mPhoneIdToSlotId;
    private boolean mIsSlotStatusSupported = true;

    private static final Object mLock = new Object();
    private static UiccController mInstance;
@@ -118,7 +124,7 @@ public class UiccController extends Handler {
                throw new RuntimeException("MSimUiccController.make() should only be called once");
            }
            mInstance = new UiccController(c, ci);
            return (UiccController)mInstance;
            return mInstance;
        }
    }

@@ -126,37 +132,41 @@ public class UiccController extends Handler {
        if (DBG) log("Creating UiccController");
        mContext = c;
        mCis = ci;
        if (VDBG) {
            log("config_num_physical_slots = " + c.getResources().getInteger(
                    com.android.internal.R.integer.config_num_physical_slots));
        }
        mUiccSlots = new UiccSlot[c.getResources().getInteger(
                com.android.internal.R.integer.config_num_physical_slots)];
        mPhoneIdToSlotId = new int[ci.length];
        Arrays.fill(mPhoneIdToSlotId, INVALID_SLOT_ID);
        if (VDBG) logPhoneIdToSlotIdMapping();
        for (int i = 0; i < mCis.length; i++) {
            // todo: get rid of this once hardcoding of mapping between UiccSlot index and phoneId
            // is removed, instead do this when icc/slot status is received
            mUiccSlots[i] = new UiccSlot(c, true /* isActive */);

            Integer index = i;
            mCis[i].registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, index);
            // todo: add registration for slot status changed here
            mCis[i].registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, i);
            // slot status should be the same on all RILs; request it only for phoneId 0
            if (i == 0) {
                mCis[i].registerForIccSlotStatusChanged(this, EVENT_SLOT_STATUS_CHANGED, i);
            }

            // TODO remove this once modem correctly notifies the unsols
            // If the device is unencrypted or has been decrypted or FBE is supported,
            // i.e. not in cryptkeeper bounce, read SIM when radio state isavailable.
            // i.e. not in CryptKeeper bounce, read SIM when radio state is available.
            // Else wait for radio to be on. This is needed for the scenario when SIM is locked --
            // to avoid overlap of CryptKeeper and SIM unlock screen.
            if (!StorageManager.inCryptKeeperBounce()) {
                mCis[i].registerForAvailable(this, EVENT_ICC_OR_SLOT_STATUS_CHANGED, index);
                mCis[i].registerForAvailable(this, EVENT_RADIO_AVAILABLE, i);
            } else {
                mCis[i].registerForOn(this, EVENT_ICC_OR_SLOT_STATUS_CHANGED, index);
                mCis[i].registerForOn(this, EVENT_RADIO_ON, i);
            }
            mCis[i].registerForNotAvailable(this, EVENT_RADIO_UNAVAILABLE, index);
            mCis[i].registerForIccRefresh(this, EVENT_SIM_REFRESH, index);
            mCis[i].registerForNotAvailable(this, EVENT_RADIO_UNAVAILABLE, i);
            mCis[i].registerForIccRefresh(this, EVENT_SIM_REFRESH, i);
        }

        mLauncher = new UiccStateChangedLauncher(c, this);
    }

    private int getSlotIdFromPhoneId(int phoneId) {
        // todo: implement (if mUiccSlotsInitialized || if info available about that specific
        // phoneId which will be the case if sim status for that phoneId is received first)
        // else return invalid slotId
        return phoneId;
        return mPhoneIdToSlotId[phoneId];
    }

    public static UiccController getInstance() {
@@ -198,20 +208,11 @@ public class UiccController extends Handler {
     */
    public UiccCard getUiccCardForPhone(int phoneId) {
        synchronized (mLock) {
            int slotId = getSlotIdFromPhoneId(phoneId);
            return getUiccCardForSlot(slotId);
        }
            UiccSlot uiccSlot = getUiccSlotForPhone(phoneId);
            if (uiccSlot != null) {
                return uiccSlot.getUiccCard();
            }

    /**
     * API to get an array of all UiccSlots, which represents all physical slots on the device
     * @return array of all UiccSlots
     */
    public UiccSlot[] getUiccSlots() {
        // Return cloned array since we don't want to give out reference
        // to internal data structure.
        synchronized (mLock) {
            return mUiccSlots.clone();
            return null;
        }
    }

@@ -296,18 +297,45 @@ public class UiccController extends Handler {
            AsyncResult ar = (AsyncResult)msg.obj;
            switch (msg.what) {
                case EVENT_ICC_STATUS_CHANGED:
                case EVENT_ICC_OR_SLOT_STATUS_CHANGED:
                    if (DBG) log("Received EVENT_ICC_STATUS_CHANGED, calling getIccCardStatus");
                    mCis[phoneId].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE,
                            phoneId));
                    break;
                case EVENT_RADIO_AVAILABLE:
                case EVENT_RADIO_ON:
                    if (DBG) {
                        log("Received EVENT_RADIO_AVAILABLE/EVENT_RADIO_ON, calling "
                                + "getIccCardStatus");
                    }
                    mCis[phoneId].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE,
                            phoneId));
                    // slot status should be the same on all RILs; request it only for phoneId 0
                    if (phoneId == 0) {
                        if (DBG) {
                            log("Received EVENT_RADIO_AVAILABLE/EVENT_RADIO_ON for phoneId 0, "
                                    + "calling getIccSlotsStatus");
                        }
                        mCis[phoneId].getIccSlotsStatus(obtainMessage(EVENT_GET_SLOT_STATUS_DONE,
                                phoneId));
                    }
                    break;
                case EVENT_GET_ICC_STATUS_DONE:
                    if (DBG) log("Received EVENT_GET_ICC_STATUS_DONE");
                    onGetIccCardStatusDone(ar, phoneId);
                    break;
                case EVENT_SLOT_STATUS_CHANGED:
                case EVENT_GET_SLOT_STATUS_DONE:
                    if (DBG) {
                        log("Received EVENT_SLOT_STATUS_CHANGED or EVENT_GET_SLOT_STATUS_DONE");
                    }
                    onGetSlotStatusDone(ar);
                    break;
                case EVENT_RADIO_UNAVAILABLE:
                    if (DBG) log("EVENT_RADIO_UNAVAILABLE, dispose card");
                    mUiccSlots[getSlotIdFromPhoneId(phoneId)].onRadioStateUnavailable();
                    UiccSlot uiccSlot = getUiccSlotForPhone(phoneId);
                    if (uiccSlot != null) {
                        uiccSlot.onRadioStateUnavailable();
                    }
                    mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, phoneId, null));
                    break;
                case EVENT_SIM_REFRESH:
@@ -368,11 +396,112 @@ public class UiccController extends Handler {

        IccCardStatus status = (IccCardStatus)ar.result;

        mUiccSlots[getSlotIdFromPhoneId(index)].update(mContext, mCis[index], status, index);
        int slotId = status.physicalSlotIndex;
        if (VDBG) log("onGetIccCardStatusDone: phoneId " + index + " physicalSlotIndex " + slotId);
        if (slotId == INVALID_SLOT_ID) {
            slotId = index;
            mPhoneIdToSlotId[index] = slotId;
        }

        if (VDBG) logPhoneIdToSlotIdMapping();

        if (mUiccSlots[slotId] == null) {
            if (VDBG) {
                log("Creating mUiccSlots[" + slotId + "]; mUiccSlots.length = "
                        + mUiccSlots.length);
            }
            mUiccSlots[slotId] = new UiccSlot(mContext, true);
        }

        mUiccSlots[slotId].update(mCis[index], status, index);

        if (DBG) log("Notifying IccChangedRegistrants");
        mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null));
    }

    private synchronized void onGetSlotStatusDone(AsyncResult ar) {
        if (!mIsSlotStatusSupported) {
            if (VDBG) log("onGetSlotStatusDone: ignoring since mIsSlotStatusSupported is false");
            return;
        }
        Throwable e = ar.exception;
        if (e != null) {
            if (!(e instanceof CommandException) || ((CommandException) e).getCommandError()
                    != CommandException.Error.REQUEST_NOT_SUPPORTED) {
                // this is not expected; there should be no exception other than
                // REQUEST_NOT_SUPPORTED
                Rlog.e(LOG_TAG, "Unexpected error getting slot status.", ar.exception);
            } else {
                // REQUEST_NOT_SUPPORTED
                log("onGetSlotStatusDone: request not supported; marking mIsSlotStatusSupported "
                        + "to false");
                mIsSlotStatusSupported = false;
            }
            return;
        }

        ArrayList<IccSlotStatus> status = (ArrayList<IccSlotStatus>) ar.result;

        int numActiveSlots = 0;
        for (int i = 0; i < status.size(); i++) {
            IccSlotStatus iss = status.get(i);
            boolean isActive = (iss.slotState == IccSlotStatus.SlotState.SLOTSTATE_ACTIVE);
            if (isActive) {
                numActiveSlots++;

                // sanity check: logicalSlotIndex should be valid for an active slot
                if (!isValidCardIndex(iss.logicalSlotIndex)) {
                    throw new RuntimeException("Logical slot index " + iss.logicalSlotIndex
                            + " invalid for physical slot " + i);
                }
                mPhoneIdToSlotId[iss.logicalSlotIndex] = i;
            }

            if (mUiccSlots[i] == null) {
                if (VDBG) {
                    log("Creating mUiccSlot[" + i + "]; mUiccSlots.length = " + mUiccSlots.length);
                }
                mUiccSlots[i] = new UiccSlot(mContext, isActive);
            }

            mUiccSlots[i].update(isActive ? mCis[iss.logicalSlotIndex] : null, iss);
        }

        if (VDBG) logPhoneIdToSlotIdMapping();

        // sanity check: number of active slots should be valid
        if (numActiveSlots != mPhoneIdToSlotId.length) {
            throw new RuntimeException("Number of active slots " + numActiveSlots
                    + " does not match the expected value " + mPhoneIdToSlotId.length);
        }

        // sanity check: slotIds should be unique in mPhoneIdToSlotId
        Set<Integer> slotIds = new HashSet<>();
        for (int slotId : mPhoneIdToSlotId) {
            if (slotIds.contains(slotId)) {
                throw new RuntimeException("slotId " + slotId + " mapped to muptiple phoneIds");
            }
            slotIds.add(slotId);
        }
    }

    private void logPhoneIdToSlotIdMapping() {
        log("mPhoneIdToSlotId mapping:");
        for (int i = 0; i < mPhoneIdToSlotId.length; i++) {
            log("    phoneId " + i + " slotId " + mPhoneIdToSlotId[i]);
        }
    }
    /**
     * Slots are initialized when none of them are null.
     * todo: is this even needed?
     */
    private synchronized boolean areSlotsInitialized() {
        for (UiccSlot slot : mUiccSlots) {
            if (slot == null) {
                return false;
            }
        }
        return true;
    }

    private void onSimRefresh(AsyncResult ar, Integer index) {
@@ -387,7 +516,7 @@ public class UiccController extends Handler {
        }

        IccRefreshResponse resp = (IccRefreshResponse) ar.result;
        Rlog.d(LOG_TAG, "onSimRefresh: " + resp);
        log("onSimRefresh: " + resp);

        if (resp == null) {
            Rlog.e(LOG_TAG, "onSimRefresh: received without input");
@@ -400,7 +529,7 @@ public class UiccController extends Handler {
            return;
        }

        Rlog.d(LOG_TAG, "Handling refresh: " + resp);
        log("Handling refresh: " + resp);
        boolean changed = false;
        switch(resp.refreshResult) {
            case IccRefreshResponse.REFRESH_RESULT_RESET:
+57 −5
Original line number Diff line number Diff line
@@ -57,6 +57,8 @@ public class UiccSlot extends Handler {
    private CommandsInterface mCi;
    private UiccCard mUiccCard;
    private RadioState mLastRadioState = RadioState.RADIO_UNAVAILABLE;
    private boolean mIsEuicc;
    private String mIccId;

    private RegistrantList mAbsentRegistrants = new RegistrantList();

@@ -75,12 +77,12 @@ public class UiccSlot extends Handler {
    /**
     * Update slot. The main trigger for this is a change in the ICC Card status.
     */
    public void update(Context c, CommandsInterface ci, IccCardStatus ics, int phoneId) {
    public void update(CommandsInterface ci, IccCardStatus ics, int phoneId) {
        synchronized (mLock) {
            CardState oldState = mCardState;
            mCardState = ics.mCardState;
            parseAtr(ics.atr);
            mCi = ci;
            mContext = c;

            RadioState radioState = mCi.getRadioState();
            if (DBG) {
@@ -96,7 +98,7 @@ public class UiccSlot extends Handler {
                    sendMessage(obtainMessage(EVENT_CARD_REMOVED, null));
                }

                // todo: broadcast sim state changed for absent/unknown
                // todo: broadcast sim state changed for absent/unknown when IccCardProxy is removed

                // no card present in the slot now; dispose card and make mUiccCard null
                mUiccCard.dispose();
@@ -115,7 +117,12 @@ public class UiccSlot extends Handler {
                    mUiccCard.dispose();
                }

                if (!mIsEuicc) {
                    mUiccCard = new UiccCard(mContext, mCi, ics, phoneId);
                } else {
                    // todo: initialize new EuiccCard object here
                    //mUiccCard = new EuiccCard();
                }
            } else {
                if (mUiccCard != null) {
                    mUiccCard.update(mContext, mCi, ics);
@@ -125,6 +132,51 @@ public class UiccSlot extends Handler {
        }
    }

    /**
     * Update slot based on IccSlotStatus.
     */
    public void update(CommandsInterface ci, IccSlotStatus iss) {
        log("slotStatus update");
        synchronized (mLock) {
            mCi = ci;
            if (iss.slotState == IccSlotStatus.SlotState.SLOTSTATE_INACTIVE) {
                if (mActive) {
                    mActive = false;
                    // treat as radio state unavailable
                    onRadioStateUnavailable();
                }
                parseAtr(iss.atr);
                mCardState = iss.cardState;
                mIccId = iss.iccid;
            } else if (!mActive && iss.slotState == IccSlotStatus.SlotState.SLOTSTATE_ACTIVE) {
                mActive = true;
                // todo - ignoring these fields for now; relying on sim state changed to update
                // these
                //      iss.atr;
                //      iss.cardState;
                //      iss.iccid;
                //      iss.logicalSlotIndex;
            }
        }
    }

    private void parseAtr(String atr) {
        // todo - parse atr and set mIsEuicc based on it
        mIsEuicc = false;
    }

    public boolean isEuicc() {
        return mIsEuicc;
    }

    public boolean isActive() {
        return mActive;
    }

    public String getIccId() {
        return mIccId;
    }

    @Override
    protected void finalize() {
        if (DBG) log("UiccSlot finalized");
@@ -246,7 +298,7 @@ public class UiccSlot extends Handler {
        }
        mUiccCard = null;

        // todo: broadcast sim state changed for absent/unknown
        // todo: broadcast sim state changed for absent/unknown when IccCardProxy is removed

        mCardState = CardState.CARDSTATE_ABSENT;
        mLastRadioState = RadioState.RADIO_UNAVAILABLE;
Loading