diff options
Diffstat (limited to 'policy')
9 files changed, 821 insertions, 307 deletions
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java index ba1d7f5..70a4b20 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java @@ -113,7 +113,15 @@ public class KeyguardViewManager implements KeyguardWindowController { flags, PixelFormat.TRANSLUCENT); lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN; lp.windowAnimations = com.android.internal.R.style.Animation_LockScreen; - lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; + + if (mContext.getResources().getBoolean(R.bool.config_enableLockScreenRotation)) { + Log.d(TAG, "Rotation sensor for lock screen On!"); + lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR; + } else { + Log.d(TAG, "Rotation sensor for lock screen Off!"); + lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; + } + lp.setTitle("Keyguard"); mWindowLayoutParams = lp; diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java index 88203c3..d19f318 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java @@ -16,6 +16,8 @@ package com.android.internal.policy.impl; +import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT; + import com.android.internal.telephony.IccCard; import com.android.internal.widget.LockPatternUtils; @@ -41,6 +43,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; import android.provider.Settings; +import android.provider.Settings.SettingNotFoundException; import android.telephony.TelephonyManager; import android.util.Config; import android.util.EventLog; @@ -93,6 +96,7 @@ import android.view.WindowManagerPolicy; */ public class KeyguardViewMediator implements KeyguardViewCallback, KeyguardUpdateMonitor.SimStateCallback { + private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000; private final static boolean DEBUG = false && Config.LOGD; private final static boolean DBG_WAKE = DEBUG || true; @@ -133,7 +137,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback, * turning on the keyguard (i.e, the user has this much time to turn * the screen back on without having to face the keyguard). */ - private static final int KEYGUARD_DELAY_MS = 5000; + private static final int KEYGUARD_LOCK_AFTER_DELAY_DEFAULT = 5000; /** * How long we'll wait for the {@link KeyguardViewCallback#keyguardDoneDrawing()} @@ -244,6 +248,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback, * the keyguard. */ private boolean mWaitingUntilKeyguardVisible = false; + private LockPatternUtils mLockPatternUtils; public KeyguardViewMediator(Context context, PhoneWindowManager callback, LocalPowerManager powerManager) { @@ -275,8 +280,9 @@ public class KeyguardViewMediator implements KeyguardViewCallback, mUpdateMonitor.registerSimStateCallback(this); - mKeyguardViewProperties = new LockPatternKeyguardViewProperties( - new LockPatternUtils(mContext), mUpdateMonitor); + mLockPatternUtils = new LockPatternUtils(mContext); + mKeyguardViewProperties + = new LockPatternKeyguardViewProperties(mLockPatternUtils, mUpdateMonitor); mKeyguardViewManager = new KeyguardViewManager( context, WindowManagerImpl.getDefault(), this, @@ -326,15 +332,46 @@ public class KeyguardViewMediator implements KeyguardViewCallback, // to enable it a little bit later (i.e, give the user a chance // to turn the screen back on within a certain window without // having to unlock the screen) - long when = SystemClock.elapsedRealtime() + KEYGUARD_DELAY_MS; - Intent intent = new Intent(DELAYED_KEYGUARD_ACTION); - intent.putExtra("seq", mDelayedShowingSequence); - PendingIntent sender = PendingIntent.getBroadcast(mContext, - 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, - sender); - if (DEBUG) Log.d(TAG, "setting alarm to turn off keyguard, seq = " - + mDelayedShowingSequence); + final ContentResolver cr = mContext.getContentResolver(); + + // From DisplaySettings + long displayTimeout = Settings.System.getInt(cr, SCREEN_OFF_TIMEOUT, + KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT); + + // From SecuritySettings + final long lockAfterTimeout = Settings.Secure.getInt(cr, + Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, + KEYGUARD_LOCK_AFTER_DELAY_DEFAULT); + + // From DevicePolicyAdmin + final long policyTimeout = mLockPatternUtils.getDevicePolicyManager() + .getMaximumTimeToLock(null); + + long timeout; + if (policyTimeout > 0) { + // policy in effect. Make sure we don't go beyond policy limit. + displayTimeout = Math.max(displayTimeout, 0); // ignore negative values + timeout = Math.min(policyTimeout - displayTimeout, lockAfterTimeout); + } else { + timeout = lockAfterTimeout; + } + + if (timeout <= 0) { + // Lock now + mSuppressNextLockSound = true; + doKeyguard(); + } else { + // Lock in the future + long when = SystemClock.elapsedRealtime() + timeout; + Intent intent = new Intent(DELAYED_KEYGUARD_ACTION); + intent.putExtra("seq", mDelayedShowingSequence); + PendingIntent sender = PendingIntent.getBroadcast(mContext, + 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); + mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, + sender); + if (DEBUG) Log.d(TAG, "setting alarm to turn off keyguard, seq = " + + mDelayedShowingSequence); + } } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) { // Do not enable the keyguard if the prox sensor forced the screen off. } else { diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java index 27706ef..822be46 100644 --- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java +++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java @@ -645,7 +645,9 @@ public class LockPatternKeyguardView extends KeyguardViewBase { // Show LockScreen first for any screen other than Pattern unlock. final boolean usingLockPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality() == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; - if (isSecure() && usingLockPattern) { + + boolean showSlidingTab = getResources().getBoolean(R.bool.config_enableSlidingTabFirst); + if (isSecure() && (usingLockPattern || !showSlidingTab)) { return Mode.UnlockScreen; } else { return Mode.LockScreen; @@ -667,6 +669,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase { case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: + case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: currentMode = UnlockMode.Password; break; case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: @@ -687,8 +690,17 @@ public class LockPatternKeyguardView extends KeyguardViewBase { private void showTimeoutDialog() { int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000; + int messageId = R.string.lockscreen_too_many_failed_attempts_dialog_message; + if(getUnlockMode() == UnlockMode.Password) { + if(mLockPatternUtils.getKeyguardStoredPasswordQuality() == + DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) { + messageId = R.string.lockscreen_too_many_failed_pin_attempts_dialog_message; + } else { + messageId = R.string.lockscreen_too_many_failed_password_attempts_dialog_message; + } + } String message = mContext.getString( - R.string.lockscreen_too_many_failed_attempts_dialog_message, + messageId, mUpdateMonitor.getFailedAttempts(), timeoutInSeconds); final AlertDialog dialog = new AlertDialog.Builder(mContext) diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java index a5ef1fa..f8c0aba 100644 --- a/policy/src/com/android/internal/policy/impl/LockScreen.java +++ b/policy/src/com/android/internal/policy/impl/LockScreen.java @@ -59,12 +59,7 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM private final KeyguardUpdateMonitor mUpdateMonitor; private final KeyguardScreenCallback mCallback; - private TextView mCarrier; private SlidingTab mSelector; - private TextView mTime; - private TextView mDate; - private TextView mStatus1; - private TextView mStatus2; private TextView mScreenLocked; private TextView mEmergencyCallText; private Button mEmergencyCallButton; @@ -93,6 +88,8 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM private java.text.DateFormat mTimeFormat; private boolean mEnableMenuKeyInLockScreen; + private StatusView mStatusView; + /** * The status of this lock screen. */ @@ -195,14 +192,7 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM inflater.inflate(R.layout.keyguard_screen_tab_unlock_land, this, true); } - mCarrier = (TextView) findViewById(R.id.carrier); - // Required for Marquee to work - mCarrier.setSelected(true); - mCarrier.setTextColor(0xffffffff); - - mDate = (TextView) findViewById(R.id.date); - mStatus1 = (TextView) findViewById(R.id.status1); - mStatus2 = (TextView) findViewById(R.id.status2); + mStatusView = new StatusView(this, mUpdateMonitor, mLockPatternUtils); mScreenLocked = (TextView) findViewById(R.id.screenLocked); mSelector = (SlidingTab) findViewById(R.id.tab_selector); @@ -220,7 +210,6 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM } }); - setFocusable(true); setFocusableInTouchMode(true); setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); @@ -428,38 +417,11 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM } private void refreshTimeAndDateDisplay() { - mDate.setText(DateFormat.format(mDateFormatString, new Date())); + mStatusView.refreshTimeAndDateDisplay(); } private void updateStatusLines() { - if (!mStatus.showStatusLines() - || (mCharging == null && mNextAlarm == null)) { - mStatus1.setVisibility(View.INVISIBLE); - mStatus2.setVisibility(View.INVISIBLE); - } else if (mCharging != null && mNextAlarm == null) { - // charging only - mStatus1.setVisibility(View.VISIBLE); - mStatus2.setVisibility(View.INVISIBLE); - - mStatus1.setText(mCharging); - mStatus1.setCompoundDrawablesWithIntrinsicBounds(mChargingIcon, null, null, null); - } else if (mNextAlarm != null && mCharging == null) { - // next alarm only - mStatus1.setVisibility(View.VISIBLE); - mStatus2.setVisibility(View.INVISIBLE); - - mStatus1.setText(mNextAlarm); - mStatus1.setCompoundDrawablesWithIntrinsicBounds(mAlarmIcon, null, null, null); - } else if (mCharging != null && mNextAlarm != null) { - // both charging and next alarm - mStatus1.setVisibility(View.VISIBLE); - mStatus2.setVisibility(View.VISIBLE); - - mStatus1.setText(mCharging); - mStatus1.setCompoundDrawablesWithIntrinsicBounds(mChargingIcon, null, null, null); - mStatus2.setText(mNextAlarm); - mStatus2.setCompoundDrawablesWithIntrinsicBounds(mAlarmIcon, null, null, null); - } + mStatusView.updateStatusLines(mStatus.showStatusLines(), mCharging, mChargingIcon, mAlarmIcon); } /** {@inheritDoc} */ @@ -509,7 +471,7 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM switch (status) { case Normal: // text - mCarrier.setText( + mStatusView.setCarrierText( getCarrierString( mUpdateMonitor.getTelephonyPlmn(), mUpdateMonitor.getTelephonySpn())); @@ -518,14 +480,14 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM mScreenLocked.setText(""); // layout - mScreenLocked.setVisibility(View.VISIBLE); + mScreenLocked.setVisibility(View.INVISIBLE); mSelector.setVisibility(View.VISIBLE); mEmergencyCallText.setVisibility(View.GONE); break; case NetworkLocked: // The carrier string shows both sim card status (i.e. No Sim Card) and // carrier's name and/or "Emergency Calls Only" status - mCarrier.setText( + mStatusView.setCarrierText( getCarrierString( mUpdateMonitor.getTelephonyPlmn(), getContext().getText(R.string.lockscreen_network_locked_message))); @@ -538,7 +500,7 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM break; case SimMissing: // text - mCarrier.setText(R.string.lockscreen_missing_sim_message_short); + mStatusView.setCarrierText(R.string.lockscreen_missing_sim_message_short); mScreenLocked.setText(R.string.lockscreen_missing_sim_instructions); // layout @@ -549,7 +511,7 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM break; case SimMissingLocked: // text - mCarrier.setText( + mStatusView.setCarrierText( getCarrierString( mUpdateMonitor.getTelephonyPlmn(), getContext().getText(R.string.lockscreen_missing_sim_message_short))); @@ -563,7 +525,7 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM break; case SimLocked: // text - mCarrier.setText( + mStatusView.setCarrierText( getCarrierString( mUpdateMonitor.getTelephonyPlmn(), getContext().getText(R.string.lockscreen_sim_locked_message))); @@ -575,7 +537,7 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM break; case SimPukLocked: // text - mCarrier.setText( + mStatusView.setCarrierText( getCarrierString( mUpdateMonitor.getTelephonyPlmn(), getContext().getText(R.string.lockscreen_sim_puk_locked_message))); @@ -658,7 +620,6 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM /** {@inheritDoc} */ public void onResume() { resetStatusInfo(mUpdateMonitor); - mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton); } /** {@inheritDoc} */ @@ -676,6 +637,5 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM } public void onPhoneStateChanged(String newState) { - mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton); } } diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java index 39f2917..9db86aa 100644 --- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java +++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java @@ -30,6 +30,7 @@ import android.os.SystemClock; import android.telephony.TelephonyManager; import android.text.method.DigitsKeyListener; import android.text.method.TextKeyListener; +import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; @@ -50,19 +51,25 @@ import com.android.internal.widget.PasswordEntryKeyboardHelper; public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen, View.OnClickListener, KeyguardUpdateMonitor.InfoCallback, OnEditorActionListener { + private static final String TAG = "PasswordUnlockScreen"; private final KeyguardUpdateMonitor mUpdateMonitor; private final KeyguardScreenCallback mCallback; + private boolean mIsAlpha; + private EditText mPasswordEntry; private Button mEmergencyCallButton; private LockPatternUtils mLockPatternUtils; private PasswordEntryKeyboardView mKeyboardView; + private PasswordEntryKeyboardView mKeyboardViewAlpha; private PasswordEntryKeyboardHelper mKeyboardHelper; + private PasswordEntryKeyboardHelper mKeyboardHelperAlpha; private int mCreationOrientation; private int mCreationHardKeyboardHidden; private CountDownTimer mCountdownTimer; - private TextView mTitle; + + private StatusView mStatusView; // 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. @@ -86,36 +93,65 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen layoutInflater.inflate(R.layout.keyguard_screen_password_landscape, this, true); } + mStatusView = new StatusView(this, mUpdateMonitor, mLockPatternUtils); + final int quality = lockPatternUtils.getKeyguardStoredPasswordQuality(); - final boolean isAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == quality - || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == quality; + mIsAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == quality + || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == quality + || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == quality; mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard); + mKeyboardViewAlpha = (PasswordEntryKeyboardView) findViewById(R.id.keyboardAlpha); mPasswordEntry = (EditText) findViewById(R.id.passwordEntry); mPasswordEntry.setOnEditorActionListener(this); mEmergencyCallButton = (Button) findViewById(R.id.emergencyCall); mEmergencyCallButton.setOnClickListener(this); mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton); - mTitle = (TextView) findViewById(R.id.enter_password_label); - mKeyboardHelper = new PasswordEntryKeyboardHelper(context, mKeyboardView, this); - mKeyboardHelper.setKeyboardMode(isAlpha ? PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA - : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC); + mKeyboardHelper = new PasswordEntryKeyboardHelper(context, mKeyboardView, this, false); + if (mKeyboardViewAlpha == null || !mIsAlpha) { + mKeyboardHelper.setKeyboardMode(mIsAlpha ? + PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA + : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC); + mKeyboardView.setVisibility( + mCreationHardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO + ? View.INVISIBLE : View.VISIBLE); + } else { + mKeyboardHelperAlpha = new PasswordEntryKeyboardHelper(context, mKeyboardViewAlpha, + this, false); + mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC); + mKeyboardHelperAlpha.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA); + mKeyboardView.setVisibility(View.GONE); + mKeyboardViewAlpha.setVisibility( + mCreationHardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO + ? View.INVISIBLE : View.VISIBLE); + mPasswordEntry.setWidth(mKeyboardViewAlpha.getLayoutParams().width); + } - mKeyboardView.setVisibility(mCreationHardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO - ? View.INVISIBLE : View.VISIBLE); + mPasswordEntry.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_lock, 0, + 0, 0); mPasswordEntry.requestFocus(); // This allows keyboards with overlapping qwerty/numeric keys to choose just the // numeric keys. - if (isAlpha) { + if (mIsAlpha) { mPasswordEntry.setKeyListener(TextKeyListener.getInstance()); } else { mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance()); + mStatusView.setInstructionText(R.string.keyguard_password_enter_pin_password_code); } mKeyboardHelper.setVibratePattern(mLockPatternUtils.isTactileFeedbackEnabled() ? com.android.internal.R.array.config_virtualKeyVibePattern : 0); + if (mKeyboardHelperAlpha != null) { + mKeyboardHelperAlpha.setVibratePattern(mLockPatternUtils.isTactileFeedbackEnabled() ? + com.android.internal.R.array.config_virtualKeyVibePattern : 0); + } + + // until we get an update... + mStatusView.setCarrierText(LockScreen.getCarrierString( + mUpdateMonitor.getTelephonyPlmn(), + mUpdateMonitor.getTelephonySpn())); } @Override @@ -136,8 +172,12 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen /** {@inheritDoc} */ public void onResume() { + // reset status + mStatusView.resetStatusInfo(mUpdateMonitor, mLockPatternUtils); + // start fresh mPasswordEntry.setText(""); + resetStatusInfo(); mPasswordEntry.requestFocus(); mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton); @@ -174,6 +214,9 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen long deadline = mLockPatternUtils.setLockoutAttemptDeadline(); handleAttemptLockout(deadline); } + mStatusView.setInstructionText(R.string.lockscreen_password_wrong); + } else if (entry.length() > 0) { + mStatusView.setInstructionText(R.string.lockscreen_password_wrong); } mPasswordEntry.setText(""); } @@ -191,14 +234,14 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen String instructions = getContext().getString( R.string.lockscreen_too_many_failed_attempts_countdown, secondsRemaining); - mTitle.setText(instructions); + mStatusView.setInstructionText(instructions); } @Override public void onFinish() { mPasswordEntry.setEnabled(true); - mTitle.setText(R.string.keyguard_password_enter_password_code); mKeyboardView.setEnabled(true); + resetStatusInfo(); } }.start(); } @@ -244,24 +287,41 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen return false; } - public void onPhoneStateChanged(String newState) { - mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton); - } + // ---------- InfoCallback + /** {@inheritDoc} */ public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) { + mStatusView.onRefreshBatteryInfo(showBatteryInfo, pluggedIn, batteryLevel); + } + /** {@inheritDoc} */ + public void onTimeChanged() { + mStatusView.onTimeChanged(); } + /** {@inheritDoc} */ public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { - + mStatusView.onRefreshCarrierInfo(plmn, spn); } + /** {@inheritDoc} */ public void onRingerModeChanged(int state) { - + // not currently used } - public void onTimeChanged() { + // ---------- SimStateCallback + /** {@inheritDoc} */ + public void onPhoneStateChanged(String newState) { + mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton); + } + + private void resetStatusInfo() { + if(mIsAlpha) { + mStatusView.setInstructionText(R.string.keyguard_password_enter_password_code); + } else { + mStatusView.setInstructionText(R.string.keyguard_password_enter_pin_password_code); + } } } diff --git a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java index 418e243..35fa3e5 100644 --- a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java +++ b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java @@ -25,9 +25,6 @@ import android.view.View; import android.view.ViewGroup; import android.view.MotionEvent; import android.widget.Button; -import android.widget.TextView; -import android.text.format.DateFormat; -import android.text.TextUtils; import android.util.Log; import com.android.internal.R; import com.android.internal.telephony.IccCard; @@ -37,7 +34,6 @@ import com.android.internal.widget.LockPatternView; import com.android.internal.widget.LockPatternView.Cell; import java.util.List; -import java.util.Date; /** * This is the screen that shows the 9 circle unlock widget and instructs @@ -75,27 +71,7 @@ class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient */ private boolean mEnableFallback; - private String mDateFormatString; - - private TextView mCarrier; - private TextView mDate; - - // are we showing battery information? - private boolean mShowingBatteryInfo = false; - - // last known plugged in state - private boolean mPluggedIn = false; - - // last known battery level - private int mBatteryLevel = 100; - - private String mNextAlarm = null; - - private String mInstructions = null; - private TextView mStatus1; - private TextView mStatusSep; - private TextView mStatus2; - + private StatusView mStatusView; private LockPatternView mLockPatternView; @@ -133,15 +109,18 @@ class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient private void updateFooter(FooterMode mode) { switch (mode) { case Normal: + Log.d(TAG, "mode normal"); mFooterNormal.setVisibility(View.VISIBLE); mFooterForgotPattern.setVisibility(View.GONE); break; case ForgotLockPattern: + Log.d(TAG, "mode ForgotLockPattern"); mFooterNormal.setVisibility(View.GONE); mFooterForgotPattern.setVisibility(View.VISIBLE); mForgotPatternButton.setVisibility(View.VISIBLE); break; case VerifyUnlocked: + Log.d(TAG, "mode VerifyUnlocked"); mFooterNormal.setVisibility(View.GONE); mFooterForgotPattern.setVisibility(View.GONE); } @@ -180,24 +159,16 @@ class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient mCreationOrientation = configuration.orientation; LayoutInflater inflater = LayoutInflater.from(context); + if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) { + Log.d(TAG, "portrait mode"); inflater.inflate(R.layout.keyguard_screen_unlock_portrait, this, true); } else { + Log.d(TAG, "landscape mode"); inflater.inflate(R.layout.keyguard_screen_unlock_landscape, this, true); } - mCarrier = (TextView) findViewById(R.id.carrier); - mDate = (TextView) findViewById(R.id.date); - - mDateFormatString = getContext().getString(R.string.full_wday_month_day_no_year); - refreshTimeAndDateDisplay(); - - mStatus1 = (TextView) findViewById(R.id.status1); - mStatusSep = (TextView) findViewById(R.id.statusSep); - mStatus2 = (TextView) findViewById(R.id.status2); - - resetStatusInfo(); - + mStatusView = new StatusView(this, mUpdateMonitor, mLockPatternUtils); mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern); @@ -249,15 +220,11 @@ class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient updateMonitor.registerSimStateCallback(this); setFocusableInTouchMode(true); - // Required to get Marquee to work. - mCarrier.setSelected(true); - mCarrier.setTextColor(0xffffffff); - // until we get an update... - mCarrier.setText( - LockScreen.getCarrierString( + mStatusView.setCarrierText(LockScreen.getCarrierString( mUpdateMonitor.getTelephonyPlmn(), mUpdateMonitor.getTelephonySpn())); + } private void refreshEmergencyButtonText() { @@ -270,88 +237,6 @@ class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient mEnableFallback = state; } - private void resetStatusInfo() { - mInstructions = null; - mShowingBatteryInfo = mUpdateMonitor.shouldShowBatteryInfo(); - mPluggedIn = mUpdateMonitor.isDevicePluggedIn(); - mBatteryLevel = mUpdateMonitor.getBatteryLevel(); - mNextAlarm = mLockPatternUtils.getNextAlarm(); - updateStatusLines(); - } - - private void updateStatusLines() { - if (mInstructions != null) { - // instructions only - mStatus1.setText(mInstructions); - if (TextUtils.isEmpty(mInstructions)) { - mStatus1.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); - } else { - mStatus1.setCompoundDrawablesWithIntrinsicBounds( - R.drawable.ic_lock_idle_lock, 0, 0, 0); - } - - mStatus1.setVisibility(View.VISIBLE); - mStatusSep.setVisibility(View.GONE); - mStatus2.setVisibility(View.GONE); - } else if (mShowingBatteryInfo && mNextAlarm == null) { - // battery only - if (mPluggedIn) { - if (mBatteryLevel >= 100) { - mStatus1.setText(getContext().getString(R.string.lockscreen_charged)); - } else { - mStatus1.setText(getContext().getString(R.string.lockscreen_plugged_in, mBatteryLevel)); - } - } else { - mStatus1.setText(getContext().getString(R.string.lockscreen_low_battery)); - } - mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_charging, 0, 0, 0); - - mStatus1.setVisibility(View.VISIBLE); - mStatusSep.setVisibility(View.GONE); - mStatus2.setVisibility(View.GONE); - - } else if (mNextAlarm != null && !mShowingBatteryInfo) { - // alarm only - mStatus1.setText(mNextAlarm); - mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_alarm, 0, 0, 0); - - mStatus1.setVisibility(View.VISIBLE); - mStatusSep.setVisibility(View.GONE); - mStatus2.setVisibility(View.GONE); - } else if (mNextAlarm != null && mShowingBatteryInfo) { - // both battery and next alarm - mStatus1.setText(mNextAlarm); - mStatusSep.setText("|"); - mStatus2.setText(getContext().getString( - R.string.lockscreen_battery_short, - Math.min(100, mBatteryLevel))); - mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_alarm, 0, 0, 0); - if (mPluggedIn) { - mStatus2.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_charging, 0, 0, 0); - } else { - mStatus2.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); - } - - mStatus1.setVisibility(View.VISIBLE); - mStatusSep.setVisibility(View.VISIBLE); - mStatus2.setVisibility(View.VISIBLE); - } else { - // nothing specific to show; show general instructions - mStatus1.setText(R.string.lockscreen_pattern_instructions); - mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_lock, 0, 0, 0); - - mStatus1.setVisibility(View.VISIBLE); - mStatusSep.setVisibility(View.GONE); - mStatus2.setVisibility(View.GONE); - } - } - - - private void refreshTimeAndDateDisplay() { - mDate.setText(DateFormat.format(mDateFormatString, new Date())); - } - - @Override public boolean dispatchTouchEvent(MotionEvent ev) { // as long as the user is entering a pattern (i.e sending a touch @@ -366,25 +251,21 @@ class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient return result; } - // ---------- InfoCallback /** {@inheritDoc} */ public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) { - mShowingBatteryInfo = showBatteryInfo; - mPluggedIn = pluggedIn; - mBatteryLevel = batteryLevel; - updateStatusLines(); + mStatusView.onRefreshBatteryInfo(showBatteryInfo, pluggedIn, batteryLevel); } /** {@inheritDoc} */ public void onTimeChanged() { - refreshTimeAndDateDisplay(); + mStatusView.onTimeChanged(); } /** {@inheritDoc} */ public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { - mCarrier.setText(LockScreen.getCarrierString(plmn, spn)); + mStatusView.onRefreshCarrierInfo(plmn, spn); } /** {@inheritDoc} */ @@ -444,8 +325,8 @@ class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient /** {@inheritDoc} */ public void onResume() { - // reset header - resetStatusInfo(); + // reset status + mStatusView.resetStatusInfo(mUpdateMonitor, mLockPatternUtils); // reset lock pattern mLockPatternView.enableInput(); @@ -514,8 +395,8 @@ class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient if (mLockPatternUtils.checkPattern(pattern)) { mLockPatternView .setDisplayMode(LockPatternView.DisplayMode.Correct); - mInstructions = ""; - updateStatusLines(); + mStatusView.setInstructions(""); + mStatusView.updateStatusLines(); mCallback.keyguardDone(true); mCallback.reportSuccessfulUnlockAttempt(); } else { @@ -533,8 +414,9 @@ class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient handleAttemptLockout(deadline); } else { // TODO mUnlockIcon.setVisibility(View.VISIBLE); - mInstructions = getContext().getString(R.string.lockscreen_pattern_wrong); - updateStatusLines(); + mStatusView.setInstructions( + getContext().getString(R.string.lockscreen_pattern_wrong)); + mStatusView.updateStatusLines(); mLockPatternView.postDelayed( mCancelPatternRunnable, PATTERN_CLEAR_TIMEOUT_MS); @@ -552,17 +434,18 @@ class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient @Override public void onTick(long millisUntilFinished) { int secondsRemaining = (int) (millisUntilFinished / 1000); - mInstructions = getContext().getString( + mStatusView.setInstructions(getContext().getString( R.string.lockscreen_too_many_failed_attempts_countdown, - secondsRemaining); - updateStatusLines(); + secondsRemaining)); + mStatusView.updateStatusLines(); } @Override public void onFinish() { mLockPatternView.setEnabled(true); - mInstructions = getContext().getString(R.string.lockscreen_pattern_instructions); - updateStatusLines(); + mStatusView.setInstructions(getContext().getString( + R.string.lockscreen_pattern_instructions)); + mStatusView.updateStatusLines(); // TODO mUnlockIcon.setVisibility(View.VISIBLE); mFailedPatternAttemptsSinceLastTimeout = 0; if (mEnableFallback) { diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index dffccf8..c25df1d 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -24,11 +24,15 @@ import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import com.android.internal.view.BaseSurfaceHolder; import com.android.internal.view.RootViewSurfaceTaker; +import com.android.internal.view.StandaloneActionMode; import com.android.internal.view.menu.ContextMenuBuilder; import com.android.internal.view.menu.MenuBuilder; import com.android.internal.view.menu.MenuDialogHelper; +import com.android.internal.view.menu.MenuPopupHelper; import com.android.internal.view.menu.MenuView; import com.android.internal.view.menu.SubMenuBuilder; +import com.android.internal.widget.ActionBarContextView; +import com.android.internal.widget.ActionBarView; import android.app.KeyguardManager; import android.app.SearchManager; @@ -53,6 +57,7 @@ import android.util.Config; import android.util.EventLog; import android.util.Log; import android.util.SparseArray; +import android.view.ActionMode; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.InputQueue; @@ -66,6 +71,7 @@ import android.view.SurfaceHolder; import android.view.View; import android.view.ViewGroup; import android.view.ViewManager; +import android.view.ViewStub; import android.view.VolumePanel; import android.view.Window; import android.view.WindowManager; @@ -95,7 +101,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { * Simple callback used by the context menu and its submenus. The options * menu submenus do not use this (their behavior is more complex). */ - ContextMenuCallback mContextMenuCallback = new ContextMenuCallback(FEATURE_CONTEXT_MENU); + DialogMenuCallback mContextMenuCallback = new DialogMenuCallback(FEATURE_CONTEXT_MENU); // This is the top-level view of the window, containing the window decor. private DecorView mDecor; @@ -114,6 +120,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { private LayoutInflater mLayoutInflater; private TextView mTitleView; + + private ActionBarView mActionBar; private DrawableFeatureState[] mDrawables; @@ -191,8 +199,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { /* Custom title feature is enabled and the user is trying to enable another feature */ throw new AndroidRuntimeException("You cannot combine custom titles with other title features"); } - if (featureId == FEATURE_OPENGL) { - getAttributes().memoryType = WindowManager.LayoutParams.MEMORY_TYPE_GPU; + if ((features & (1 << FEATURE_NO_TITLE)) != 0 && featureId == FEATURE_ACTION_BAR) { + return false; // Ignore. No title dominates. + } + if ((features & (1 << FEATURE_ACTION_BAR)) != 0 && featureId == FEATURE_NO_TITLE) { + // Remove the action bar feature if we have no title. No title dominates. + removeFeature(FEATURE_ACTION_BAR); } return super.requestFeature(featureId); } @@ -276,6 +288,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { public void setTitle(CharSequence title) { if (mTitleView != null) { mTitleView.setText(title); + } else if (mActionBar != null) { + mActionBar.setWindowTitle(title); } mTitle = title; } @@ -301,7 +315,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { // Already prepared (isPrepared will be reset to false later) if (st.isPrepared) return true; - + if ((mPreparedPanel != null) && (mPreparedPanel != st)) { // Another Panel is prepared and possibly open, so close it closePanel(mPreparedPanel, false); @@ -315,9 +329,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (st.createdPanelView == null) { // Init the panel state's menu--return false if init failed - if (st.menu == null) { - if (!initializePanelMenu(st) || (st.menu == null)) { - return false; + if (st.menu == null || st.refreshMenuContent) { + if (st.menu == null) { + if (!initializePanelMenu(st) || (st.menu == null)) { + return false; + } } // Call callback, and return if it doesn't want to display menu if ((cb == null) || !cb.onCreatePanelMenu(st.featureId, st.menu)) { @@ -326,6 +342,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { return false; } + + st.refreshMenuContent = false; + + if (mActionBar != null) { + mActionBar.setMenu(st.menu); + } } // Callback and return if the callback does not want to show the menu @@ -349,36 +371,37 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { @Override public void onConfigurationChanged(Configuration newConfig) { - PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false); - if ((st != null) && (st.menu != null)) { - final MenuBuilder menuBuilder = (MenuBuilder) st.menu; + // Action bars handle their own menu state + if (mActionBar == null) { + PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false); + if ((st != null) && (st.menu != null)) { + final MenuBuilder menuBuilder = (MenuBuilder) st.menu; - if (st.isOpen) { - // Freeze state - final Bundle state = new Bundle(); - menuBuilder.saveHierarchyState(state); + if (st.isOpen) { + // Freeze state + final Bundle state = new Bundle(); + menuBuilder.saveHierarchyState(state); - // Remove the menu views since they need to be recreated - // according to the new configuration - clearMenuViews(st); + // Remove the menu views since they need to be recreated + // according to the new configuration + clearMenuViews(st); - // Re-open the same menu - reopenMenu(false); + // Re-open the same menu + reopenMenu(false); - // Restore state - menuBuilder.restoreHierarchyState(state); + // Restore state + menuBuilder.restoreHierarchyState(state); - } else { - // Clear menu views so on next menu opening, it will use - // the proper layout - clearMenuViews(st); + } else { + // Clear menu views so on next menu opening, it will use + // the proper layout + clearMenuViews(st); + } } } - } private static void clearMenuViews(PanelFeatureState st) { - // This can be called on config changes, so we should make sure // the views will be reconstructed based on the new orientation, etc. @@ -393,7 +416,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { @Override public final void openPanel(int featureId, KeyEvent event) { - openPanel(getPanelState(featureId, true), event); + if (featureId == FEATURE_OPTIONS_PANEL && mActionBar != null && + mActionBar.isOverflowReserved()) { + mActionBar.showOverflowMenu(); + } else { + openPanel(getPanelState(featureId, true), event); + } } private void openPanel(PanelFeatureState st, KeyEvent event) { @@ -484,7 +512,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { @Override public final void closePanel(int featureId) { - if (featureId == FEATURE_CONTEXT_MENU) { + if (featureId == FEATURE_OPTIONS_PANEL && mActionBar != null && + mActionBar.isOverflowReserved()) { + mActionBar.hideOverflowMenu(); + } else if (featureId == FEATURE_CONTEXT_MENU) { closeContextMenu(); } else { closePanel(getPanelState(featureId, true), true); @@ -545,6 +576,26 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } } + @Override + public void invalidatePanelMenu(int featureId) { + PanelFeatureState st = getPanelState(featureId, true); + if (st.menu != null) { + st.menu.clear(); + } + st.refreshMenuContent = true; + st.refreshDecorView = true; + + // Prepare the options panel if we have an action bar + if ((featureId == FEATURE_ACTION_BAR || featureId == FEATURE_OPTIONS_PANEL) + && mActionBar != null) { + st = getPanelState(Window.FEATURE_OPTIONS_PANEL, false); + if (st != null) { + st.isPrepared = false; + preparePanel(st, null); + } + } + } + /** * Called when the panel key is pushed down. * @param featureId The feature ID of the relevant panel (defaults to FEATURE_OPTIONS_PANEL}. @@ -558,7 +609,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { // The panel key was pushed, so set the chording key mPanelChordingKey = keyCode; mPanelMayLongPress = false; - + PanelFeatureState st = getPanelState(featureId, true); if (!st.isOpen) { if (getContext().getResources().getConfiguration().keyboard @@ -567,7 +618,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } return preparePanel(st, event); } - } else if (mPanelMayLongPress && mPanelChordingKey == keyCode && (event.getFlags()&KeyEvent.FLAG_LONG_PRESS) != 0) { // We have had a long press while in a state where this @@ -602,25 +652,38 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } boolean playSoundEffect = false; - PanelFeatureState st = getPanelState(featureId, true); - if (st.isOpen || st.isHandled) { + final PanelFeatureState st = getPanelState(featureId, true); + if (featureId == FEATURE_OPTIONS_PANEL && mActionBar != null && + mActionBar.isOverflowReserved()) { + if (!mActionBar.isOverflowMenuShowing()) { + final Callback cb = getCallback(); + if (cb != null && + cb.onPreparePanel(featureId, st.createdPanelView, st.menu)) { + playSoundEffect = mActionBar.showOverflowMenu(); + } + } else { + playSoundEffect = mActionBar.hideOverflowMenu(); + } + } else { + if (st.isOpen || st.isHandled) { - // Play the sound effect if the user closed an open menu (and not if - // they just released a menu shortcut) - playSoundEffect = st.isOpen; + // Play the sound effect if the user closed an open menu (and not if + // they just released a menu shortcut) + playSoundEffect = st.isOpen; - // Close menu - closePanel(st, true); + // Close menu + closePanel(st, true); - } else if (st.isPrepared) { + } else if (st.isPrepared) { - // Write 'menu opened' to event log - EventLog.writeEvent(50001, 0); + // Write 'menu opened' to event log + EventLog.writeEvent(50001, 0); - // Show menu - openPanel(st, event); + // Show menu + openPanel(st, event); - playSoundEffect = true; + playSoundEffect = true; + } } if (playSoundEffect) { @@ -777,8 +840,20 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { return true; } - // The window manager will give us a valid window token - new MenuDialogHelper(subMenu).show(null); + final Menu parentMenu = subMenu.getRootMenu(); + final PanelFeatureState panel = findMenuPanel(parentMenu); + + /* + * Use the panel open state to determine whether this is coming from an open panel + * or an action button. If it's an open panel we want to use MenuDialogHelper. + * If it's closed we want to grab the relevant view and create a popup anchored to it. + */ + if (panel.isOpen) { + // The window manager will give us a valid window token + new MenuDialogHelper(subMenu).show(null); + } else { + new MenuPopupHelper(getContext(), subMenu).show(); + } return true; } @@ -788,6 +863,21 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } private void reopenMenu(boolean toggleMenuMode) { + if (mActionBar != null) { + if (!mActionBar.isOverflowMenuShowing() || !toggleMenuMode) { + final Callback cb = getCallback(); + if (cb != null) { + final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true); + if (cb.onPreparePanel(FEATURE_OPTIONS_PANEL, st.createdPanelView, st.menu)) { + mActionBar.showOverflowMenu(); + } + } + } else { + mActionBar.hideOverflowMenu(); + } + return; + } + PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true); // Save the future expanded mode state since closePanel will reset it @@ -1437,6 +1527,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { static private final String FOCUSED_ID_TAG = "android:focusedViewId"; static private final String VIEWS_TAG = "android:views"; static private final String PANELS_TAG = "android:Panels"; + static private final String ACTION_BAR_TAG = "android:ActionBar"; /** {@inheritDoc} */ @Override @@ -1470,6 +1561,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { outState.putSparseParcelableArray(PANELS_TAG, panelStates); } + if (mActionBar != null) { + outState.putBoolean(ACTION_BAR_TAG, mActionBar.isOverflowMenuShowing()); + } + return outState; } @@ -1504,6 +1599,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (panelStates != null) { restorePanelState(panelStates); } + + if (mActionBar != null && savedInstanceState.getBoolean(ACTION_BAR_TAG)) { + mActionBar.postShowOverflowMenu(); + } } /** @@ -1594,6 +1693,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { private boolean mWatchingForMenu; private int mDownY; + private ActionMode mActionMode; + private ActionBarContextView mActionModeView; + public DecorView(Context context, int featureId) { super(context); mFeatureId = featureId; @@ -1602,7 +1704,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { @Override public boolean dispatchKeyEvent(KeyEvent event) { final int keyCode = event.getKeyCode(); - final boolean isDown = event.getAction() == KeyEvent.ACTION_DOWN; + final int action = event.getAction(); + final boolean isDown = action == KeyEvent.ACTION_DOWN; /* * If the user hits another key within the play sound delay, then @@ -1659,6 +1762,14 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } } + // Back cancels action modes first. + if (mActionMode != null && keyCode == KeyEvent.KEYCODE_BACK) { + if (action == KeyEvent.ACTION_UP) { + mActionMode.finish(); + } + return true; + } + final Callback cb = getCallback(); final boolean handled = cb != null && mFeatureId < 0 ? cb.dispatchKeyEvent(event) : super.dispatchKeyEvent(event); @@ -1881,6 +1992,55 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { return mContextMenuHelper != null; } + @Override + public ActionMode startActionModeForChild(View originalView, + ActionMode.Callback callback) { + // originalView can be used here to be sure that we don't obscure + // relevant content with the context mode UI. + return startActionMode(callback); + } + + @Override + public ActionMode startActionMode(ActionMode.Callback callback) { + if (mActionMode != null) { + mActionMode.finish(); + } + + final ActionMode.Callback wrappedCallback = new ActionModeCallbackWrapper(callback); + ActionMode mode = getCallback().onStartActionMode(wrappedCallback); + if (mode != null) { + mActionMode = mode; + } else { + if (mActionModeView == null) { + if (hasFeature(FEATURE_ACTION_MODE_OVERLAY)) { + mActionModeView = new ActionBarContextView(mContext); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + MATCH_PARENT, WRAP_CONTENT); + addView(mActionModeView, params); + } else { + ViewStub stub = (ViewStub) findViewById( + com.android.internal.R.id.action_mode_bar_stub); + if (stub != null) { + mActionModeView = (ActionBarContextView) stub.inflate(); + } + } + } + + if (mActionModeView != null) { + mode = new StandaloneActionMode(getContext(), mActionModeView, wrappedCallback); + if (callback.onCreateActionMode(mode, mode.getMenu())) { + mode.invalidate(); + mActionModeView.initForMode(mode); + mActionModeView.setVisibility(View.VISIBLE); + mActionMode = mode; + } else { + mActionMode = null; + } + } + } + return mActionMode; + } + public void startChanging() { mChanging = true; } @@ -2060,6 +2220,37 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (keepOn) PhoneWindow.this.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); else PhoneWindow.this.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } + + /** + * Clears out internal reference when the action mode is destroyed. + */ + private class ActionModeCallbackWrapper implements ActionMode.Callback { + private ActionMode.Callback mWrapped; + + public ActionModeCallbackWrapper(ActionMode.Callback wrapped) { + mWrapped = wrapped; + } + + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + return mWrapped.onCreateActionMode(mode, menu); + } + + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + return mWrapped.onPrepareActionMode(mode, menu); + } + + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + return mWrapped.onActionItemClicked(mode, item); + } + + public void onDestroyActionMode(ActionMode mode) { + mWrapped.onDestroyActionMode(mode); + if (mActionModeView != null) { + mActionModeView.removeAllViews(); + } + mActionMode = null; + } + } } protected DecorView generateDecor() { @@ -2108,6 +2299,17 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (a.getBoolean(com.android.internal.R.styleable.Window_windowNoTitle, false)) { requestFeature(FEATURE_NO_TITLE); + } else if (a.getBoolean(com.android.internal.R.styleable.Window_windowActionBar, false)) { + // Don't allow an action bar if there is no title. + requestFeature(FEATURE_ACTION_BAR); + } + + if (a.getBoolean(com.android.internal.R.styleable.Window_windowActionBarOverlay, false)) { + requestFeature(FEATURE_ACTION_BAR_OVERLAY); + } + + if (a.getBoolean(com.android.internal.R.styleable.Window_windowActionModeOverlay, false)) { + requestFeature(FEATURE_ACTION_MODE_OVERLAY); } if (a.getBoolean(com.android.internal.R.styleable.Window_windowFullscreen, false)) { @@ -2172,11 +2374,15 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } else { layoutResource = com.android.internal.R.layout.screen_title_icons; } + // XXX Remove this once action bar supports these features. + removeFeature(FEATURE_ACTION_BAR); // System.out.println("Title Icons!"); } else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0) { // Special case for a window with only a progress bar (and title). // XXX Need to have a no-title version of embedded windows. layoutResource = com.android.internal.R.layout.screen_progress; + // XXX Remove this once action bar supports these features. + removeFeature(FEATURE_ACTION_BAR); // System.out.println("Progress!"); } else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) { // Special case for a window with a custom title. @@ -2186,11 +2392,19 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } else { layoutResource = com.android.internal.R.layout.screen_custom_title; } + // XXX Remove this once action bar supports these features. + removeFeature(FEATURE_ACTION_BAR); } else if ((features & (1 << FEATURE_NO_TITLE)) == 0) { // If no other features and not embedded, only need a title. // If the window is floating, we need a dialog layout if (mIsFloating) { layoutResource = com.android.internal.R.layout.dialog_title; + } else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) { + if ((features & (1 << FEATURE_ACTION_BAR_OVERLAY)) != 0) { + layoutResource = com.android.internal.R.layout.screen_action_bar_overlay; + } else { + layoutResource = com.android.internal.R.layout.screen_action_bar; + } } else { layoutResource = com.android.internal.R.layout.screen_title; } @@ -2275,6 +2489,22 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } else { mTitleView.setText(mTitle); } + } else { + mActionBar = (ActionBarView) findViewById(com.android.internal.R.id.action_bar); + if (mActionBar != null) { + if (mActionBar.getTitle() == null) { + mActionBar.setWindowTitle(mTitle); + } + // Post the panel invalidate for later; avoid application onCreateOptionsMenu + // being called in the middle of onCreate or similar. + mDecor.post(new Runnable() { + public void run() { + if (!isDestroyed()) { + invalidatePanelMenu(FEATURE_ACTION_BAR); + } + } + }); + } } } } @@ -2628,6 +2858,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { boolean refreshDecorView; + boolean refreshMenuContent; + boolean wasLastOpen; boolean wasLastExpanded; @@ -2750,11 +2982,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { * <li> Calls back to the callback's onMenuItemSelected when an item is * selected. */ - private final class ContextMenuCallback implements MenuBuilder.Callback { + private final class DialogMenuCallback implements MenuBuilder.Callback { private int mFeatureId; private MenuDialogHelper mSubMenuHelper; - public ContextMenuCallback(int featureId) { + public DialogMenuCallback(int featureId) { mFeatureId = featureId; } diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 567b270..bd774ce 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -46,6 +46,7 @@ import android.os.SystemProperties; import android.os.Vibrator; import android.provider.Settings; +import com.android.internal.R; import com.android.internal.policy.PolicyManager; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.telephony.ITelephony; @@ -176,6 +177,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { Context mContext; IWindowManager mWindowManager; LocalPowerManager mPowerManager; + IStatusBarService mStatusBarService; Vibrator mVibrator; // Vibrator for giving feedback of orientation changes // Vibrator pattern for haptic feedback of a long press. @@ -198,6 +200,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean mSafeMode; WindowState mStatusBar = null; + boolean mStatusBarCanHide; final ArrayList<WindowState> mStatusBarPanels = new ArrayList<WindowState>(); WindowState mKeyguard = null; KeyguardViewMediator mKeyguardMediator; @@ -264,6 +267,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final Rect mTmpVisibleFrame = new Rect(); WindowState mTopFullscreenOpaqueWindowState; + boolean mTopIsFullscreen; boolean mForceStatusBar; boolean mHideLockScreen; boolean mDismissKeyguard; @@ -291,6 +295,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Nothing to see here, move along... int mFancyRotationAnimation; + + // Enable 3D recents based on config settings. + private Boolean mUse3dRecents; ShortcutManager mShortcutManager; PowerManager.WakeLock mBroadcastWakeLock; @@ -493,6 +500,27 @@ public class PhoneWindowManager implements WindowManagerPolicy { * Create (if necessary) and launch the recent apps dialog */ void showRecentAppsDialog() { + // We can't initialize this in init() since the configuration hasn't been loaded yet. + if (mUse3dRecents == null) { + mUse3dRecents = mContext.getResources().getBoolean(R.bool.config_enableRecentApps3D); + } + + // Use 3d Recents dialog + if (mUse3dRecents) { + try { + Intent intent = new Intent(); + intent.setClassName("com.android.systemui", + "com.android.systemui.statusbar.RecentApplicationsActivity"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + mContext.startActivity(intent); + return; + } catch (ActivityNotFoundException e) { + Log.e(TAG, "Failed to launch RecentAppsIntent", e); + } + } + + // Fallback to dialog if we fail to launch the above. if (mRecentAppsDialog == null) { mRecentAppsDialog = new RecentApplicationsDialog(mContext); } @@ -524,6 +552,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK); mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); mBroadcastWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "PhoneWindowManager.mBroadcastWakeLock"); @@ -566,6 +595,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { com.android.internal.R.array.config_safeModeDisabledVibePattern); mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(), com.android.internal.R.array.config_safeModeEnabledVibePattern); + + // Note: the Configuration is not stable here, so we cannot load mStatusBarCanHide from + // config_statusBarCanHide because the latter depends on the screen size } public void updateSettings() { @@ -978,6 +1010,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { return WindowManagerImpl.ADD_MULTIPLE_SINGLETON; } mStatusBar = win; + + // The Configuration will be stable by now, so we can load this + mStatusBarCanHide = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_statusBarCanHide); + break; case TYPE_STATUS_BAR_PANEL: mContext.enforceCallingOrSelfPermission( @@ -1236,7 +1273,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) { final int fl = attrs.flags; - if ((fl & + if (mStatusBarCanHide && (fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR)) == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { contentInset.set(mCurLeft, mCurTop, mW - mCurRight, mH - mCurBottom); @@ -1269,10 +1306,17 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mStatusBar.isVisibleLw()) { // If the status bar is hidden, we don't want to cause // windows behind it to scroll. - mDockTop = mContentTop = mCurTop = mStatusBar.getFrameLw().bottom; - if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: mDockBottom=" - + mDockBottom + " mContentBottom=" - + mContentBottom + " mCurBottom=" + mCurBottom); + final Rect r = mStatusBar.getFrameLw(); + if (mDockTop == r.top) mDockTop = r.bottom; + else if (mDockBottom == r.bottom) mDockBottom = r.top; + mContentTop = mCurTop = mDockTop; + mContentBottom = mCurBottom = mDockBottom; + if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: mDockTop=" + mDockTop + + " mContentTop=" + mContentTop + + " mCurTop=" + mCurTop + + " mDockBottom=" + mDockBottom + + " mContentBottom=" + mContentBottom + + " mCurBottom=" + mCurBottom); } } } @@ -1357,7 +1401,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { attrs.gravity = Gravity.BOTTOM; mDockLayer = win.getSurfaceLayer(); } else { - if ((fl & + if (mStatusBarCanHide && (fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR)) == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { // This is the case for a normal activity window: we want it @@ -1389,7 +1433,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { vf.right = mCurRight; vf.bottom = mCurBottom; } - } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0) { + } else if (mStatusBarCanHide && (fl & FLAG_LAYOUT_IN_SCREEN) != 0) { // A window that has requested to fill the entire screen just // gets everything, period. pf.left = df.left = cf.left = 0; @@ -1516,8 +1560,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ public int finishAnimationLw() { int changes = 0; - - boolean hiding = false; + + boolean topIsFullscreen = false; if (mStatusBar != null) { if (localLOGV) Log.i(TAG, "force=" + mForceStatusBar + " top=" + mTopFullscreenOpaqueWindowState); @@ -1525,17 +1569,25 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar"); if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT; } else if (mTopFullscreenOpaqueWindowState != null) { - //Log.i(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw() - // + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw()); - //Log.i(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()); - WindowManager.LayoutParams lp = - mTopFullscreenOpaqueWindowState.getAttrs(); - boolean hideStatusBar = - (lp.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0; - if (hideStatusBar) { - if (DEBUG_LAYOUT) Log.v(TAG, "Hiding status bar"); - if (mStatusBar.hideLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT; - hiding = true; + final WindowManager.LayoutParams lp = mTopFullscreenOpaqueWindowState.getAttrs(); + if (localLOGV) { + Log.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw() + + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw()); + Log.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs() + + " lp.flags=0x" + Integer.toHexString(lp.flags)); + } + topIsFullscreen = (lp.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0; + // The subtle difference between the window for mTopFullscreenOpaqueWindowState + // and mTopIsFullscreen is that that mTopIsFullscreen is set only if the window + // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the + // case though. + if (topIsFullscreen) { + if (mStatusBarCanHide) { + if (DEBUG_LAYOUT) Log.v(TAG, "Hiding status bar"); + if (mStatusBar.hideLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT; + } else if (localLOGV) { + Log.v(TAG, "Preventing status bar from hiding by policy"); + } } else { if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar"); if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT; @@ -1543,21 +1595,36 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - if (changes != 0 && hiding) { - IStatusBarService sbs = IStatusBarService.Stub.asInterface(ServiceManager.getService("statusbar")); - if (sbs != null) { - try { - // Make sure the window shade is hidden. - sbs.collapse(); - } catch (RemoteException e) { - } - } + if (topIsFullscreen != mTopIsFullscreen) { + final boolean topIsFullscreenF = topIsFullscreen; + mTopIsFullscreen = topIsFullscreen; + mHandler.post(new Runnable() { + public void run() { + if (mStatusBarService == null) { + // This is the one that can not go away, but it doesn't come up + // before the window manager does, so don't fail if it doesn't + // exist. This works as long as no fullscreen windows come up + // before the status bar service does. + mStatusBarService = IStatusBarService.Stub.asInterface( + ServiceManager.getService("statusbar")); + } + final IStatusBarService sbs = mStatusBarService; + if (mStatusBarService != null) { + try { + sbs.setActiveWindowIsFullscreen(topIsFullscreenF); + } catch (RemoteException e) { + // This should be impossible because we're in the same process. + mStatusBarService = null; + } + } + } + }); } // Hide the key guard if a visible window explicitly specifies that it wants to be displayed // when the screen is locked if (mKeyguard != null) { - if (localLOGV) Log.v(TAG, "finishLayoutLw::mHideKeyguard="+mHideLockScreen); + if (localLOGV) Log.v(TAG, "finishAnimationLw::mHideKeyguard="+mHideLockScreen); if (mDismissKeyguard && !mKeyguardMediator.isSecure()) { if (mKeyguard.hideLw(true)) { changes |= FINISH_LAYOUT_REDO_LAYOUT diff --git a/policy/src/com/android/internal/policy/impl/StatusView.java b/policy/src/com/android/internal/policy/impl/StatusView.java new file mode 100644 index 0000000..3f08cfd --- /dev/null +++ b/policy/src/com/android/internal/policy/impl/StatusView.java @@ -0,0 +1,255 @@ +// Copyright 2010 Google Inc. All Rights Reserved. + +package com.android.internal.policy.impl; + +import com.android.internal.R; +import com.android.internal.widget.LockPatternUtils; + +import java.util.Date; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.text.TextUtils; +import android.text.format.DateFormat; +import android.util.Log; +import android.view.View; +import android.widget.TextView; + +class StatusView { + private String mDateFormatString; + + private TextView mCarrier; + private TextView mDate; + + // are we showing battery information? + private boolean mShowingBatteryInfo = false; + + // last known plugged in state + private boolean mPluggedIn = false; + + // last known battery level + private int mBatteryLevel = 100; + + private String mNextAlarm = null; + + private String mInstructions = null; + private TextView mStatus1; + private TextView mStatus2; + private TextView mPropertyOf; + + private boolean mHasStatus2; + private boolean mHasCarrier; + private boolean mHasDate; + private boolean mHasProperty; + + private View mView; + + private View findViewById(int id) { + return mView.findViewById(id); + } + + private Context getContext() { + return mView.getContext(); + } + + void setInstructions(String instructions) { + mInstructions = instructions; + } + + void setCarrierText(CharSequence carrierText) { + if (mCarrier != null) { + mCarrier.setText(carrierText); + } + } + + void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) { + mShowingBatteryInfo = showBatteryInfo; + mPluggedIn = pluggedIn; + mBatteryLevel = batteryLevel; + updateStatusLines(); + } + + void onTimeChanged() { + refreshTimeAndDateDisplay(); + } + + public void onRingerModeChanged(int state) { + } + + void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { + setCarrierText(LockScreen.getCarrierString(plmn, spn)); + } + + public StatusView(View view, KeyguardUpdateMonitor updateMonitor, + LockPatternUtils lockPatternUtils) { + mView = view; + mCarrier = (TextView) findViewById(R.id.carrier); + mHasCarrier = (mCarrier != null); + mDate = (TextView) findViewById(R.id.date); + mHasDate = (mDate != null); + mDateFormatString = getContext().getString(R.string.full_wday_month_day_no_year); + + refreshTimeAndDateDisplay(); + + mStatus1 = (TextView) findViewById(R.id.status1); + mStatus2 = (TextView) findViewById(R.id.status2); + mHasStatus2 = (mStatus2 != null); + mPropertyOf = (TextView) findViewById(R.id.propertyOf); + mHasProperty = (mPropertyOf != null); + + resetStatusInfo(updateMonitor, lockPatternUtils); + + // Required to get Marquee to work. + if (mHasCarrier) { + mCarrier.setSelected(true); + mCarrier.setTextColor(0xffffffff); + } + + } + + void resetStatusInfo(KeyguardUpdateMonitor updateMonitor, LockPatternUtils lockPatternUtils) { + mInstructions = null; + mShowingBatteryInfo = updateMonitor.shouldShowBatteryInfo(); + mPluggedIn = updateMonitor.isDevicePluggedIn(); + mBatteryLevel = updateMonitor.getBatteryLevel(); + mNextAlarm = lockPatternUtils.getNextAlarm(); + updateStatusLines(); + } + + void setInstructionText(int stringId) { + mStatus1.setText(stringId); + mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_lock, 0, 0, 0); + mStatus1.setVisibility(View.VISIBLE); + } + + void setInstructionText(String string) { + mStatus1.setText(string); + mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_lock, 0, 0, 0); + mStatus1.setVisibility(View.VISIBLE); + } + + void setCarrierText(int stringId) { + mCarrier.setText(stringId); + } + void setCarrierText(String string) { + mCarrier.setText(string); + } + + /** Originated from PatternUnlockScreen **/ + void updateStatusLines() { + if (mHasProperty) { + // TODO Get actual name & email + String name = "John Smith"; + String email = "jsmith@gmail.com"; + mPropertyOf.setText("Property of:\n" + name + "\n" + email); + mPropertyOf.setVisibility(View.VISIBLE); + } + + if (!mHasStatus2) return; + + if (mInstructions != null) { + // instructions only + mStatus1.setText(mInstructions); + if (TextUtils.isEmpty(mInstructions)) { + mStatus1.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + } else { + mStatus1.setCompoundDrawablesWithIntrinsicBounds( + R.drawable.ic_lock_idle_lock, 0, 0, 0); + } + + mStatus1.setVisibility(View.VISIBLE); + mStatus2.setVisibility(View.INVISIBLE); + } else if (mShowingBatteryInfo && mNextAlarm == null) { + // battery only + if (mPluggedIn) { + if (mBatteryLevel >= 100) { + mStatus1.setText(getContext().getString(R.string.lockscreen_charged)); + } else { + mStatus1.setText(getContext().getString(R.string.lockscreen_plugged_in, + mBatteryLevel)); + } + } else { + mStatus1.setText(getContext().getString(R.string.lockscreen_low_battery)); + } + mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_charging, 0, + 0, 0); + + mStatus1.setVisibility(View.VISIBLE); + mStatus2.setVisibility(View.INVISIBLE); + + } else if (mNextAlarm != null && !mShowingBatteryInfo) { + // alarm only + mStatus1.setText(mNextAlarm); + mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_alarm, 0, + 0, 0); + + mStatus1.setVisibility(View.VISIBLE); + mStatus2.setVisibility(View.INVISIBLE); + } else if (mNextAlarm != null && mShowingBatteryInfo) { + // both battery and next alarm + mStatus1.setText(mNextAlarm); + mStatus2.setText(getContext().getString( + R.string.lockscreen_battery_short, + Math.min(100, mBatteryLevel))); + mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_alarm, 0, + 0, 0); + if (mPluggedIn) { + mStatus2.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_charging, + 0, 0, 0); + } else { + mStatus2.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + } + + mStatus1.setVisibility(View.VISIBLE); + mStatus2.setVisibility(View.VISIBLE); + } else { + // nothing specific to show; show general instructions + mStatus1.setText(R.string.lockscreen_pattern_instructions); + mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_lock, 0, + 0, 0); + + mStatus1.setVisibility(View.VISIBLE); + mStatus2.setVisibility(View.INVISIBLE); + } + } + + /** Originated from LockScreen **/ + // TODO Merge with function above + void updateStatusLines(boolean showStatusLines, String charging, Drawable chargingIcon, + Drawable alarmIcon) { + if (!showStatusLines || (charging == null && mNextAlarm == null)) { + mStatus1.setVisibility(View.INVISIBLE); + mStatus2.setVisibility(View.INVISIBLE); + } else if (charging != null && mNextAlarm == null) { + // charging only + mStatus1.setVisibility(View.VISIBLE); + mStatus2.setVisibility(View.INVISIBLE); + + mStatus1.setText(charging); + mStatus1.setCompoundDrawablesWithIntrinsicBounds(chargingIcon, null, null, null); + } else if (mNextAlarm != null && charging == null) { + // next alarm only + mStatus1.setVisibility(View.VISIBLE); + mStatus2.setVisibility(View.INVISIBLE); + + mStatus1.setText(mNextAlarm); + mStatus1.setCompoundDrawablesWithIntrinsicBounds(alarmIcon, null, null, null); + } else if (charging != null && mNextAlarm != null) { + // both charging and next alarm + mStatus1.setVisibility(View.VISIBLE); + mStatus2.setVisibility(View.VISIBLE); + + mStatus1.setText(charging); + mStatus1.setCompoundDrawablesWithIntrinsicBounds(chargingIcon, null, null, null); + mStatus2.setText(mNextAlarm); + mStatus2.setCompoundDrawablesWithIntrinsicBounds(alarmIcon, null, null, null); + } + } + + void refreshTimeAndDateDisplay() { + if (mHasDate) { + mDate.setText(DateFormat.format(mDateFormatString, new Date())); + } + } + +} |