diff --git a/core/java/com/android/internal/widget/DigitalClock.java b/core/java/com/android/internal/widget/DigitalClock.java index bc749d8819e8e..2bc9dd1893b07 100644 --- a/core/java/com/android/internal/widget/DigitalClock.java +++ b/core/java/com/android/internal/widget/DigitalClock.java @@ -34,6 +34,7 @@ import android.view.View; import android.widget.RelativeLayout; import android.widget.TextView; +import java.lang.ref.WeakReference; import java.text.DateFormatSymbols; import java.util.Calendar; @@ -54,26 +55,41 @@ public class DigitalClock extends RelativeLayout { private TextView mTimeDisplayForeground; private AmPm mAmPm; private ContentObserver mFormatChangeObserver; - private boolean mLive = true; - private boolean mAttached; + private int mAttached = 0; // for debugging - tells us whether attach/detach is unbalanced /* called by system on minute ticks */ private final Handler mHandler = new Handler(); - private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (mLive && intent.getAction().equals( - Intent.ACTION_TIMEZONE_CHANGED)) { - mCalendar = Calendar.getInstance(); - } - // Post a runnable to avoid blocking the broadcast. - mHandler.post(new Runnable() { - public void run() { - updateTime(); + private BroadcastReceiver mIntentReceiver; + + private static class TimeChangedReceiver extends BroadcastReceiver { + private WeakReference mClock; + private Context mContext; + + public TimeChangedReceiver(DigitalClock clock) { + mClock = new WeakReference(clock); + mContext = clock.getContext(); + } + + @Override + public void onReceive(Context context, Intent intent) { + // Post a runnable to avoid blocking the broadcast. + final boolean timezoneChanged = + intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED); + final DigitalClock clock = mClock.get(); + if (clock != null) { + clock.mHandler.post(new Runnable() { + public void run() { + if (timezoneChanged) { + clock.mCalendar = Calendar.getInstance(); } + clock.updateTime(); + } }); + } else { + mContext.unregisterReceiver(this); } - }; + } + }; static class AmPm { private TextView mAmPm; @@ -99,14 +115,23 @@ public class DigitalClock extends RelativeLayout { } } - private class FormatChangeObserver extends ContentObserver { - public FormatChangeObserver() { + private static class FormatChangeObserver extends ContentObserver { + private WeakReference mClock; + private Context mContext; + public FormatChangeObserver(DigitalClock clock) { super(new Handler()); + mClock = new WeakReference(clock); + mContext = clock.getContext(); } @Override public void onChange(boolean selfChange) { - setDateFormat(); - updateTime(); + DigitalClock digitalClock = mClock.get(); + if (digitalClock != null) { + digitalClock.setDateFormat(); + digitalClock.updateTime(); + } else { + mContext.getContentResolver().unregisterContentObserver(this); + } } } @@ -139,11 +164,11 @@ public class DigitalClock extends RelativeLayout { protected void onAttachedToWindow() { super.onAttachedToWindow(); - if (mAttached) return; - mAttached = true; + mAttached++; - if (mLive) { - /* monitor time ticks, time changed, timezone */ + /* monitor time ticks, time changed, timezone */ + if (mIntentReceiver == null) { + mIntentReceiver = new TimeChangedReceiver(this); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_TIME_TICK); filter.addAction(Intent.ACTION_TIME_CHANGED); @@ -152,9 +177,11 @@ public class DigitalClock extends RelativeLayout { } /* monitor 12/24-hour display preference */ - mFormatChangeObserver = new FormatChangeObserver(); - mContext.getContentResolver().registerContentObserver( - Settings.System.CONTENT_URI, true, mFormatChangeObserver); + if (mFormatChangeObserver == null) { + mFormatChangeObserver = new FormatChangeObserver(this); + mContext.getContentResolver().registerContentObserver( + Settings.System.CONTENT_URI, true, mFormatChangeObserver); + } updateTime(); } @@ -163,16 +190,19 @@ public class DigitalClock extends RelativeLayout { protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - if (!mAttached) return; - mAttached = false; + mAttached--; - if (mLive) { + if (mIntentReceiver != null) { mContext.unregisterReceiver(mIntentReceiver); } - mContext.getContentResolver().unregisterContentObserver( - mFormatChangeObserver); - } + if (mFormatChangeObserver != null) { + mContext.getContentResolver().unregisterContentObserver( + mFormatChangeObserver); + } + mFormatChangeObserver = null; + mIntentReceiver = null; + } void updateTime(Calendar c) { mCalendar = c; @@ -180,9 +210,7 @@ public class DigitalClock extends RelativeLayout { } private void updateTime() { - if (mLive) { - mCalendar.setTimeInMillis(System.currentTimeMillis()); - } + mCalendar.setTimeInMillis(System.currentTimeMillis()); CharSequence newTime = DateFormat.format(mFormat, mCalendar); mTimeDisplayBackground.setText(newTime); @@ -195,8 +223,4 @@ public class DigitalClock extends RelativeLayout { ? M24 : M12; mAmPm.setShowAmPm(mFormat.equals(M12)); } - - void setLive(boolean live) { - mLive = live; - } } diff --git a/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java b/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java index 840c5e198e21c..c4feefd2e32c8 100644 --- a/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java +++ b/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java @@ -62,8 +62,8 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree */ private static final int AWAKE_POKE_MILLIS = 30000; - private final KeyguardScreenCallback mCallback; - private final LockPatternUtils mLockPatternUtils; + private KeyguardScreenCallback mCallback; + private LockPatternUtils mLockPatternUtils; private KeyguardUpdateMonitor mUpdateMonitor; private TextView mTopHeader; @@ -159,7 +159,10 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree if (mCheckingDialog != null) { mCheckingDialog.hide(); } - mUpdateMonitor.removeCallback(this); + mUpdateMonitor.removeCallback(this); // this must be first + mCallback = null; + mLockPatternUtils = null; + mUpdateMonitor = null; } /** {@inheritDoc} */ diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java index 70a4b20bb61ad..fcd4bf397d18d 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java @@ -231,8 +231,8 @@ public class KeyguardViewManager implements KeyguardWindowController { mKeyguardHost.postDelayed(new Runnable() { public void run() { synchronized (KeyguardViewManager.this) { - mKeyguardHost.removeView(lastView); lastView.cleanUp(); + mKeyguardHost.removeView(lastView); } } }, 500); diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java index 822be468ac668..886b85fbb54cf 100644 --- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java +++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java @@ -495,8 +495,10 @@ public class LockPatternKeyguardView extends KeyguardViewBase { public void cleanUp() { ((KeyguardScreen) mLockScreen).onPause(); ((KeyguardScreen) mLockScreen).cleanUp(); + this.removeView(mLockScreen); ((KeyguardScreen) mUnlockScreen).onPause(); ((KeyguardScreen) mUnlockScreen).cleanUp(); + this.removeView(mUnlockScreen); } private boolean isSecure() { diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java index 79fbe0e79f12a..b55d3b94615b7 100644 --- a/policy/src/com/android/internal/policy/impl/LockScreen.java +++ b/policy/src/com/android/internal/policy/impl/LockScreen.java @@ -59,9 +59,9 @@ class LockScreen extends LinearLayout implements KeyguardScreen, private Status mStatus = Status.Normal; - private final LockPatternUtils mLockPatternUtils; - private final KeyguardUpdateMonitor mUpdateMonitor; - private final KeyguardScreenCallback mCallback; + private LockPatternUtils mLockPatternUtils; + private KeyguardUpdateMonitor mUpdateMonitor; + private KeyguardScreenCallback mCallback; private SlidingTab mSlidingTab; private TextView mScreenLocked; @@ -311,8 +311,8 @@ class LockScreen extends LinearLayout implements KeyguardScreen, setFocusableInTouchMode(true); setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); - updateMonitor.registerInfoCallback(this); - updateMonitor.registerSimStateCallback(this); + mUpdateMonitor.registerInfoCallback(this); + mUpdateMonitor.registerSimStateCallback(this); mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE); mSilentMode = isSilentMode(); @@ -656,7 +656,10 @@ class LockScreen extends LinearLayout implements KeyguardScreen, /** {@inheritDoc} */ public void cleanUp() { - mUpdateMonitor.removeCallback(this); + mUpdateMonitor.removeCallback(this); // this must be first + mLockPatternUtils = null; + mUpdateMonitor = null; + mCallback = null; } /** {@inheritDoc} */ diff --git a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java index 5d1455e5b9350..be4032c2beca6 100644 --- a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java +++ b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java @@ -62,9 +62,9 @@ class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient private int mTotalFailedPatternAttempts = 0; private CountDownTimer mCountdownTimer = null; - private final LockPatternUtils mLockPatternUtils; - private final KeyguardUpdateMonitor mUpdateMonitor; - private final KeyguardScreenCallback mCallback; + private LockPatternUtils mLockPatternUtils; + private KeyguardUpdateMonitor mUpdateMonitor; + private KeyguardScreenCallback mCallback; /** * whether there is a fallback option available when the pattern is forgotten. @@ -359,6 +359,9 @@ class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient /** {@inheritDoc} */ public void cleanUp() { mUpdateMonitor.removeCallback(this); + mLockPatternUtils = null; + mUpdateMonitor = null; + mCallback = null; } @Override