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

Commit 42b432d8 authored by Jim Miller's avatar Jim Miller
Browse files

Partial Fix for 2416967: Fix potential memory leak in PasswordUnlockScreen.

PasswordUnlockScreen was previously registering for multiple callbacks which *sometimes*
caused a memory leak because a reference stuck around in the callback list.  I wasn't able to
track down the cause, but it looks like an interaction between switching between various lockscreen
modes and ordering of CONFIGURATION_CHANGED events.

I found one instance where the callback was being registered twice (fixed).  However, I'm
still able to reproduce the bug but far less frequently.

As a workaround, I've added code to prevent adding additional callbacks and added logging to
detect when a callback is already registered.

Also fixed an instance where we'd recreate the password unlock screen in LockPatternKeyguardView.updateScreen()
so it should be quite a bit faster switching orientations now.

Renamed UnlockScreen.java to PatternUnlockScreen.java for consistency.
parent d13e2133
Loading
Loading
Loading
Loading
+15 −3
Original line number Diff line number Diff line
@@ -492,7 +492,11 @@ public class KeyguardUpdateMonitor {
     * @param callback The callback.
     */
    public void registerConfigurationChangeCallback(ConfigurationChangeCallback callback) {
        if (!mConfigurationChangeCallbacks.contains(callback)) {
            mConfigurationChangeCallbacks.add(callback);
        } else {
            Log.e(TAG, "Object tried to add another CONFIG callback", new Exception("Whoops"));
        }
    }

    /**
@@ -501,7 +505,11 @@ public class KeyguardUpdateMonitor {
     * @param callback The callback.
     */
    public void registerInfoCallback(InfoCallback callback) {
        if (!mInfoCallbacks.contains(callback)) {
            mInfoCallbacks.add(callback);
        } else {
            Log.e(TAG, "Object tried to add another INFO callback", new Exception("Whoops"));
        }
    }

    /**
@@ -509,7 +517,11 @@ public class KeyguardUpdateMonitor {
     * @param callback The callback.
     */
    public void registerSimStateCallback(SimStateCallback callback) {
        if (!mSimStateCallbacks.contains(callback)) {
            mSimStateCallbacks.add(callback);
        } else {
            Log.e(TAG, "Object tried to add another SIM callback", new Exception("Whoops"));
        }
    }

    public IccCard.State getSimState() {
+4 −6
Original line number Diff line number Diff line
@@ -173,8 +173,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase

        if (mUnlockScreen == null) {
            Log.w(TAG, "no unlock screen when receiving AccountManager information");
        } else if (mUnlockScreen instanceof UnlockScreen) {
            ((UnlockScreen)mUnlockScreen).setEnableFallback(mEnableFallback);
        } else if (mUnlockScreen instanceof PatternUnlockScreen) {
            ((PatternUnlockScreen)mUnlockScreen).setEnableFallback(mEnableFallback);
        }
    }

@@ -411,7 +411,6 @@ public class LockPatternKeyguardView extends KeyguardViewBase
        }
    }


    private void recreateScreens() {
        if (mLockScreen.getVisibility() == View.VISIBLE) {
            ((KeyguardScreen) mLockScreen).onPause();
@@ -504,8 +503,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase
        mMode = mode;

        final View goneScreen = (mode == Mode.LockScreen) ? mUnlockScreen : mLockScreen;
        final View visibleScreen = (mode == Mode.LockScreen)
                ? mLockScreen : getUnlockScreenForCurrentUnlockMode();
        final View visibleScreen = (mode == Mode.LockScreen) ? mLockScreen : mUnlockScreen;

        // do this before changing visibility so focus isn't requested before the input
        // flag is set
@@ -544,7 +542,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase
        mIsPortrait = getResources().getBoolean(R.bool.lockscreen_isPortrait);

        if (unlockMode == UnlockMode.Pattern) {
            UnlockScreen view = new UnlockScreen(
            PatternUnlockScreen view = new PatternUnlockScreen(
                    mContext,
                    mLockPatternUtils,
                    mUpdateMonitor,
+8 −8
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen
    private LockPatternUtils mLockPatternUtils;
    private PasswordEntryKeyboardView mKeyboardView;
    private PasswordEntryKeyboardHelper mKeyboardHelper;
    private boolean mIsInPortrait;

    // To avoid accidental lockout due to events while the device in in the pocket, ignore
    // any passwords with length less than or equal to this length.
@@ -66,10 +67,10 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen
        mCreatedWithKeyboardOpen = mUpdateMonitor.isKeyboardOpen();

        LayoutInflater layoutInflater = LayoutInflater.from(context);
        if (mCreatedWithKeyboardOpen) {
            layoutInflater.inflate(R.layout.keyguard_screen_password_landscape, this, true);
        } else {
        if (mUpdateMonitor.isInPortrait()) {
            layoutInflater.inflate(R.layout.keyguard_screen_password_portrait, this, true);
        } else {
            layoutInflater.inflate(R.layout.keyguard_screen_password_landscape, this, true);
        }

        boolean isAlpha = lockPatternUtils.getPasswordMode() == LockPatternUtils.MODE_PASSWORD;
@@ -85,7 +86,7 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen
        mKeyboardHelper.setKeyboardMode(isAlpha ? PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
                : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);

        updateMonitor.registerConfigurationChangeCallback(this);
        mKeyboardView.setVisibility(mCreatedWithKeyboardOpen ? View.INVISIBLE : View.VISIBLE);
        mPasswordEntry.requestFocus();
    }

@@ -144,13 +145,12 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen
    }

    public void onOrientationChange(boolean inPortrait) {

        mCallback.recreateMe();
    }

    public void onKeyboardChange(boolean isKeyboardOpen) {
        if (isKeyboardOpen != mCreatedWithKeyboardOpen) {
            mCallback.recreateMe();
        }
        // Don't show the soft keyboard when the real keyboard is open
        mKeyboardView.setVisibility(isKeyboardOpen ? View.INVISIBLE : View.VISIBLE);
    }

    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+2 −2
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ import java.util.Date;
 * This is the screen that shows the 9 circle unlock widget and instructs
 * the user how to unlock their device, or make an emergency call.
 */
class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient
class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient
        implements KeyguardScreen, KeyguardUpdateMonitor.ConfigurationChangeCallback,
        KeyguardUpdateMonitor.InfoCallback, KeyguardUpdateMonitor.SimStateCallback {

@@ -160,7 +160,7 @@ class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient
     *        their pattern (e.g they have a google account so we can show them the account based
     *        backup option).
     */
    UnlockScreen(Context context,
    PatternUnlockScreen(Context context,
                 LockPatternUtils lockPatternUtils,
                 KeyguardUpdateMonitor updateMonitor,
                 KeyguardScreenCallback callback,