diff options
author | Steve Kondik <shade@chemlab.org> | 2011-12-16 14:45:56 -0800 |
---|---|---|
committer | Steve Kondik <shade@chemlab.org> | 2011-12-16 14:45:56 -0800 |
commit | bec96948c8ea41c022fe7e68ccdfdaa1a1128871 (patch) | |
tree | d18f611794386ae7058f3a4b66e2c867bf14c70a /policy | |
parent | 7e350ef016b80203bc1b1c275729fe8c441a7728 (diff) | |
parent | 8b6ed2d17d5e7e47944026679c9cba66611ab27f (diff) | |
download | frameworks_base-bec96948c8ea41c022fe7e68ccdfdaa1a1128871.zip frameworks_base-bec96948c8ea41c022fe7e68ccdfdaa1a1128871.tar.gz frameworks_base-bec96948c8ea41c022fe7e68ccdfdaa1a1128871.tar.bz2 |
Merge branch 'ics-mr1' of https://android.googlesource.com/platform/frameworks/base into aosp
Conflicts:
core/res/res/values/strings.xml
policy/src/com/android/internal/policy/impl/GlobalActions.java
services/java/com/android/server/WifiService.java
services/sensorservice/SensorDevice.cpp
telephony/java/com/android/internal/telephony/RIL.java
Change-Id: I89ec56d5ff282a2eb879ca40fb6d74ebcf752837
Diffstat (limited to 'policy')
15 files changed, 675 insertions, 478 deletions
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java index ed1fa76..dfece30 100644 --- a/policy/src/com/android/internal/policy/impl/GlobalActions.java +++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java @@ -67,13 +67,15 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac private static final String TAG = "GlobalActions"; + private static final boolean SHOW_SILENT_TOGGLE = true; + private final Context mContext; private final AudioManager mAudioManager; private ArrayList<Action> mItems; private AlertDialog mDialog; - private ToggleAction mSilentModeToggle; + private SilentModeAction mSilentModeAction; private ToggleAction mAirplaneModeOn; private MyAdapter mAdapter; @@ -124,39 +126,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac * @return A new dialog. */ private AlertDialog createDialog() { - mSilentModeToggle = new ToggleAction( - R.drawable.ic_audio_vol_mute, - R.drawable.ic_audio_vol, - R.string.global_action_toggle_silent_mode, - R.string.global_action_silent_mode_on_status, - R.string.global_action_silent_mode_off_status) { - - void willCreate() { - mEnabledIconResId = (Settings.System.getInt(mContext.getContentResolver(), - Settings.System.VIBRATE_IN_SILENT, 1) == 1) - ? R.drawable.ic_audio_ring_notif_vibrate - : R.drawable.ic_audio_vol_mute; - } - - void onToggle(boolean on) { - if (on) { - mAudioManager.setRingerMode((Settings.System.getInt(mContext.getContentResolver(), - Settings.System.VIBRATE_IN_SILENT, 1) == 1) - ? AudioManager.RINGER_MODE_VIBRATE - : AudioManager.RINGER_MODE_SILENT); - } else { - mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL); - } - } - - public boolean showDuringKeyguard() { - return true; - } - - public boolean showBeforeProvisioning() { - return false; - } - }; + mSilentModeAction = new SilentModeAction(mAudioManager, mHandler); mAirplaneModeOn = new ToggleAction( R.drawable.ic_lock_airplane_mode, @@ -198,65 +168,78 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } }; - mItems = Lists.newArrayList( - // silent mode - mSilentModeToggle, - // next: airplane mode - mAirplaneModeOn, - // next: screenshot - new SinglePressAction(com.android.internal.R.drawable.ic_lock_screenshot, R.string.global_action_screenshot) { - public void onPress() { - takeScreenshot(); - } + mItems = new ArrayList<Action>(); - public boolean showDuringKeyguard() { - return true; - } + // first: power off + mItems.add( + new SinglePressAction( + com.android.internal.R.drawable.ic_lock_power_off, + R.string.global_action_power_off) { - public boolean showBeforeProvisioning() { - return true; - } - }, - // next: reboot - new SinglePressAction(com.android.internal.R.drawable.ic_lock_reboot, R.string.global_action_reboot) { - public void onPress() { - ShutdownThread.reboot(mContext, "null", true); - } + public void onPress() { + // shutdown by making sure radio and power are handled accordingly. + ShutdownThread.shutdown(mContext, true); + } - public boolean showDuringKeyguard() { - return true; - } + public boolean showDuringKeyguard() { + return true; + } - public boolean showBeforeProvisioning() { - return true; - } - }, - // last: power off - new SinglePressAction(com.android.internal.R.drawable.ic_lock_power_off, R.string.global_action_power_off) { + public boolean showBeforeProvisioning() { + return true; + } + }); - public void onPress() { - // shutdown by making sure radio and power are handled accordingly. - ShutdownThread.shutdown(mContext, true); - } + // next: reboot + mItems.add( + new SinglePressAction(com.android.internal.R.drawable.ic_lock_reboot, R.string.global_action_reboot) { + public void onPress() { + ShutdownThread.reboot(mContext, "null", true); + } - public boolean showDuringKeyguard() { - return true; - } + public boolean showDuringKeyguard() { + return true; + } + + public boolean showBeforeProvisioning() { + return true; + } + }); + + // next: screenshot + mItems.add( + new SinglePressAction(com.android.internal.R.drawable.ic_lock_screenshot, R.string.global_action_screenshot) { + public void onPress() { + takeScreenshot(); + } + + public boolean showDuringKeyguard() { + return true; + } + + public boolean showBeforeProvisioning() { + return true; + } + }); + + // next: airplane mode + mItems.add(mAirplaneModeOn); + + // last: silent mode + if (SHOW_SILENT_TOGGLE) { + mItems.add(mSilentModeAction); + } - public boolean showBeforeProvisioning() { - return true; - } - }); mAdapter = new MyAdapter(); final AlertDialog.Builder ab = new AlertDialog.Builder(mContext); ab.setAdapter(mAdapter, this) - .setInverseBackgroundForced(true) - .setTitle(R.string.global_actions); + .setInverseBackgroundForced(true); final AlertDialog dialog = ab.create(); + dialog.getListView().setItemsCanFocus(true); dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); dialog.setOnDismissListener(this); @@ -349,8 +332,6 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac private void prepareDialog() { final boolean silentModeOn = mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL; - mSilentModeToggle.updateState( - silentModeOn ? ToggleAction.State.On : ToggleAction.State.Off); mAirplaneModeOn.updateState(mAirplaneState); mAdapter.notifyDataSetChanged(); if (mKeyguardShowing) { @@ -358,21 +339,31 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } else { mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); } + mDialog.setTitle(R.string.global_actions); + + if (SHOW_SILENT_TOGGLE) { + IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION); + mContext.registerReceiver(mRingerModeReceiver, filter); + } } /** {@inheritDoc} */ public void onDismiss(DialogInterface dialog) { + if (SHOW_SILENT_TOGGLE) { + mContext.unregisterReceiver(mRingerModeReceiver); + } } /** {@inheritDoc} */ public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); + if (!(mAdapter.getItem(which) instanceof SilentModeAction)) { + dialog.dismiss(); + } mAdapter.getItem(which).onPress(); } - /** * The adapter used for the list within the global actions dialog, taking * into account whether the keyguard is showing via @@ -493,9 +484,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac public View create( Context context, View convertView, ViewGroup parent, LayoutInflater inflater) { - View v = (convertView != null) ? - convertView : - inflater.inflate(R.layout.global_actions_item, parent, false); + View v = inflater.inflate(R.layout.global_actions_item, parent, false); ImageView icon = (ImageView) v.findViewById(R.id.icon); TextView messageView = (TextView) v.findViewById(R.id.message); @@ -572,27 +561,31 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac LayoutInflater inflater) { willCreate(); - View v = (convertView != null) ? - convertView : - inflater.inflate(R + View v = inflater.inflate(R .layout.global_actions_item, parent, false); ImageView icon = (ImageView) v.findViewById(R.id.icon); TextView messageView = (TextView) v.findViewById(R.id.message); TextView statusView = (TextView) v.findViewById(R.id.status); + final boolean enabled = isEnabled(); - messageView.setText(mMessageResId); + if (messageView != null) { + messageView.setText(mMessageResId); + messageView.setEnabled(enabled); + } boolean on = ((mState == State.On) || (mState == State.TurningOn)); - icon.setImageDrawable(context.getResources().getDrawable( - (on ? mEnabledIconResId : mDisabledIconResid))); - statusView.setText(on ? mEnabledStatusMessageResId : mDisabledStatusMessageResId); - statusView.setVisibility(View.VISIBLE); + if (icon != null) { + icon.setImageDrawable(context.getResources().getDrawable( + (on ? mEnabledIconResId : mDisabledIconResid))); + icon.setEnabled(enabled); + } - final boolean enabled = isEnabled(); - messageView.setEnabled(enabled); - statusView.setEnabled(enabled); - icon.setEnabled(enabled); + if (statusView != null) { + statusView.setText(on ? mEnabledStatusMessageResId : mDisabledStatusMessageResId); + statusView.setVisibility(View.VISIBLE); + statusView.setEnabled(enabled); + } v.setEnabled(enabled); return v; @@ -630,6 +623,70 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } } + private static class SilentModeAction implements Action, View.OnClickListener { + + private final int[] ITEM_IDS = { R.id.option1, R.id.option2, R.id.option3 }; + + private final AudioManager mAudioManager; + private final Handler mHandler; + + SilentModeAction(AudioManager audioManager, Handler handler) { + mAudioManager = audioManager; + mHandler = handler; + } + + private int ringerModeToIndex(int ringerMode) { + // They just happen to coincide + return ringerMode; + } + + private int indexToRingerMode(int index) { + // They just happen to coincide + return index; + } + + public View create(Context context, View convertView, ViewGroup parent, + LayoutInflater inflater) { + View v = inflater.inflate(R.layout.global_actions_silent_mode, parent, false); + + int selectedIndex = ringerModeToIndex(mAudioManager.getRingerMode()); + for (int i = 0; i < 3; i++) { + View itemView = v.findViewById(ITEM_IDS[i]); + itemView.setSelected(selectedIndex == i); + // Set up click handler + itemView.setTag(i); + itemView.setOnClickListener(this); + } + return v; + } + + public void onPress() { + } + + public boolean showDuringKeyguard() { + return true; + } + + public boolean showBeforeProvisioning() { + return false; + } + + public boolean isEnabled() { + return true; + } + + void willCreate() { + } + + public void onClick(View v) { + if (!(v.getTag() instanceof Integer)) return; + + int index = (Integer) v.getTag(); + mAudioManager.setRingerMode(indexToRingerMode(index)); + mHandler.sendEmptyMessageDelayed(MESSAGE_DISMISS, DIALOG_DISMISS_DELAY); + } + } + private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); @@ -661,13 +718,27 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } }; + private BroadcastReceiver mRingerModeReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { + mHandler.sendEmptyMessage(MESSAGE_REFRESH); + } + } + }; + private static final int MESSAGE_DISMISS = 0; + private static final int MESSAGE_REFRESH = 1; + private static final int DIALOG_DISMISS_DELAY = 300; // ms + private Handler mHandler = new Handler() { public void handleMessage(Message msg) { if (msg.what == MESSAGE_DISMISS) { if (mDialog != null) { mDialog.dismiss(); } + } else if (msg.what == MESSAGE_REFRESH) { + mAdapter.notifyDataSetChanged(); } } }; diff --git a/policy/src/com/android/internal/policy/impl/IconUtilities.java b/policy/src/com/android/internal/policy/impl/IconUtilities.java index 4564f90..e997355 100644 --- a/policy/src/com/android/internal/policy/impl/IconUtilities.java +++ b/policy/src/com/android/internal/policy/impl/IconUtilities.java @@ -38,6 +38,8 @@ import android.text.StaticLayout; import android.text.TextPaint; import android.util.DisplayMetrics; import android.util.Log; +import android.util.TypedValue; +import android.view.ContextThemeWrapper; import android.content.res.Resources; import android.content.Context; @@ -74,9 +76,13 @@ final class IconUtilities { mIconTextureWidth = mIconTextureHeight = mIconWidth + (int)(blurPx*2); mBlurPaint.setMaskFilter(new BlurMaskFilter(blurPx, BlurMaskFilter.Blur.NORMAL)); - mGlowColorPressedPaint.setColor(0xffffc300); + + TypedValue value = new TypedValue(); + mGlowColorPressedPaint.setColor(context.getTheme().resolveAttribute( + android.R.attr.colorPressedHighlight, value, true) ? value.data : 0xffffc300); mGlowColorPressedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30)); - mGlowColorFocusedPaint.setColor(0xffff8e00); + mGlowColorFocusedPaint.setColor(context.getTheme().resolveAttribute( + android.R.attr.colorFocusedHighlight, value, true) ? value.data : 0xffff8e00); mGlowColorFocusedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30)); ColorMatrix cm = new ColorMatrix(); diff --git a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java index 6614d79..ee54de1 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java @@ -91,7 +91,7 @@ class KeyguardStatusViewManager implements OnClickListener { private LockPatternUtils mLockPatternUtils; private KeyguardUpdateMonitor mUpdateMonitor; private Button mEmergencyCallButton; - private boolean mUnlockDisabledDueToSimState; + private boolean mEmergencyButtonEnabledBecauseSimLocked; // Shadowed text values private CharSequence mCarrierText; @@ -101,9 +101,10 @@ class KeyguardStatusViewManager implements OnClickListener { private CharSequence mOwnerInfoText; private boolean mShowingStatus; private KeyguardScreenCallback mCallback; - private final boolean mShowEmergencyButtonByDefault; + private final boolean mEmergencyCallButtonEnabledInScreen; private CharSequence mPlmn; private CharSequence mSpn; + protected int mPhoneState; private class TransientTextManager { private TextView mTextView; @@ -154,12 +155,20 @@ class KeyguardStatusViewManager implements OnClickListener { } }; + /** + * + * @param view the containing view of all widgets + * @param updateMonitor the update monitor to use + * @param lockPatternUtils lock pattern util object + * @param callback used to invoke emergency dialer + * @param emergencyButtonEnabledInScreen whether emergency button is enabled by default + */ public KeyguardStatusViewManager(View view, KeyguardUpdateMonitor updateMonitor, LockPatternUtils lockPatternUtils, KeyguardScreenCallback callback, - boolean showEmergencyButtonByDefault) { + boolean emergencyButtonEnabledInScreen) { if (DEBUG) Log.v(TAG, "KeyguardStatusViewManager()"); mContainer = view; - mDateFormatString = getContext().getString(R.string.full_wday_month_day_no_year); + mDateFormatString = getContext().getString(R.string.abbrev_wday_month_day_no_year); mLockPatternUtils = lockPatternUtils; mUpdateMonitor = updateMonitor; mCallback = callback; @@ -171,7 +180,7 @@ class KeyguardStatusViewManager implements OnClickListener { mOwnerInfoView = (TextView) findViewById(R.id.propertyOf); mTransportView = (TransportControlView) findViewById(R.id.transport); mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton); - mShowEmergencyButtonByDefault = showEmergencyButtonByDefault; + mEmergencyCallButtonEnabledInScreen = emergencyButtonEnabledInScreen; // Hide transport control view until we know we need to show it. if (mTransportView != null) { @@ -452,12 +461,12 @@ class KeyguardStatusViewManager implements OnClickListener { * * @param simState */ - private void updateCarrierTextWithSimStatus(State simState) { + private void updateCarrierStateWithSimStatus(State simState) { if (DEBUG) Log.d(TAG, "updateCarrierTextWithSimStatus(), simState = " + simState); CharSequence carrierText = null; int carrierHelpTextId = 0; - mUnlockDisabledDueToSimState = false; + mEmergencyButtonEnabledBecauseSimLocked = false; mStatus = getStatusForIccState(simState); mSimState = simState; switch (mStatus) { @@ -472,39 +481,49 @@ class KeyguardStatusViewManager implements OnClickListener { break; case SimMissing: + // Shows "No SIM card | Emergency calls only" on devices that are voice-capable. + // This depends on mPlmn containing the text "Emergency calls only" when the radio + // has some connectivity. Otherwise, it should be null or empty and just show + // "No SIM card" carrierText = getContext().getText(R.string.lockscreen_missing_sim_message_short); + if (mLockPatternUtils.isEmergencyCallCapable()) { + carrierText = makeCarierString(carrierText, mPlmn); + } carrierHelpTextId = R.string.lockscreen_missing_sim_instructions_long; break; case SimPermDisabled: carrierText = getContext().getText(R.string.lockscreen_missing_sim_message_short); carrierHelpTextId = R.string.lockscreen_permanent_disabled_sim_instructions; - mUnlockDisabledDueToSimState = true; + mEmergencyButtonEnabledBecauseSimLocked = true; break; case SimMissingLocked: carrierText = makeCarierString(mPlmn, getContext().getText(R.string.lockscreen_missing_sim_message_short)); carrierHelpTextId = R.string.lockscreen_missing_sim_instructions; - mUnlockDisabledDueToSimState = true; + mEmergencyButtonEnabledBecauseSimLocked = true; break; case SimLocked: carrierText = makeCarierString(mPlmn, getContext().getText(R.string.lockscreen_sim_locked_message)); + mEmergencyButtonEnabledBecauseSimLocked = true; break; case SimPukLocked: carrierText = makeCarierString(mPlmn, getContext().getText(R.string.lockscreen_sim_puk_locked_message)); if (!mLockPatternUtils.isPukUnlockScreenEnable()) { - mUnlockDisabledDueToSimState = true; + // This means we're showing the PUK unlock screen + mEmergencyButtonEnabledBecauseSimLocked = true; } break; } setCarrierText(carrierText); setCarrierHelpText(carrierHelpTextId); + updateEmergencyCallButtonState(mPhoneState); } private View findViewById(int id) { @@ -569,9 +588,12 @@ class KeyguardStatusViewManager implements OnClickListener { private void updateEmergencyCallButtonState(int phoneState) { if (mEmergencyCallButton != null) { - boolean showIfCapable = mShowEmergencyButtonByDefault || mUnlockDisabledDueToSimState; + boolean enabledBecauseSimLocked = + mLockPatternUtils.isEmergencyCallEnabledWhileSimLocked() + && mEmergencyButtonEnabledBecauseSimLocked; + boolean shown = mEmergencyCallButtonEnabledInScreen || enabledBecauseSimLocked; mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton, - phoneState, showIfCapable); + phoneState, shown); } } @@ -594,7 +616,7 @@ class KeyguardStatusViewManager implements OnClickListener { public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { mPlmn = plmn; mSpn = spn; - updateCarrierTextWithSimStatus(mSimState); + updateCarrierStateWithSimStatus(mSimState); } public void onRingerModeChanged(int state) { @@ -602,6 +624,7 @@ class KeyguardStatusViewManager implements OnClickListener { } public void onPhoneStateChanged(int phoneState) { + mPhoneState = phoneState; updateEmergencyCallButtonState(phoneState); } @@ -618,7 +641,7 @@ class KeyguardStatusViewManager implements OnClickListener { private SimStateCallback mSimStateCallback = new SimStateCallback() { public void onSimStateChanged(State simState) { - updateCarrierTextWithSimStatus(simState); + updateCarrierStateWithSimStatus(simState); } }; @@ -635,11 +658,13 @@ class KeyguardStatusViewManager implements OnClickListener { * @return */ private static CharSequence makeCarierString(CharSequence plmn, CharSequence spn) { - if (plmn != null && spn == null) { - return plmn; - } else if (plmn != null && spn != null) { + final boolean plmnValid = !TextUtils.isEmpty(plmn); + final boolean spnValid = !TextUtils.isEmpty(spn); + if (plmnValid && spnValid) { return plmn + "|" + spn; - } else if (plmn == null && spn != null) { + } else if (plmnValid) { + return plmn; + } else if (spnValid) { return spn; } else { return ""; diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java index 008f5d8..b4b82aa 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java @@ -21,11 +21,14 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.ContentObserver; -import static android.os.BatteryManager.BATTERY_STATUS_CHARGING; import static android.os.BatteryManager.BATTERY_STATUS_FULL; import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN; +import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN; +import static android.os.BatteryManager.EXTRA_STATUS; +import static android.os.BatteryManager.EXTRA_PLUGGED; +import static android.os.BatteryManager.EXTRA_LEVEL; +import static android.os.BatteryManager.EXTRA_HEALTH; import android.media.AudioManager; -import android.media.IRemoteControlClient; import android.os.BatteryManager; import android.os.Handler; import android.os.Message; @@ -72,9 +75,7 @@ public class KeyguardUpdateMonitor { private boolean mDeviceProvisioned; - private int mBatteryLevel; - - private int mBatteryStatus; + private BatteryStatus mBatteryStatus; private CharSequence mTelephonyPlmn; private CharSequence mTelephonySpn; @@ -109,10 +110,14 @@ public class KeyguardUpdateMonitor { * the intent and provide a {@link SimCard.State} result. */ private static class SimArgs { - public final IccCard.State simState; - private SimArgs(Intent intent) { + SimArgs(IccCard.State state) { + simState = state; + } + + static SimArgs fromIntent(Intent intent) { + IccCard.State state; if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) { throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED"); } @@ -123,27 +128,28 @@ public class KeyguardUpdateMonitor { if (IccCard.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals( absentReason)) { - this.simState = IccCard.State.PERM_DISABLED; + state = IccCard.State.PERM_DISABLED; } else { - this.simState = IccCard.State.ABSENT; + state = IccCard.State.ABSENT; } } else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) { - this.simState = IccCard.State.READY; + state = IccCard.State.READY; } else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) { final String lockedReason = intent .getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON); if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) { - this.simState = IccCard.State.PIN_REQUIRED; + state = IccCard.State.PIN_REQUIRED; } else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) { - this.simState = IccCard.State.PUK_REQUIRED; + state = IccCard.State.PUK_REQUIRED; } else { - this.simState = IccCard.State.UNKNOWN; + state = IccCard.State.UNKNOWN; } } else if (IccCard.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) { - this.simState = IccCard.State.NETWORK_LOCKED; + state = IccCard.State.NETWORK_LOCKED; } else { - this.simState = IccCard.State.UNKNOWN; + state = IccCard.State.UNKNOWN; } + return new SimArgs(state); } public String toString() { @@ -151,6 +157,20 @@ public class KeyguardUpdateMonitor { } } + private static class BatteryStatus { + public final int status; + public final int level; + public final int plugged; + public final int health; + public BatteryStatus(int status, int level, int plugged, int health) { + this.status = status; + this.level = level; + this.plugged = plugged; + this.health = health; + } + + } + public KeyguardUpdateMonitor(Context context) { mContext = context; @@ -162,7 +182,7 @@ public class KeyguardUpdateMonitor { handleTimeUpdate(); break; case MSG_BATTERY_UPDATE: - handleBatteryUpdate(msg.arg1, msg.arg2); + handleBatteryUpdate((BatteryStatus) msg.obj); break; case MSG_CARRIER_INFO_UPDATE: handleCarrierInfoUpdate(); @@ -226,8 +246,7 @@ public class KeyguardUpdateMonitor { // take a guess to start mSimState = IccCard.State.READY; - mBatteryStatus = BATTERY_STATUS_UNKNOWN; - mBatteryLevel = 100; + mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0); mTelephonyPlmn = getDefaultPlmn(); @@ -256,18 +275,16 @@ public class KeyguardUpdateMonitor { mTelephonySpn = getTelephonySpnFrom(intent); mHandler.sendMessage(mHandler.obtainMessage(MSG_CARRIER_INFO_UPDATE)); } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) { - final int pluggedInStatus = intent - .getIntExtra("status", BATTERY_STATUS_UNKNOWN); - int batteryLevel = intent.getIntExtra("level", 0); + final int status = intent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN); + final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0); + final int level = intent.getIntExtra(EXTRA_LEVEL, 0); + final int health = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN); final Message msg = mHandler.obtainMessage( - MSG_BATTERY_UPDATE, - pluggedInStatus, - batteryLevel); + MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health)); mHandler.sendMessage(msg); } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) { mHandler.sendMessage(mHandler.obtainMessage( - MSG_SIM_STATE_CHANGE, - new SimArgs(intent))); + MSG_SIM_STATE_CHANGE, SimArgs.fromIntent(intent))); } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) { mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED, intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0)); @@ -325,15 +342,16 @@ public class KeyguardUpdateMonitor { /** * Handle {@link #MSG_BATTERY_UPDATE} */ - private void handleBatteryUpdate(int batteryStatus, int batteryLevel) { + private void handleBatteryUpdate(BatteryStatus batteryStatus) { if (DEBUG) Log.d(TAG, "handleBatteryUpdate"); - if (isBatteryUpdateInteresting(batteryStatus, batteryLevel)) { - mBatteryStatus = batteryStatus; - mBatteryLevel = batteryLevel; - final boolean pluggedIn = isPluggedIn(batteryStatus);; + final boolean batteryUpdateInteresting = + isBatteryUpdateInteresting(mBatteryStatus, batteryStatus); + mBatteryStatus = batteryStatus; + if (batteryUpdateInteresting) { for (int i = 0; i < mInfoCallbacks.size(); i++) { + // TODO: pass BatteryStatus object to onRefreshBatteryInfo() instead... mInfoCallbacks.get(i).onRefreshBatteryInfo( - shouldShowBatteryInfo(), pluggedIn, batteryLevel); + shouldShowBatteryInfo(),isPluggedIn(batteryStatus), batteryStatus.level); } } } @@ -377,39 +395,40 @@ public class KeyguardUpdateMonitor { } /** - * @param status One of the statuses of {@link android.os.BatteryManager} - * @return Whether the status maps to a status for being plugged in. + * @param pluggedIn state from {@link android.os.BatteryManager#EXTRA_PLUGGED} + * @return Whether the device is considered "plugged in." */ - private boolean isPluggedIn(int status) { - return status == BATTERY_STATUS_CHARGING || status == BATTERY_STATUS_FULL; + private static boolean isPluggedIn(BatteryStatus status) { + return status.plugged == BatteryManager.BATTERY_PLUGGED_AC + || status.plugged == BatteryManager.BATTERY_PLUGGED_USB; } - private boolean isBatteryUpdateInteresting(int batteryStatus, int batteryLevel) { - // change in plug is always interesting - final boolean isPluggedIn = isPluggedIn(batteryStatus); - final boolean wasPluggedIn = isPluggedIn(mBatteryStatus); + private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) { + final boolean nowPluggedIn = isPluggedIn(current); + final boolean wasPluggedIn = isPluggedIn(old); final boolean stateChangedWhilePluggedIn = - wasPluggedIn == true && isPluggedIn == true && (mBatteryStatus != batteryStatus); - if (wasPluggedIn != isPluggedIn || stateChangedWhilePluggedIn) { + wasPluggedIn == true && nowPluggedIn == true + && (old.status != current.status); + + // change in plug state is always interesting + if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) { return true; } // change in battery level while plugged in - if (isPluggedIn && mBatteryLevel != batteryLevel) { + if (nowPluggedIn && old.level != current.level) { return true; } - if (!isPluggedIn) { - // not plugged in and below threshold - if (isBatteryLow(batteryLevel) && batteryLevel != mBatteryLevel) { - return true; - } + // change where battery needs charging + if (!nowPluggedIn && isBatteryLow(current) && current.level != old.level) { + return true; } return false; } - private boolean isBatteryLow(int batteryLevel) { - return batteryLevel < LOW_BATTERY_THRESHOLD; + private static boolean isBatteryLow(BatteryStatus status) { + return status.level < LOW_BATTERY_THRESHOLD; } /** @@ -518,8 +537,8 @@ public class KeyguardUpdateMonitor { if (!mInfoCallbacks.contains(callback)) { mInfoCallbacks.add(callback); // Notify listener of the current state - callback.onRefreshBatteryInfo(shouldShowBatteryInfo(), isPluggedIn(mBatteryStatus), - mBatteryLevel); + callback.onRefreshBatteryInfo(shouldShowBatteryInfo(),isPluggedIn(mBatteryStatus), + mBatteryStatus.level); callback.onTimeChanged(); callback.onRingerModeChanged(mRingMode); callback.onPhoneStateChanged(mPhoneState); @@ -556,12 +575,16 @@ public class KeyguardUpdateMonitor { } /** - * Report that the user succesfully entered the sim pin or puk so we + * Report that the user successfully entered the SIM PIN or PUK/SIM PIN so we * have the information earlier than waiting for the intent * broadcast from the telephony code. + * + * NOTE: Because handleSimStateChange() invokes callbacks immediately without going + * through mHandler, this *must* be called from the UI thread. */ public void reportSimUnlocked() { mSimState = IccCard.State.READY; + handleSimStateChange(new SimArgs(mSimState)); } public boolean isKeyguardBypassEnabled() { @@ -573,16 +596,16 @@ public class KeyguardUpdateMonitor { } public boolean isDeviceCharged() { - return mBatteryStatus == BatteryManager.BATTERY_STATUS_FULL - || mBatteryLevel >= 100; // in case a particular device doesn't flag it + return mBatteryStatus.status == BATTERY_STATUS_FULL + || mBatteryStatus.level >= 100; // in case particular device doesn't flag it } public int getBatteryLevel() { - return mBatteryLevel; + return mBatteryStatus.level; } public boolean shouldShowBatteryInfo() { - return isPluggedIn(mBatteryStatus) || isBatteryLow(mBatteryLevel); + return isPluggedIn(mBatteryStatus) || isBatteryLow(mBatteryStatus); } public CharSequence getTelephonyPlmn() { diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java index 26bd697..f204070 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java @@ -46,6 +46,10 @@ public abstract class KeyguardViewBase extends FrameLayout { private KeyguardViewCallback mCallback; private AudioManager mAudioManager; private TelephonyManager mTelephonyManager = null; + // Whether the volume keys should be handled by keyguard. If true, then + // they will be handled here for specific media types such as music, otherwise + // the audio service will bring up the volume dialog. + private static final boolean KEYGUARD_MANAGES_VOLUME = true; // This is a faster way to draw the background on devices without hardware acceleration Drawable mBackgroundDrawable = new Drawable() { @@ -203,24 +207,28 @@ public abstract class KeyguardViewBase extends FrameLayout { case KeyEvent.KEYCODE_VOLUME_UP: case KeyEvent.KEYCODE_VOLUME_DOWN: case KeyEvent.KEYCODE_VOLUME_MUTE: { - synchronized (this) { - if (mAudioManager == null) { - mAudioManager = (AudioManager) getContext().getSystemService( - Context.AUDIO_SERVICE); + if (KEYGUARD_MANAGES_VOLUME) { + synchronized (this) { + if (mAudioManager == null) { + mAudioManager = (AudioManager) getContext().getSystemService( + Context.AUDIO_SERVICE); + } } + // Volume buttons should only function for music. + if (mAudioManager.isMusicActive()) { + // TODO: Actually handle MUTE. + mAudioManager.adjustStreamVolume( + AudioManager.STREAM_MUSIC, + keyCode == KeyEvent.KEYCODE_VOLUME_UP + ? AudioManager.ADJUST_RAISE + : AudioManager.ADJUST_LOWER, + 0); + } + // Don't execute default volume behavior + return true; + } else { + return false; } - // Volume buttons should only function for music. - if (mAudioManager.isMusicActive()) { - // TODO: Actually handle MUTE. - mAudioManager.adjustStreamVolume( - AudioManager.STREAM_MUSIC, - keyCode == KeyEvent.KEYCODE_VOLUME_UP - ? AudioManager.ADJUST_RAISE - : AudioManager.ADJUST_LOWER, - 0); - } - // Don't execute default volume behavior - return true; } } } else if (event.getAction() == KeyEvent.ACTION_UP) { diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java index 0499cfa..ff8d5ac 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java @@ -138,6 +138,7 @@ public class KeyguardViewManager implements KeyguardWindowController { lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED; } + lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY; 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 c802bc1..b514689 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java @@ -830,12 +830,13 @@ public class KeyguardViewMediator implements KeyguardViewCallback, * action should be posted to a handler. * * @param keyCode The keycode of the key that woke the device + * @param isDocked True if the device is in the dock * @return Whether we poked the wake lock (and turned the screen on) */ - public boolean onWakeKeyWhenKeyguardShowingTq(int keyCode) { + public boolean onWakeKeyWhenKeyguardShowingTq(int keyCode, boolean isDocked) { if (DEBUG) Log.d(TAG, "onWakeKeyWhenKeyguardShowing(" + keyCode + ")"); - if (isWakeKeyWhenKeyguardShowing(keyCode)) { + if (isWakeKeyWhenKeyguardShowing(keyCode, isDocked)) { // give the keyguard view manager a chance to adjust the state of the // keyguard based on the key that woke the device before poking // the wake lock @@ -846,11 +847,22 @@ public class KeyguardViewMediator implements KeyguardViewCallback, } } - private boolean isWakeKeyWhenKeyguardShowing(int keyCode) { + /** + * When the keyguard is showing we ignore some keys that might otherwise typically + * be considered wake keys. We filter them out here. + * + * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it + * is always considered a wake key. + */ + private boolean isWakeKeyWhenKeyguardShowing(int keyCode, boolean isDocked) { switch (keyCode) { + // ignore volume keys unless docked case KeyEvent.KEYCODE_VOLUME_UP: case KeyEvent.KEYCODE_VOLUME_DOWN: case KeyEvent.KEYCODE_VOLUME_MUTE: + return isDocked; + + // ignore media and camera keys case KeyEvent.KEYCODE_MUTE: case KeyEvent.KEYCODE_HEADSETHOOK: case KeyEvent.KEYCODE_MEDIA_PLAY: diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java index 0f21bdb..6eff4b6 100644 --- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java +++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java @@ -244,8 +244,14 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler // TODO: examine all widgets to derive clock status mUpdateMonitor.reportClockVisible(false); - // TODO: We should disable the wallpaper instead - setBackgroundColor(0xff000000); + // If there's not a bg protection view containing the transport, then show a black + // background. Otherwise, allow the normal background to show. + if (findViewById(R.id.transport_bg_protect) == null) { + // TODO: We should disable the wallpaper instead + setBackgroundColor(0xff000000); + } else { + resetBackground(); + } } public void requestHide(View view) { @@ -552,9 +558,12 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler mScreenOn = false; mForgotPattern = false; mHasOverlay = mUpdateMonitor.getPhoneState() != TelephonyManager.CALL_STATE_IDLE; - if (mMode == Mode.LockScreen) { + + // Emulate activity life-cycle for both lock and unlock screen. + if (mLockScreen != null) { ((KeyguardScreen) mLockScreen).onPause(); - } else { + } + if (mUnlockScreen != null) { ((KeyguardScreen) mUnlockScreen).onPause(); } @@ -645,9 +654,11 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler @Override public void show() { - if (mMode == Mode.LockScreen) { + // Emulate activity life-cycle for both lock and unlock screen. + if (mLockScreen != null) { ((KeyguardScreen) mLockScreen).onResume(); - } else { + } + if (mUnlockScreen != null) { ((KeyguardScreen) mUnlockScreen).onResume(); } diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java index 3469483..24a2420 100644 --- a/policy/src/com/android/internal/policy/impl/LockScreen.java +++ b/policy/src/com/android/internal/policy/impl/LockScreen.java @@ -34,6 +34,7 @@ import android.view.ViewGroup; import android.widget.*; import android.util.Log; import android.media.AudioManager; +import android.provider.MediaStore; import android.provider.Settings; import java.io.File; @@ -225,9 +226,10 @@ class LockScreen extends LinearLayout implements KeyguardScreen { mCallback.goToUnlockScreen(); } else if (target == 2 || target == 3) { // 2 = alt/portrait, 3 = alt/landscape if (!mCameraDisabled) { - // Broadcast an intent to start the Camera - Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null); - mContext.sendOrderedBroadcast(intent, null); + // Start the Camera + Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); mCallback.goToUnlockScreen(); } else { toggleRingMode(); diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java index 3ad716b..06cd69e 100644 --- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java +++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java @@ -35,15 +35,18 @@ import android.text.InputType; import android.text.TextWatcher; import android.text.method.DigitsKeyListener; import android.text.method.TextKeyListener; +import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup.LayoutParams; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; import android.widget.EditText; import android.widget.LinearLayout; +import android.widget.Space; import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; @@ -114,6 +117,7 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED, 0) != 0); + boolean imeOrDeleteButtonVisible = false; if (mIsAlpha) { // We always use the system IME for alpha keyboard, so hide lockscreen's soft keyboard mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA); @@ -129,6 +133,7 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen View pinDelete = findViewById(R.id.pinDel); if (pinDelete != null) { pinDelete.setVisibility(View.VISIBLE); + imeOrDeleteButtonVisible = true; pinDelete.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { @@ -181,6 +186,7 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen Context.INPUT_METHOD_SERVICE); if (mIsAlpha && switchImeButton != null && hasMultipleEnabledIMEsOrSubtypes(imm, false)) { switchImeButton.setVisibility(View.VISIBLE); + imeOrDeleteButtonVisible = true; switchImeButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { mCallback.pokeWakelock(); // Leave the screen on a bit longer @@ -188,6 +194,16 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen } }); } + + // If no icon is visible, reset the left margin on the password field so the text is + // still centered. + if (!imeOrDeleteButtonVisible) { + android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams(); + if (params instanceof MarginLayoutParams) { + ((MarginLayoutParams)params).leftMargin = 0; + mPasswordEntry.setLayoutParams(params); + } + } } /** diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index af86ae9..f1fe43b 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -1816,22 +1816,42 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { @Override public boolean dispatchKeyShortcutEvent(KeyEvent ev) { - // Perform the shortcut (mPreparedPanel can be null since - // global shortcuts (such as search) don't rely on a - // prepared panel or menu). - boolean handled = performPanelShortcut(mPreparedPanel, ev.getKeyCode(), ev, - Menu.FLAG_PERFORM_NO_CLOSE); - if (handled) { - if (mPreparedPanel != null) { - mPreparedPanel.isHandled = true; + // If the panel is already prepared, then perform the shortcut using it. + boolean handled; + if (mPreparedPanel != null) { + handled = performPanelShortcut(mPreparedPanel, ev.getKeyCode(), ev, + Menu.FLAG_PERFORM_NO_CLOSE); + if (handled) { + if (mPreparedPanel != null) { + mPreparedPanel.isHandled = true; + } + return true; } - return true; } // Shortcut not handled by the panel. Dispatch to the view hierarchy. final Callback cb = getCallback(); - return cb != null && !isDestroyed() && mFeatureId < 0 ? cb.dispatchKeyShortcutEvent(ev) - : super.dispatchKeyShortcutEvent(ev); + handled = cb != null && !isDestroyed() && mFeatureId < 0 + ? cb.dispatchKeyShortcutEvent(ev) : super.dispatchKeyShortcutEvent(ev); + if (handled) { + return true; + } + + // If the panel is not prepared, then we may be trying to handle a shortcut key + // combination such as Control+C. Temporarily prepare the panel then mark it + // unprepared again when finished to ensure that the panel will again be prepared + // the next time it is shown for real. + if (mPreparedPanel == null) { + PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true); + preparePanel(st, ev); + handled = performPanelShortcut(st, ev.getKeyCode(), ev, + Menu.FLAG_PERFORM_NO_CLOSE); + st.isPrepared = false; + if (handled) { + return true; + } + } + return false; } @Override @@ -2562,6 +2582,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (targetPreHoneycomb || (targetPreIcs && targetHcNeedsOptions && noActionBar)) { addFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY); + } else { + clearFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY); } if (mAlwaysReadCloseOnTouchAttr || getContext().getApplicationInfo().targetSdkVersion diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 0a77654..0b223c1 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -39,7 +39,7 @@ import android.database.ContentObserver; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.RectF; -import android.os.Binder; +import android.os.BatteryManager; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -68,8 +68,10 @@ import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; import android.util.Slog; +import android.util.SparseArray; import android.view.Gravity; import android.view.HapticFeedbackConstants; +import android.view.IApplicationToken; import android.view.IWindowManager; import android.view.InputChannel; import android.view.InputDevice; @@ -157,6 +159,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final boolean SHOW_STARTING_ANIMATIONS = true; static final boolean SHOW_PROCESSES_ON_ALT_MENU = false; + // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key. + // No longer recommended for desk docks; still useful in car docks. + static final boolean ENABLE_CAR_DOCK_HOME_CAPTURE = true; + static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false; + static final int LONG_PRESS_POWER_NOTHING = 0; static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1; static final int LONG_PRESS_POWER_SHUT_OFF = 2; @@ -221,7 +228,30 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Useful scan codes. private static final int SW_LID = 0x00; private static final int BTN_MOUSE = 0x110; - + + /* Table of Application Launch keys. Maps from key codes to intent categories. + * + * These are special keys that are used to launch particular kinds of applications, + * such as a web browser. HID defines nearly a hundred of them in the Consumer (0x0C) + * usage page. We don't support quite that many yet... + */ + static SparseArray<String> sApplicationLaunchKeyCategories; + static { + sApplicationLaunchKeyCategories = new SparseArray<String>(); + sApplicationLaunchKeyCategories.append( + KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER); + sApplicationLaunchKeyCategories.append( + KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL); + sApplicationLaunchKeyCategories.append( + KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS); + sApplicationLaunchKeyCategories.append( + KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR); + sApplicationLaunchKeyCategories.append( + KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC); + sApplicationLaunchKeyCategories.append( + KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR); + } + /** * Lock protecting internal state. Must not call out into window * manager with lock held. (This lock will be acquired in places @@ -268,9 +298,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { GlobalActions mGlobalActions; volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread boolean mPendingPowerKeyUpCanceled; - RecentApplicationsDialog mRecentAppsDialog; Handler mHandler; + static final int RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS = 0; + static final int RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW = 1; + static final int RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH = 2; + + RecentApplicationsDialog mRecentAppsDialog; + int mRecentAppsDialogHeldModifiers; + private static final int LID_ABSENT = -1; private static final int LID_CLOSED = 0; private static final int LID_OPEN = 1; @@ -310,6 +346,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // The last window we were told about in focusChanged. WindowState mFocusedWindow; + IApplicationToken mFocusedApp; private final InputHandler mPointerLocationInputHandler = new BaseInputHandler() { @Override @@ -360,6 +397,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mResettingSystemUiFlags = 0; // Bits that we are currently always keeping cleared. int mForceClearedSystemUiFlags = 0; + // What we last reported to system UI about whether the compatibility + // menu needs to be displayed. + boolean mLastFocusNeedsMenu = false; FakeWindow mHideNavFakeWindow = null; @@ -370,8 +410,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final Rect mTmpNavigationFrame = new Rect(); WindowState mTopFullscreenOpaqueWindowState; - WindowState mTopAppWindowState; - WindowState mLastTopAppWindowState; boolean mTopIsFullscreen; boolean mForceStatusBar; boolean mHideLockScreen; @@ -388,10 +426,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mLockScreenTimeout; boolean mLockScreenTimerActive; - // visual screen saver support - int mScreenSaverTimeout; - boolean mScreenSaverEnabled = false; - // Behavior of ENDCALL Button. (See Settings.System.END_BUTTON_BEHAVIOR.) int mEndcallBehavior; @@ -454,8 +488,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { Settings.Secure.DEFAULT_INPUT_METHOD), false, this); resolver.registerContentObserver(Settings.System.getUriFor( "fancy_rotation_anim"), false, this); - resolver.registerContentObserver(Settings.System.getUriFor( - Settings.Secure.DREAM_TIMEOUT), false, this); updateSettings(); } @@ -493,7 +525,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { return true; } if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) || - (mDeskDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_DESK)) { + (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK + || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK + || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) { // enable accelerometer if we are docked in a dock that enables accelerometer // orientation management, return true; @@ -665,7 +699,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) { - showOrHideRecentAppsDialog(0, true /*dismissIfShown*/); + showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS); } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) { try { mStatusBarService.toggleRecentApps(); @@ -676,10 +710,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { } /** - * Create (if necessary) and launch the recent apps dialog, or hide it if it is - * already shown. + * Create (if necessary) and show or dismiss the recent apps dialog according + * according to the requested behavior. */ - void showOrHideRecentAppsDialog(final int heldModifiers, final boolean dismissIfShown) { + void showOrHideRecentAppsDialog(final int behavior) { mHandler.post(new Runnable() { @Override public void run() { @@ -687,12 +721,33 @@ public class PhoneWindowManager implements WindowManagerPolicy { mRecentAppsDialog = new RecentApplicationsDialog(mContext); } if (mRecentAppsDialog.isShowing()) { - if (dismissIfShown) { - mRecentAppsDialog.dismiss(); + switch (behavior) { + case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS: + mRecentAppsDialog.dismiss(); + break; + case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH: + mRecentAppsDialog.dismissAndSwitch(); + break; + case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW: + default: + break; } } else { - mRecentAppsDialog.setHeldModifiers(heldModifiers); - mRecentAppsDialog.show(); + switch (behavior) { + case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS: + mRecentAppsDialog.show(); + break; + case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW: + try { + mWindowManager.setInTouchMode(false); + } catch (RemoteException e) { + } + mRecentAppsDialog.show(); + break; + case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH: + default: + break; + } } } }); @@ -760,6 +815,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED); } + mVibrator = new Vibrator(); mLongPressVibePattern = getLongIntArray(mContext.getResources(), com.android.internal.R.array.config_longPressVibePattern); @@ -908,11 +964,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mHasSoftInput = hasSoftInput; updateRotation = true; } - - mScreenSaverTimeout = Settings.System.getInt(resolver, - Settings.Secure.DREAM_TIMEOUT, 0); - mScreenSaverEnabled = true; - updateScreenSaverTimeoutLocked(); } if (updateRotation) { updateRotation(true); @@ -1183,7 +1234,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { } public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation) { - return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation); + // This is the same as getNonDecorDisplayHeight, unless the status bar + // can hide. If the status bar can hide, we don't count that as part + // of the decor; however for purposes of configurations, we do want to + // exclude it since applications can't generally use that part of the + // screen. + return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation) + - (mStatusBarCanHide ? mStatusBarHeight : 0); } public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) { @@ -1568,7 +1625,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { return 0; } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) { if (down && repeatCount == 0) { - showOrHideRecentAppsDialog(0, true /*dismissIfShown*/); + showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS); } return -1; } @@ -1604,6 +1661,62 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + // Invoke shortcuts using Meta. + if (down && repeatCount == 0 + && (metaState & KeyEvent.META_META_ON) != 0) { + final KeyCharacterMap kcm = event.getKeyCharacterMap(); + Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, + metaState & ~(KeyEvent.META_META_ON + | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON)); + if (shortcutIntent != null) { + shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + try { + mContext.startActivity(shortcutIntent); + } catch (ActivityNotFoundException ex) { + Slog.w(TAG, "Dropping shortcut key combination because " + + "the activity to which it is registered was not found: " + + "META+" + KeyEvent.keyCodeToString(keyCode), ex); + } + return -1; + } + } + + // Handle application launch keys. + if (down && repeatCount == 0) { + String category = sApplicationLaunchKeyCategories.get(keyCode); + if (category != null) { + Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + try { + mContext.startActivity(intent); + } catch (ActivityNotFoundException ex) { + Slog.w(TAG, "Dropping application launch key because " + + "the activity to which it is registered was not found: " + + "keyCode=" + keyCode + ", category=" + category, ex); + } + return -1; + } + } + + // Display task switcher for ALT-TAB or Meta-TAB. + if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) { + if (mRecentAppsDialogHeldModifiers == 0) { + final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK; + if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON) + || KeyEvent.metaStateHasModifiers( + shiftlessModifiers, KeyEvent.META_META_ON)) { + mRecentAppsDialogHeldModifiers = shiftlessModifiers; + showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW); + return -1; + } + } + } else if (!down && mRecentAppsDialogHeldModifiers != 0 + && (metaState & mRecentAppsDialogHeldModifiers) == 0) { + mRecentAppsDialogHeldModifiers = 0; + showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH); + } + + // Let the application handle the key. return 0; } @@ -1625,39 +1738,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { final KeyCharacterMap kcm = event.getKeyCharacterMap(); final int keyCode = event.getKeyCode(); final int metaState = event.getMetaState(); - final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN - && event.getRepeatCount() == 0; - - if (initialDown) { - // Invoke shortcuts using Meta as a fallback. - if ((metaState & KeyEvent.META_META_ON) != 0) { - Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, - metaState & ~(KeyEvent.META_META_ON - | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON)); - if (shortcutIntent != null) { - shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - try { - mContext.startActivity(shortcutIntent); - } catch (ActivityNotFoundException ex) { - Slog.w(TAG, "Dropping shortcut key combination because " - + "the activity to which it is registered was not found: " - + "META+" + KeyEvent.keyCodeToString(keyCode), ex); - } - return null; - } - } - - // Display task switcher for ALT-TAB or Meta-TAB. - if (keyCode == KeyEvent.KEYCODE_TAB) { - final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK; - if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON) - || KeyEvent.metaStateHasModifiers( - shiftlessModifiers, KeyEvent.META_META_ON)) { - showOrHideRecentAppsDialog(shiftlessModifiers, false /*dismissIfShown*/); - return null; - } - } - } // Check for fallback actions specified by the key character map. if (getFallbackAction(kcm, keyCode, metaState, mFallbackAction)) { @@ -2243,7 +2323,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ public void beginAnimationLw(int displayWidth, int displayHeight) { mTopFullscreenOpaqueWindowState = null; - mTopAppWindowState = null; mForceStatusBar = false; mHideLockScreen = false; @@ -2281,12 +2360,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } } - if (mTopAppWindowState == null && win.isVisibleOrBehindKeyguardLw()) { - if (attrs.type >= FIRST_APPLICATION_WINDOW - && attrs.type <= LAST_APPLICATION_WINDOW) { - mTopAppWindowState = win; - } - } } /** {@inheritDoc} */ @@ -2342,35 +2415,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mTopIsFullscreen = topIsFullscreen; - if (mTopAppWindowState != null && mTopAppWindowState != mLastTopAppWindowState) { - mLastTopAppWindowState = mTopAppWindowState; - - final boolean topNeedsMenu = (mTopAppWindowState.getAttrs().flags - & WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0; - - 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.topAppWindowChanged(topNeedsMenu); - } 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) { @@ -2479,7 +2523,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // keyguard, then we need to have it turn on the // screen once it is shown. mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq( - KeyEvent.KEYCODE_POWER); + KeyEvent.KEYCODE_POWER, mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED); } } else { // Light up the keyboard if we are sliding up. @@ -2699,7 +2743,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (down && isWakeKey) { if (keyguardActive) { // If the keyguard is showing, let it decide what to do with the wake key. - mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode); + mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode, + mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED); } else { // Otherwise, wake the device ourselves. result |= ACTION_POKE_USER_ACTIVITY; @@ -2987,7 +3032,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { synchronized (mLock) { updateOrientationListenerLp(); updateLockScreenTimeout(); - updateScreenSaverTimeoutLocked(); } } @@ -3034,7 +3078,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mScreenOnEarly = true; updateOrientationListenerLp(); updateLockScreenTimeout(); - updateScreenSaverTimeoutLocked(); } } @@ -3124,11 +3167,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { sensorRotation = lastRotation; } - int preferredRotation = -1; - if (mHdmiPlugged) { - // Ignore sensor when plugged into HDMI. - preferredRotation = mHdmiRotation; - } else if (mLidOpen == LID_OPEN && mLidOpenRotation >= 0) { + final int preferredRotation; + if (mLidOpen == LID_OPEN && mLidOpenRotation >= 0) { // Ignore sensor when lid switch is open and rotation is forced. preferredRotation = mLidOpenRotation; } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR @@ -3138,13 +3178,19 @@ public class PhoneWindowManager implements WindowManagerPolicy { // enable 180 degree rotation while docked. preferredRotation = mCarDockEnablesAccelerometer ? sensorRotation : mCarDockRotation; - } else if (mDockMode == Intent.EXTRA_DOCK_STATE_DESK + } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK + || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK + || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK) && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) { // Ignore sensor when in desk dock unless explicitly enabled. // This case can override the behavior of NOSENSOR, and can also // enable 180 degree rotation while docked. preferredRotation = mDeskDockEnablesAccelerometer ? sensorRotation : mDeskDockRotation; + } else if (mHdmiPlugged) { + // Ignore sensor when plugged into HDMI. + // Note that the dock orientation overrides the HDMI orientation. + preferredRotation = mHdmiRotation; } else if ((mAccelerometerDefault != 0 /* implies not rotation locked */ && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)) @@ -3171,28 +3217,39 @@ public class PhoneWindowManager implements WindowManagerPolicy { } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) { // Apply rotation lock. preferredRotation = mUserRotation; + } else { + // No overriding preference. + // We will do exactly what the application asked us to do. + preferredRotation = -1; } - // TODO: Sometimes, we might want to override the application-requested - // orientation, such as when HDMI is plugged in or when docked. - // We can do that by modifying the appropriate cases above to return - // the preferred orientation directly instead of continuing on down here. - switch (orientation) { case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: - // Always return portrait if orientation set to portrait. + // Return portrait unless overridden. + if (isAnyPortrait(preferredRotation)) { + return preferredRotation; + } return mPortraitRotation; case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: - // Always return landscape if orientation set to landscape. + // Return landscape unless overridden. + if (isLandscapeOrSeascape(preferredRotation)) { + return preferredRotation; + } return mLandscapeRotation; case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: - // Always return portrait if orientation set to portrait. + // Return reverse portrait unless overridden. + if (isAnyPortrait(preferredRotation)) { + return preferredRotation; + } return mUpsideDownRotation; case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: - // Always return seascape if orientation set to reverse landscape. + // Return seascape unless overridden. + if (isLandscapeOrSeascape(preferredRotation)) { + return preferredRotation; + } return mSeascapeRotation; case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: @@ -3376,6 +3433,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { WindowManager.LayoutParams.FLAG_DIM_BEHIND | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); mBootMsgDialog.getWindow().setDimAmount(1); + WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes(); + lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; + mBootMsgDialog.getWindow().setAttributes(lp); mBootMsgDialog.setCancelable(false); mBootMsgDialog.show(); } @@ -3416,73 +3476,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); } } - - // Turn this off for now, screen savers not currently enabled. - if (false) { - synchronized (mLock) { - updateScreenSaverTimeoutLocked(); - } - } - } - - Runnable mScreenSaverActivator = null; - /*new Runnable() { - public void run() { - synchronized (this) { - if (!(mScreenSaverEnabled && mScreenOn)) { - Log.w(TAG, "mScreenSaverActivator ran, but the screensaver should not be showing. Who's driving this thing?"); - return; - } - - if (localLOGV) Log.v(TAG, "mScreenSaverActivator entering dreamland"); - try { - String component = Settings.System.getString( - mContext.getContentResolver(), Settings.Secure.DREAM_COMPONENT); - if (component != null) { - ComponentName cn = ComponentName.unflattenFromString(component); - Intent intent = new Intent(Intent.ACTION_MAIN) - .setComponent(cn) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS - | Intent.FLAG_ACTIVITY_NO_USER_ACTION - | Intent.FLAG_ACTIVITY_SINGLE_TOP); - mContext.startActivity(intent); - } else { - Log.e(TAG, "Couldn't start screen saver: none selected"); - } - } catch (android.content.ActivityNotFoundException exc) { - // no screensaver? give up - Log.e(TAG, "Couldn't start screen saver: none installed"); - } - } - } - }; - */ - - // Must call while holding mLock - private void updateScreenSaverTimeoutLocked() { - if (mScreenSaverActivator == null) return; - - // GAH... acquiring a lock within a lock? Please let's fix this. - // (Also note this is called from userActivity, with the power manager - // lock held. Not good.) - synchronized (mScreenSaverActivator) { - mHandler.removeCallbacks(mScreenSaverActivator); - if (mScreenSaverEnabled && mScreenOnEarly && mScreenSaverTimeout > 0) { - if (localLOGV) - Log.v(TAG, "scheduling screensaver for " + mScreenSaverTimeout + "ms from now"); - mHandler.postDelayed(mScreenSaverActivator, mScreenSaverTimeout); - } else { - if (localLOGV) { - if (mScreenSaverTimeout == 0) - Log.v(TAG, "screen saver disabled by user"); - else if (!mScreenOnEarly) - Log.v(TAG, "screen saver disabled while screen off"); - else - Log.v(TAG, "screen saver disabled by wakelock"); - } - } - } } Runnable mScreenLockTimeout = new Runnable() { @@ -3533,21 +3526,35 @@ public class PhoneWindowManager implements WindowManagerPolicy { } /** - * Return an Intent to launch the currently active dock as home. Returns - * null if the standard home should be launched. + * Return an Intent to launch the currently active dock app as home. Returns + * null if the standard home should be launched, which is the case if any of the following is + * true: + * <ul> + * <li>The device is not in either car mode or desk mode + * <li>The device is in car mode but ENABLE_CAR_DOCK_HOME_CAPTURE is false + * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false + * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME + * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME + * </ul> * @return */ Intent createHomeDockIntent() { - Intent intent; + Intent intent = null; // What home does is based on the mode, not the dock state. That // is, when in car mode you should be taken to car home regardless // of whether we are actually in a car dock. if (mUiMode == Configuration.UI_MODE_TYPE_CAR) { - intent = mCarDockIntent; + if (ENABLE_CAR_DOCK_HOME_CAPTURE) { + intent = mCarDockIntent; + } } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) { - intent = mDeskDockIntent; - } else { + if (ENABLE_DESK_DOCK_HOME_CAPTURE) { + intent = mDeskDockIntent; + } + } + + if (intent == null) { return null; } @@ -3674,11 +3681,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } public void screenOnStartedLw() { - // The window manager has just grabbed a wake lock. This is our cue to disable the screen - // saver. - synchronized (mLock) { - mScreenSaverEnabled = false; - } } public void screenOnStoppedLw() { @@ -3687,13 +3689,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { long curTime = SystemClock.uptimeMillis(); mPowerManager.userActivity(curTime, false, LocalPowerManager.OTHER_EVENT); } - - synchronized (mLock) { - // even if the keyguard is up, now that all the wakelocks have been released, we - // should re-enable the screen saver - mScreenSaverEnabled = true; - updateScreenSaverTimeoutLocked(); - } } } @@ -3712,10 +3707,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { & ~mResettingSystemUiFlags & ~mForceClearedSystemUiFlags; int diff = visibility ^ mLastSystemUiFlags; - if (diff == 0) { + final boolean needsMenu = mFocusedWindow.getNeedsMenuLw(mTopFullscreenOpaqueWindowState); + if (diff == 0 && mLastFocusNeedsMenu == needsMenu + && mFocusedApp == mFocusedWindow.getAppToken()) { return 0; } mLastSystemUiFlags = visibility; + mLastFocusNeedsMenu = needsMenu; + mFocusedApp = mFocusedWindow.getAppToken(); mHandler.post(new Runnable() { public void run() { if (mStatusBarService == null) { @@ -3725,6 +3724,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mStatusBarService != null) { try { mStatusBarService.setSystemUiVisibility(visibility); + mStatusBarService.topAppWindowChanged(needsMenu); } catch (RemoteException e) { // not much to be done mStatusBarService = null; @@ -3757,6 +3757,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(" mForceClearedSystemUiFlags=0x"); pw.println(Integer.toHexString(mForceClearedSystemUiFlags)); } + if (mLastFocusNeedsMenu) { + pw.print(prefix); pw.print("mLastFocusNeedsMenu="); + pw.println(mLastFocusNeedsMenu); + } pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode); pw.print(" mDockMode="); pw.print(mDockMode); pw.print(" mCarDockRotation="); pw.print(mCarDockRotation); diff --git a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java index aa00fbd..b9903dd 100644 --- a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java +++ b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java @@ -71,8 +71,6 @@ public class RecentApplicationsDialog extends Dialog implements OnClickListener } }; - private int mHeldModifiers; - public RecentApplicationsDialog(Context context) { super(context, com.android.internal.R.style.Theme_Dialog_RecentApplications); @@ -124,17 +122,6 @@ public class RecentApplicationsDialog extends Dialog implements OnClickListener } } - /** - * Sets the modifier keys that are being held to keep the dialog open, or 0 if none. - * Used to make the recent apps dialog automatically dismiss itself when the modifiers - * all go up. - * @param heldModifiers The held key modifiers, such as {@link KeyEvent#META_ALT_ON}. - * Should exclude shift. - */ - public void setHeldModifiers(int heldModifiers) { - mHeldModifiers = heldModifiers; - } - @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_TAB) { @@ -174,30 +161,27 @@ public class RecentApplicationsDialog extends Dialog implements OnClickListener return super.onKeyDown(keyCode, event); } - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - if (mHeldModifiers != 0 && (event.getModifiers() & mHeldModifiers) == 0) { - final int numIcons = mIcons.length; - RecentTag tag = null; - for (int i = 0; i < numIcons; i++) { - if (mIcons[i].getVisibility() != View.VISIBLE) { + /** + * Dismiss the dialog and switch to the selected application. + */ + public void dismissAndSwitch() { + final int numIcons = mIcons.length; + RecentTag tag = null; + for (int i = 0; i < numIcons; i++) { + if (mIcons[i].getVisibility() != View.VISIBLE) { + break; + } + if (i == 0 || mIcons[i].hasFocus()) { + tag = (RecentTag) mIcons[i].getTag(); + if (mIcons[i].hasFocus()) { break; } - if (i == 0 || mIcons[i].hasFocus()) { - tag = (RecentTag) mIcons[i].getTag(); - if (mIcons[i].hasFocus()) { - break; - } - } - } - if (tag != null) { - switchTo(tag); } - dismiss(); - return true; } - - return super.onKeyUp(keyCode, event); + if (tag != null) { + switchTo(tag); + } + dismiss(); } /** diff --git a/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java b/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java index 6acd1c5..ba06996 100644 --- a/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java +++ b/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java @@ -106,7 +106,7 @@ public class SimPukUnlockScreen extends LinearLayout implements KeyguardScreen, mHeaderText.setSelected(true); mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, updateMonitor, - lockpatternutils, callback, true); + lockpatternutils, callback, false); mPinText.setFocusableInTouchMode(true); mPinText.setOnFocusChangeListener(this); @@ -242,20 +242,24 @@ public class SimPukUnlockScreen extends LinearLayout implements KeyguardScreen, new CheckSimPuk(mPukText.getText().toString(), mPinText.getText().toString()) { - void onSimLockChangedResponse(boolean success) { - if (mSimUnlockProgressDialog != null) { - mSimUnlockProgressDialog.hide(); - } - if (success) { - // before closing the keyguard, report back that - // the sim is unlocked so it knows right away - mUpdateMonitor.reportSimUnlocked(); - mCallback.goToUnlockScreen(); - } else { - mHeaderText.setText(R.string.badPuk); - mPukText.setText(""); - mPinText.setText(""); - } + void onSimLockChangedResponse(final boolean success) { + mPinText.post(new Runnable() { + public void run() { + if (mSimUnlockProgressDialog != null) { + mSimUnlockProgressDialog.hide(); + } + if (success) { + // before closing the keyguard, report back that + // the sim is unlocked so it knows right away + mUpdateMonitor.reportSimUnlocked(); + mCallback.goToUnlockScreen(); + } else { + mHeaderText.setText(R.string.badPuk); + mPukText.setText(""); + mPinText.setText(""); + } + } + }); } }.start(); } @@ -379,6 +383,9 @@ public class SimPukUnlockScreen extends LinearLayout implements KeyguardScreen, public void onClick(View v) { if (v == mCancelButton) { + // clear the PIN/PUK entry fields if the user cancels + mPinText.setText(""); + mPukText.setText(""); mCallback.goToLockScreen(); return; } diff --git a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java b/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java index 184748a..9604cdc 100644 --- a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java +++ b/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java @@ -100,7 +100,7 @@ public class SimUnlockScreen extends LinearLayout implements KeyguardScreen, Vie mOkButton.setOnClickListener(this); mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, updateMonitor, - lockpatternutils, callback, true); + lockpatternutils, callback, false); setFocusableInTouchMode(true); } @@ -214,21 +214,25 @@ public class SimUnlockScreen extends LinearLayout implements KeyguardScreen, Vie getSimUnlockProgressDialog().show(); new CheckSimPin(mPinText.getText().toString()) { - void onSimLockChangedResponse(boolean success) { - if (mSimUnlockProgressDialog != null) { - mSimUnlockProgressDialog.hide(); - } - if (success) { - // before closing the keyguard, report back that - // the sim is unlocked so it knows right away - mUpdateMonitor.reportSimUnlocked(); - mCallback.goToUnlockScreen(); - } else { - mHeaderText.setText(R.string.keyguard_password_wrong_pin_code); - mPinText.setText(""); - mEnteredDigits = 0; - } - mCallback.pokeWakelock(); + void onSimLockChangedResponse(final boolean success) { + mPinText.post(new Runnable() { + public void run() { + if (mSimUnlockProgressDialog != null) { + mSimUnlockProgressDialog.hide(); + } + if (success) { + // before closing the keyguard, report back that + // the sim is unlocked so it knows right away + mUpdateMonitor.reportSimUnlocked(); + mCallback.goToUnlockScreen(); + } else { + mHeaderText.setText(R.string.keyguard_password_wrong_pin_code); + mPinText.setText(""); + mEnteredDigits = 0; + } + mCallback.pokeWakelock(); + } + }); } }.start(); } @@ -355,6 +359,7 @@ public class SimUnlockScreen extends LinearLayout implements KeyguardScreen, Vie public void onClick(View v) { if (v == mCancelButton) { + mPinText.setText(""); // clear the PIN entry field if the user cancels mCallback.goToLockScreen(); return; } |