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

Commit 3f5f83b5 authored by Jim Miller's avatar Jim Miller
Browse files

Fix 5326463: rework sim state handling in lockscreen

Previously it was possible to get an inconsistent state because there
were two paths that updated the lock screen sim state.  This reworks
the data flow to ensure the same path is always used to update the state.

KeyguardUpdateMonitor now correctly updates the entire state of the callee
whenever a new callback is registered.

In addition, KeyguardUpdateMonitor now caches the phone state in order
to avoid a round-trip binder call in updateEmergencyCallButtonState().
This avoids a condition that could make lockscreen unresponsive while
updating the emergency call button state.

KeyguardStatusViewManager also ensures the TransportControlView is
hidden when created to ensure we don't inappropriately update the carrier
line while waiting for the first callbacks to update the status lines.

Change-Id: I6b3975b703a7d90bac8d0fe29fbc0f1d9c5e0e7d
parent dd33bf0e
Loading
Loading
Loading
Loading
+7 −21
Original line number Diff line number Diff line
@@ -936,10 +936,15 @@ public class LockPatternUtils {
     *
     * If there's currently a call in progress, the button will take them to the call
     * @param button the button to update
     * @param the phone state:
     *  {@link TelephonyManager#CALL_STATE_IDLE}
     *  {@link TelephonyManager#CALL_STATE_RINGING}
     *  {@link TelephonyManager#CALL_STATE_OFFHOOK}
     * @param showIfCapable indicates whether the button should be shown if emergency calls are
     *                      possible on the device
     */
    public void updateEmergencyCallButtonState(Button button, boolean showIfCapable) {
    public void updateEmergencyCallButtonState(Button button, int  phoneState,
            boolean showIfCapable) {
        if (isEmergencyCallCapable() && showIfCapable) {
            button.setVisibility(View.VISIBLE);
        } else {
@@ -947,9 +952,8 @@ public class LockPatternUtils {
            return;
        }

        int newState = TelephonyManager.getDefault().getCallState();
        int textId;
        if (newState == TelephonyManager.CALL_STATE_OFFHOOK) {
        if (phoneState == TelephonyManager.CALL_STATE_OFFHOOK) {
            // show "return to call" text and show phone icon
            textId = R.string.lockscreen_return_to_call;
            int phoneCallIcon = R.drawable.stat_sys_phone_call;
@@ -979,22 +983,4 @@ public class LockPatternUtils {
        }
        return false;
    }

    /**
     * Performs concentenation of PLMN/SPN
     * @param plmn
     * @param spn
     * @return
     */
    public static CharSequence getCarrierString(CharSequence plmn, CharSequence spn) {
        if (plmn != null && spn == null) {
            return plmn;
        } else if (plmn != null && spn != null) {
            return plmn + "|" + spn;
        } else if (plmn == null && spn != null) {
            return spn;
        } else {
            return "";
        }
    }
}
+59 −25
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ class KeyguardStatusViewManager implements OnClickListener {
    private static final int CARRIER_HELP_TEXT = 12;
    private static final int HELP_MESSAGE_TEXT = 13;
    private static final int OWNER_INFO = 14;
    private static final int BATTERY_INFO = 15;

    private StatusMode mStatus;
    private String mDateFormatString;
@@ -84,6 +85,9 @@ class KeyguardStatusViewManager implements OnClickListener {
    // last known battery level
    private int mBatteryLevel = 100;

    // last known SIM state
    protected State mSimState;

    private LockPatternUtils mLockPatternUtils;
    private KeyguardUpdateMonitor mUpdateMonitor;
    private Button mEmergencyCallButton;
@@ -98,6 +102,8 @@ class KeyguardStatusViewManager implements OnClickListener {
    private boolean mShowingStatus;
    private KeyguardScreenCallback mCallback;
    private final boolean mShowEmergencyButtonByDefault;
    private CharSequence mPlmn;
    private CharSequence mSpn;

    private class TransientTextManager {
        private TextView mTextView;
@@ -151,6 +157,7 @@ class KeyguardStatusViewManager implements OnClickListener {
    public KeyguardStatusViewManager(View view, KeyguardUpdateMonitor updateMonitor,
                LockPatternUtils lockPatternUtils, KeyguardScreenCallback callback,
                boolean showEmergencyButtonByDefault) {
        if (DEBUG) Log.v(TAG, "KeyguardStatusViewManager()");
        mContainer = view;
        mDateFormatString = getContext().getString(R.string.full_wday_month_day_no_year);
        mLockPatternUtils = lockPatternUtils;
@@ -165,6 +172,12 @@ class KeyguardStatusViewManager implements OnClickListener {
        mTransportView = (TransportControlView) findViewById(R.id.transport);
        mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
        mShowEmergencyButtonByDefault = showEmergencyButtonByDefault;

        // Hide transport control view until we know we need to show it.
        if (mTransportView != null) {
            mTransportView.setVisibility(View.GONE);
        }

        if (mEmergencyCallButton != null) {
            mEmergencyCallButton.setText(R.string.lockscreen_emergency_call);
            mEmergencyCallButton.setOnClickListener(this);
@@ -173,8 +186,6 @@ class KeyguardStatusViewManager implements OnClickListener {

        mTransientTextManager = new TransientTextManager(mCarrierView);

        updateEmergencyCallButtonState();

        resetStatusInfo();
        refreshDate();
        updateOwnerInfo();
@@ -187,10 +198,6 @@ class KeyguardStatusViewManager implements OnClickListener {
                v.setSelected(true);
            }
        }

        // until we get an update...
        setCarrierText(LockPatternUtils.getCarrierString(
                mUpdateMonitor.getTelephonyPlmn(), mUpdateMonitor.getTelephonySpn()));
    }

    private boolean inWidgetMode() {
@@ -248,6 +255,7 @@ class KeyguardStatusViewManager implements OnClickListener {
                case INSTRUCTION_TEXT:
                case CARRIER_HELP_TEXT:
                case HELP_MESSAGE_TEXT:
                case BATTERY_INFO:
                    mTransientTextManager.post(string, 0, INSTRUCTION_RESET_DELAY);
                    break;

@@ -262,15 +270,16 @@ class KeyguardStatusViewManager implements OnClickListener {
    }

    public void onPause() {
        if (DEBUG) Log.v(TAG, "onPause()");
        mUpdateMonitor.removeCallback(mInfoCallback);
        mUpdateMonitor.removeCallback(mSimStateCallback);
    }

    /** {@inheritDoc} */
    public void onResume() {
        if (DEBUG) Log.v(TAG, "onResume()");
        mUpdateMonitor.registerInfoCallback(mInfoCallback);
        mUpdateMonitor.registerSimStateCallback(mSimStateCallback);
        updateEmergencyCallButtonState();
        resetStatusInfo();
    }

@@ -399,7 +408,12 @@ class KeyguardStatusViewManager implements OnClickListener {
     * Determine the current status of the lock screen given the sim state and other stuff.
     */
    public StatusMode getStatusForIccState(IccCard.State simState) {
        boolean missingAndNotProvisioned = (!mUpdateMonitor.isDeviceProvisioned()
        // Since reading the SIM may take a while, we assume it is present until told otherwise.
        if (simState == null) {
            return StatusMode.Normal;
        }

        final boolean missingAndNotProvisioned = (!mUpdateMonitor.isDeviceProvisioned()
                && (simState == IccCard.State.ABSENT || simState == IccCard.State.PERM_DISABLED));

        // Assume we're NETWORK_LOCKED if not provisioned
@@ -435,22 +449,21 @@ class KeyguardStatusViewManager implements OnClickListener {
     *
     * @param simState
     */
    private void updateWithSimStatus(State simState) {
        // The emergency call button no longer appears on this screen.
        if (DEBUG) Log.d(TAG, "updateLayout: status=" + mStatus);
    private void updateCarrierTextWithSimStatus(State simState) {
        if (DEBUG) Log.d(TAG, "updateCarrierTextWithSimStatus(), simState = " + simState);

        CharSequence carrierText = null;
        int carrierHelpTextId = 0;
        mUnlockDisabledDueToSimState = false;
        mStatus = getStatusForIccState(simState);
        mSimState = simState;
        switch (mStatus) {
            case Normal:
                carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(),
                        mUpdateMonitor.getTelephonySpn());
                carrierText = makeCarierString(mPlmn, mSpn);
                break;

            case NetworkLocked:
                carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(),
                carrierText = makeCarierString(mPlmn,
                        getContext().getText(R.string.lockscreen_network_locked_message));
                carrierHelpTextId = R.string.lockscreen_instructions_when_pattern_disabled;
                break;
@@ -467,19 +480,19 @@ class KeyguardStatusViewManager implements OnClickListener {
                break;

            case SimMissingLocked:
                carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(),
                carrierText = makeCarierString(mPlmn,
                        getContext().getText(R.string.lockscreen_missing_sim_message_short));
                carrierHelpTextId = R.string.lockscreen_missing_sim_instructions;
                mUnlockDisabledDueToSimState = true;
                break;

            case SimLocked:
                carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(),
                carrierText = makeCarierString(mPlmn,
                        getContext().getText(R.string.lockscreen_sim_locked_message));
                break;

            case SimPukLocked:
                carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(),
                carrierText = makeCarierString(mPlmn,
                        getContext().getText(R.string.lockscreen_sim_puk_locked_message));
                if (!mLockPatternUtils.isPukUnlockScreenEnable()) {
                    mUnlockDisabledDueToSimState = true;
@@ -489,7 +502,6 @@ class KeyguardStatusViewManager implements OnClickListener {

        setCarrierText(carrierText);
        setCarrierHelpText(carrierHelpTextId);
        updateEmergencyCallButtonState();
    }

    private View findViewById(int id) {
@@ -552,10 +564,11 @@ class KeyguardStatusViewManager implements OnClickListener {
        }
    }

    private void updateEmergencyCallButtonState() {
    private void updateEmergencyCallButtonState(int phoneState) {
        if (mEmergencyCallButton != null) {
            boolean showIfCapable = mShowEmergencyButtonByDefault || mUnlockDisabledDueToSimState;
            mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton, showIfCapable);
            mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton,
                    phoneState, showIfCapable);
        }
    }

@@ -567,7 +580,8 @@ class KeyguardStatusViewManager implements OnClickListener {
            mShowingBatteryInfo = showBatteryInfo;
            mPluggedIn = pluggedIn;
            mBatteryLevel = batteryLevel;
            updateStatusLines(true);
            final MutableInt tmpIcon = new MutableInt(0);
            update(BATTERY_INFO, getAltTextMessage(tmpIcon));
        }

        public void onTimeChanged() {
@@ -575,15 +589,17 @@ class KeyguardStatusViewManager implements OnClickListener {
        }

        public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
            setCarrierText(LockPatternUtils.getCarrierString(plmn, spn));
            mPlmn = plmn;
            mSpn = spn;
            updateCarrierTextWithSimStatus(mSimState);
        }

        public void onRingerModeChanged(int state) {

        }

        public void onPhoneStateChanged(String newState) {
            updateEmergencyCallButtonState();
        public void onPhoneStateChanged(int phoneState) {
            updateEmergencyCallButtonState(phoneState);
        }

        /** {@inheritDoc} */
@@ -595,7 +611,7 @@ class KeyguardStatusViewManager implements OnClickListener {
    private SimStateCallback mSimStateCallback = new SimStateCallback() {

        public void onSimStateChanged(State simState) {
            updateWithSimStatus(simState);
            updateCarrierTextWithSimStatus(simState);
        }
    };

@@ -604,4 +620,22 @@ class KeyguardStatusViewManager implements OnClickListener {
            mCallback.takeEmergencyCallAction();
        }
    }

    /**
     * Performs concentenation of PLMN/SPN
     * @param plmn
     * @param spn
     * @return
     */
    private static CharSequence makeCarierString(CharSequence plmn, CharSequence spn) {
        if (plmn != null && spn == null) {
            return plmn;
        } else if (plmn != null && spn != null) {
            return plmn + "|" + spn;
        } else if (plmn == null && spn != null) {
            return spn;
        } else {
            return "";
        }
    }
}
+19 −7
Original line number Diff line number Diff line
@@ -88,6 +88,8 @@ public class KeyguardUpdateMonitor {
    private ArrayList<InfoCallback> mInfoCallbacks = Lists.newArrayList();
    private ArrayList<SimStateCallback> mSimStateCallbacks = Lists.newArrayList();
    private ContentObserver mContentObserver;
    private int mRingMode;
    private int mPhoneState;

    // messages for the handler
    private static final int MSG_TIME_UPDATE = 301;
@@ -271,13 +273,21 @@ public class KeyguardUpdateMonitor {

    protected void handlePhoneStateChanged(String newState) {
        if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
        if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
            mPhoneState = TelephonyManager.CALL_STATE_IDLE;
        } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) {
            mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK;
        } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) {
            mPhoneState = TelephonyManager.CALL_STATE_RINGING;
        }
        for (int i = 0; i < mInfoCallbacks.size(); i++) {
            mInfoCallbacks.get(i).onPhoneStateChanged(newState);
            mInfoCallbacks.get(i).onPhoneStateChanged(mPhoneState);
        }
    }

    protected void handleRingerModeChange(int mode) {
        if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
        mRingMode = mode;
        for (int i = 0; i < mInfoCallbacks.size(); i++) {
            mInfoCallbacks.get(i).onRingerModeChanged(mode);
        }
@@ -459,7 +469,7 @@ public class KeyguardUpdateMonitor {
         * {@link TelephonyManager@EXTRA_STATE_RINGING}
         * {@link TelephonyManager#EXTRA_STATE_OFFHOOK
         */
        void onPhoneStateChanged(String newState);
        void onPhoneStateChanged(int phoneState);

        /**
         * Called when visibility of lockscreen clock changes, such as when
@@ -484,8 +494,12 @@ public class KeyguardUpdateMonitor {
    public void registerInfoCallback(InfoCallback callback) {
        if (!mInfoCallbacks.contains(callback)) {
            mInfoCallbacks.add(callback);
            // notify the register the current state right away
            // TODO: need call other callback methods
            // Notify listener of the current state
            callback.onRefreshBatteryInfo(shouldShowBatteryInfo(), isPluggedIn(mBatteryStatus),
                    mBatteryLevel);
            callback.onTimeChanged();
            callback.onRingerModeChanged(mRingMode);
            callback.onPhoneStateChanged(mPhoneState);
            callback.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
        } else {
            if (DEBUG) Log.e(TAG, "Object tried to add another INFO callback",
@@ -500,9 +514,7 @@ public class KeyguardUpdateMonitor {
    public void registerSimStateCallback(SimStateCallback callback) {
        if (!mSimStateCallbacks.contains(callback)) {
            mSimStateCallbacks.add(callback);
            // notify the register the current sim state right away,
            // otherwise the register won't receive any state until
            // sim state gets changed again.
            // Notify listener of the current state
            callback.onSimStateChanged(mSimState);
        } else {
            if (DEBUG) Log.e(TAG, "Object tried to add another SIM callback",
+3 −3
Original line number Diff line number Diff line
@@ -1297,7 +1297,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
    }

    /** {@inheritDoc} */
    public void onPhoneStateChanged(String newState) {
    public void onPhoneStateChanged(int phoneState) {
        // ignored
    }