Loading policy/com/android/internal/policy/impl/AccountUnlockScreen.java +92 −4 Original line number Diff line number Diff line Loading @@ -28,8 +28,11 @@ import android.content.ServiceConnection; import android.graphics.Rect; import android.os.IBinder; import android.os.RemoteException; import android.text.Editable; import android.text.InputFilter; import android.text.LoginFilter; import android.text.TextWatcher; import android.text.TextUtils; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; Loading @@ -47,13 +50,16 @@ import android.widget.TextView; * IAccountsService. */ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScreen, View.OnClickListener, ServiceConnection { View.OnClickListener, ServiceConnection, TextWatcher { private static final String LOCK_PATTERN_PACKAGE = "com.android.settings"; private static final String LOCK_PATTERN_CLASS = "com.android.settings.ChooseLockPattern"; /** * The amount of millis to stay awake once this screen detects activity */ private static final int AWAKE_POKE_MILLIS = 30000; private final KeyguardScreenCallback mCallback; private final LockPatternUtils mLockPatternUtils; private IAccountsService mAccountsService; Loading Loading @@ -87,8 +93,10 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree mLogin = (EditText) findViewById(R.id.login); mLogin.setFilters(new InputFilter[] { new LoginFilter.UsernameFilterGeneric() } ); mLogin.addTextChangedListener(this); mPassword = (EditText) findViewById(R.id.password); mPassword.addTextChangedListener(this); mOk = (Button) findViewById(R.id.ok); mOk.setOnClickListener(this); Loading @@ -105,6 +113,16 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree } } public void afterTextChanged(Editable s) { } public void beforeTextChanged(CharSequence s, int start, int count, int after) { } public void onTextChanged(CharSequence s, int start, int before, int count) { mCallback.pokeWakelock(AWAKE_POKE_MILLIS); } @Override protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) { Loading @@ -112,6 +130,11 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree return mLogin.requestFocus(direction, previouslyFocusedRect); } /** {@inheritDoc} */ public boolean needsInput() { return true; } /** {@inheritDoc} */ public void onPause() { Loading @@ -132,6 +155,7 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree /** {@inheritDoc} */ public void onClick(View v) { mCallback.pokeWakelock(); if (v == mOk) { if (checkPassword()) { // clear out forgotten password Loading Loading @@ -167,11 +191,75 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree return super.dispatchKeyEvent(event); } /** * Given the string the user entered in the 'username' field, find * the stored account that they probably intended. Prefer, in order: * * - an exact match for what was typed, or * - a case-insensitive match for what was typed, or * - if they didn't include a domain, an exact match of the username, or * - if they didn't include a domain, a case-insensitive * match of the username. * * If there is a tie for the best match, choose neither -- * the user needs to be more specific. * * @return an account name from the database, or null if we can't * find a single best match. */ private String findIntendedAccount(String username) { String[] accounts = null; try { accounts = mAccountsService.getAccounts(); } catch (RemoteException e) { return null; } if (accounts == null) { return null; } // Try to figure out which account they meant if they // typed only the username (and not the domain), or got // the case wrong. String bestAccount = null; int bestScore = 0; for (String a: accounts) { int score = 0; if (username.equals(a)) { score = 4; } else if (username.equalsIgnoreCase(a)) { score = 3; } else if (username.indexOf('@') < 0) { int i = a.indexOf('@'); if (i >= 0) { String aUsername = a.substring(0, i); if (username.equals(aUsername)) { score = 2; } else if (username.equalsIgnoreCase(aUsername)) { score = 1; } } } if (score > bestScore) { bestAccount = a; bestScore = score; } else if (score == bestScore) { bestAccount = null; } } return bestAccount; } private boolean checkPassword() { final String login = mLogin.getText().toString(); final String password = mPassword.getText().toString(); try { return mAccountsService.shouldUnlock(login, password); String account = findIntendedAccount(login); if (account == null) { return false; } return mAccountsService.shouldUnlock(account, password); } catch (RemoteException e) { return false; } Loading policy/com/android/internal/policy/impl/GlobalActions.java +150 −50 Original line number Diff line number Diff line Loading @@ -16,29 +16,30 @@ package com.android.internal.policy.impl; import com.android.internal.R; import com.google.android.collect.Lists; import android.app.AlertDialog; import android.app.StatusBarManager; import android.content.Context; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.DialogInterface; import android.media.AudioManager; import android.os.LocalPowerManager; import android.os.Handler; import android.os.Message; import android.os.SystemClock; import android.provider.Settings; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.android.internal.R; import com.google.android.collect.Lists; import java.util.ArrayList; Loading @@ -49,34 +50,41 @@ import java.util.ArrayList; */ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterface.OnClickListener { private static final String TAG = "GlobalActions"; private StatusBarManager mStatusBar; private final Context mContext; private final LocalPowerManager mPowerManager; private final AudioManager mAudioManager; private ArrayList<Action> mItems; private AlertDialog mDialog; private ToggleAction mSilentModeToggle; private ToggleAction mAirplaneModeOn; private MyAdapter mAdapter; private boolean mKeyguardShowing = false; private boolean mDeviceProvisioned = false; private ToggleAction.State mAirplaneState = ToggleAction.State.Off; /** * @param context everything needs a context :) * @param powerManager used to turn the screen off (the lock action). * @param context everything needs a context :( */ public GlobalActions(Context context, LocalPowerManager powerManager) { public GlobalActions(Context context) { mContext = context; mPowerManager = powerManager; mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); // receive broadcasts IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); context.registerReceiver(mBroadcastReceiver, filter); // get notified of phone state changes TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE); } /** Loading Loading @@ -123,29 +131,48 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } }; mItems = Lists.newArrayList( /* Disabled pending bug 1304831 -- key or touch events wake up device before it * can go to sleep. // first: lock screen new SinglePressAction(com.android.internal.R.drawable.ic_lock_lock, R.string.global_action_lock) { mAirplaneModeOn = new ToggleAction( R.drawable.ic_lock_airplane_mode, R.drawable.ic_lock_airplane_mode_off, R.string.global_actions_toggle_airplane_mode, R.string.global_actions_airplane_mode_on_status, R.string.global_actions_airplane_mode_off_status) { public void onPress() { mPowerManager.goToSleep(SystemClock.uptimeMillis() + 1); void onToggle(boolean on) { // Change the system setting Settings.System.putInt( mContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, on ? 1 : 0); Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); intent.putExtra("state", on); mContext.sendBroadcast(intent); } @Override protected void changeStateFromPress(boolean buttonOn) { mState = buttonOn ? State.TurningOn : State.TurningOff; mAirplaneState = mState; } public boolean showDuringKeyguard() { return false; return true; } public boolean showBeforeProvisioning() { return false; } }, */ // next: silent mode }; mItems = Lists.newArrayList( // silent mode mSilentModeToggle, // next: airplane mode mAirplaneModeOn, // last: power off new SinglePressAction(com.android.internal.R.drawable.ic_lock_power_off, R.string.global_action_power_off) { new SinglePressAction( com.android.internal.R.drawable.ic_lock_power_off, R.string.global_action_power_off) { public void onPress() { // shutdown by making sure radio and power are handled accordingly. Loading Loading @@ -180,10 +207,11 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } private void prepareDialog() { // TODO: May need another 'Vibrate' toggle button, but for now treat them the same final boolean silentModeOn = mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL; mSilentModeToggle.updateState(silentModeOn); mSilentModeToggle.updateState( silentModeOn ? ToggleAction.State.On : ToggleAction.State.Off); mAirplaneModeOn.updateState(mAirplaneState); mAdapter.notifyDataSetChanged(); if (mKeyguardShowing) { mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); Loading @@ -192,6 +220,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } } /** {@inheritDoc} */ public void onDismiss(DialogInterface dialog) { mStatusBar.disable(StatusBarManager.DISABLE_NONE); Loading Loading @@ -229,6 +258,16 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac return count; } @Override public boolean isEnabled(int position) { return getItem(position).isEnabled(); } @Override public boolean areAllItemsEnabled() { return false; } public Action getItem(int position) { int filteredPos = 0; Loading Loading @@ -259,7 +298,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac public View getView(int position, View convertView, ViewGroup parent) { Action action = getItem(position); return action.create(mContext, (LinearLayout) convertView, LayoutInflater.from(mContext)); return action.create(mContext, convertView, parent, LayoutInflater.from(mContext)); } } Loading @@ -273,7 +312,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac * What each item in the global actions dialog must be able to support. */ private interface Action { LinearLayout create(Context context, LinearLayout convertView, LayoutInflater inflater); View create(Context context, View convertView, ViewGroup parent, LayoutInflater inflater); void onPress(); Loading @@ -288,6 +327,8 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac * device is provisioned. */ boolean showBeforeProvisioning(); boolean isEnabled(); } /** Loading @@ -303,12 +344,17 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac mMessageResId = messageResId; } public boolean isEnabled() { return true; } abstract public void onPress(); public LinearLayout create(Context context, LinearLayout convertView, LayoutInflater inflater) { LinearLayout v = (LinearLayout) ((convertView != null) ? public View create( Context context, View convertView, ViewGroup parent, LayoutInflater inflater) { View v = (convertView != null) ? convertView : inflater.inflate(R.layout.global_actions_item, null)); 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); Loading @@ -326,9 +372,26 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac * A toggle action knows whether it is on or off, and displays an icon * and status message accordingly. */ static abstract class ToggleAction implements Action { private static abstract class ToggleAction implements Action { enum State { Off(false), TurningOn(true), TurningOff(true), On(false); private boolean mOn = false; private final boolean inTransition; State(boolean intermediate) { inTransition = intermediate; } public boolean inTransition() { return inTransition; } } protected State mState = State.Off; // prefs private final int mEnabledIconResId; Loading Loading @@ -356,12 +419,12 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac mDisabledStatusMessageResId = disabledStatusMessageResId; } public LinearLayout create(Context context, LinearLayout convertView, public View create(Context context, View convertView, ViewGroup parent, LayoutInflater inflater) { LinearLayout v = (LinearLayout) ((convertView != null) ? View v = (convertView != null) ? convertView : inflater.inflate(R .layout.global_actions_item, null)); .layout.global_actions_item, parent, false); ImageView icon = (ImageView) v.findViewById(R.id.icon); TextView messageView = (TextView) v.findViewById(R.id.message); Loading @@ -369,23 +432,50 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac messageView.setText(mMessageResId); boolean on = ((mState == State.On) || (mState == State.TurningOn)); icon.setImageDrawable(context.getResources().getDrawable( (mOn ? mEnabledIconResId : mDisabledIconResid))); statusView.setText(mOn ? mEnabledStatusMessageResId : mDisabledStatusMessageResId); (on ? mEnabledIconResId : mDisabledIconResid))); statusView.setText(on ? mEnabledStatusMessageResId : mDisabledStatusMessageResId); statusView.setVisibility(View.VISIBLE); final boolean enabled = isEnabled(); messageView.setEnabled(enabled); statusView.setEnabled(enabled); icon.setEnabled(enabled); v.setEnabled(enabled); return v; } public void onPress() { updateState(!mOn); onToggle(mOn); public final void onPress() { if (mState.inTransition()) { Log.w(TAG, "shouldn't be able to toggle when in transition"); return; } final boolean nowOn = !(mState == State.On); onToggle(nowOn); changeStateFromPress(nowOn); } public boolean isEnabled() { return !mState.inTransition(); } /** * Implementations may override this if their state can be in on of the intermediate * states until some notification is received (e.g airplane mode is 'turning off' until * we know the wireless connections are back online * @param buttonOn Whether the button was turned on or off */ protected void changeStateFromPress(boolean buttonOn) { mState = buttonOn ? State.On : State.Off; } abstract void onToggle(boolean on); public void updateState(boolean on) { mOn = on; public void updateState(State state) { mState = state; } } Loading @@ -401,6 +491,16 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } }; PhoneStateListener mPhoneStateListener = new PhoneStateListener() { @Override public void onServiceStateChanged(ServiceState serviceState) { final boolean inAirplaneMode = serviceState.getState() == ServiceState.STATE_POWER_OFF; mAirplaneState = inAirplaneMode ? ToggleAction.State.On : ToggleAction.State.Off; mAirplaneModeOn.updateState(mAirplaneState); mAdapter.notifyDataSetChanged(); } }; private static final int MESSAGE_DISMISS = 0; private Handler mHandler = new Handler() { public void handleMessage(Message msg) { Loading policy/com/android/internal/policy/impl/KeyguardScreen.java +6 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,12 @@ package com.android.internal.policy.impl; */ public interface KeyguardScreen { /** * Return true if your view needs input, so should allow the soft * keyboard to be displayed. */ boolean needsInput(); /** * This screen is no longer in front of the user. */ Loading @@ -36,5 +42,4 @@ public interface KeyguardScreen { * This view is going away; a hook to do cleanup. */ void cleanUp(); } policy/com/android/internal/policy/impl/KeyguardUpdateMonitor.java +2 −2 Original line number Diff line number Diff line Loading @@ -375,12 +375,12 @@ public class KeyguardUpdateMonitor { } /** * Is the keyboard currently open? * Is the (hard) keyboard currently open? */ boolean queryKeyboardOpen() { final Configuration configuration = mContext.getResources().getConfiguration(); return configuration.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO; return configuration.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO; } /** Loading policy/com/android/internal/policy/impl/KeyguardViewBase.java +14 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.internal.policy.impl; import android.content.Context; import android.content.Intent; import android.media.AudioManager; import android.telephony.TelephonyManager; import android.view.KeyEvent; import android.view.View; import android.widget.FrameLayout; Loading @@ -36,6 +37,7 @@ public abstract class KeyguardViewBase extends FrameLayout { private KeyguardViewCallback mCallback; private AudioManager mAudioManager; private TelephonyManager mTelephonyManager = null; public KeyguardViewBase(Context context) { super(context); Loading Loading @@ -131,8 +133,18 @@ public abstract class KeyguardViewBase extends FrameLayout { final int keyCode = event.getKeyCode(); if (event.getAction() == KeyEvent.ACTION_DOWN) { switch (keyCode) { case KeyEvent.KEYCODE_HEADSETHOOK: case KeyEvent.KEYCODE_PLAYPAUSE: /* Suppress PLAYPAUSE toggle when phone is ringing or * in-call to avoid music playback */ if (mTelephonyManager == null) { mTelephonyManager = (TelephonyManager) getContext().getSystemService( Context.TELEPHONY_SERVICE); } if (mTelephonyManager != null && mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) { return true; // suppress key event } case KeyEvent.KEYCODE_HEADSETHOOK: case KeyEvent.KEYCODE_STOP: case KeyEvent.KEYCODE_NEXTSONG: case KeyEvent.KEYCODE_PREVIOUSSONG: Loading Loading @@ -167,6 +179,7 @@ public abstract class KeyguardViewBase extends FrameLayout { } } else if (event.getAction() == KeyEvent.ACTION_UP) { switch (keyCode) { case KeyEvent.KEYCODE_MUTE: case KeyEvent.KEYCODE_HEADSETHOOK: case KeyEvent.KEYCODE_PLAYPAUSE: case KeyEvent.KEYCODE_STOP: Loading Loading
policy/com/android/internal/policy/impl/AccountUnlockScreen.java +92 −4 Original line number Diff line number Diff line Loading @@ -28,8 +28,11 @@ import android.content.ServiceConnection; import android.graphics.Rect; import android.os.IBinder; import android.os.RemoteException; import android.text.Editable; import android.text.InputFilter; import android.text.LoginFilter; import android.text.TextWatcher; import android.text.TextUtils; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; Loading @@ -47,13 +50,16 @@ import android.widget.TextView; * IAccountsService. */ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScreen, View.OnClickListener, ServiceConnection { View.OnClickListener, ServiceConnection, TextWatcher { private static final String LOCK_PATTERN_PACKAGE = "com.android.settings"; private static final String LOCK_PATTERN_CLASS = "com.android.settings.ChooseLockPattern"; /** * The amount of millis to stay awake once this screen detects activity */ private static final int AWAKE_POKE_MILLIS = 30000; private final KeyguardScreenCallback mCallback; private final LockPatternUtils mLockPatternUtils; private IAccountsService mAccountsService; Loading Loading @@ -87,8 +93,10 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree mLogin = (EditText) findViewById(R.id.login); mLogin.setFilters(new InputFilter[] { new LoginFilter.UsernameFilterGeneric() } ); mLogin.addTextChangedListener(this); mPassword = (EditText) findViewById(R.id.password); mPassword.addTextChangedListener(this); mOk = (Button) findViewById(R.id.ok); mOk.setOnClickListener(this); Loading @@ -105,6 +113,16 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree } } public void afterTextChanged(Editable s) { } public void beforeTextChanged(CharSequence s, int start, int count, int after) { } public void onTextChanged(CharSequence s, int start, int before, int count) { mCallback.pokeWakelock(AWAKE_POKE_MILLIS); } @Override protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) { Loading @@ -112,6 +130,11 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree return mLogin.requestFocus(direction, previouslyFocusedRect); } /** {@inheritDoc} */ public boolean needsInput() { return true; } /** {@inheritDoc} */ public void onPause() { Loading @@ -132,6 +155,7 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree /** {@inheritDoc} */ public void onClick(View v) { mCallback.pokeWakelock(); if (v == mOk) { if (checkPassword()) { // clear out forgotten password Loading Loading @@ -167,11 +191,75 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree return super.dispatchKeyEvent(event); } /** * Given the string the user entered in the 'username' field, find * the stored account that they probably intended. Prefer, in order: * * - an exact match for what was typed, or * - a case-insensitive match for what was typed, or * - if they didn't include a domain, an exact match of the username, or * - if they didn't include a domain, a case-insensitive * match of the username. * * If there is a tie for the best match, choose neither -- * the user needs to be more specific. * * @return an account name from the database, or null if we can't * find a single best match. */ private String findIntendedAccount(String username) { String[] accounts = null; try { accounts = mAccountsService.getAccounts(); } catch (RemoteException e) { return null; } if (accounts == null) { return null; } // Try to figure out which account they meant if they // typed only the username (and not the domain), or got // the case wrong. String bestAccount = null; int bestScore = 0; for (String a: accounts) { int score = 0; if (username.equals(a)) { score = 4; } else if (username.equalsIgnoreCase(a)) { score = 3; } else if (username.indexOf('@') < 0) { int i = a.indexOf('@'); if (i >= 0) { String aUsername = a.substring(0, i); if (username.equals(aUsername)) { score = 2; } else if (username.equalsIgnoreCase(aUsername)) { score = 1; } } } if (score > bestScore) { bestAccount = a; bestScore = score; } else if (score == bestScore) { bestAccount = null; } } return bestAccount; } private boolean checkPassword() { final String login = mLogin.getText().toString(); final String password = mPassword.getText().toString(); try { return mAccountsService.shouldUnlock(login, password); String account = findIntendedAccount(login); if (account == null) { return false; } return mAccountsService.shouldUnlock(account, password); } catch (RemoteException e) { return false; } Loading
policy/com/android/internal/policy/impl/GlobalActions.java +150 −50 Original line number Diff line number Diff line Loading @@ -16,29 +16,30 @@ package com.android.internal.policy.impl; import com.android.internal.R; import com.google.android.collect.Lists; import android.app.AlertDialog; import android.app.StatusBarManager; import android.content.Context; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.DialogInterface; import android.media.AudioManager; import android.os.LocalPowerManager; import android.os.Handler; import android.os.Message; import android.os.SystemClock; import android.provider.Settings; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.android.internal.R; import com.google.android.collect.Lists; import java.util.ArrayList; Loading @@ -49,34 +50,41 @@ import java.util.ArrayList; */ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterface.OnClickListener { private static final String TAG = "GlobalActions"; private StatusBarManager mStatusBar; private final Context mContext; private final LocalPowerManager mPowerManager; private final AudioManager mAudioManager; private ArrayList<Action> mItems; private AlertDialog mDialog; private ToggleAction mSilentModeToggle; private ToggleAction mAirplaneModeOn; private MyAdapter mAdapter; private boolean mKeyguardShowing = false; private boolean mDeviceProvisioned = false; private ToggleAction.State mAirplaneState = ToggleAction.State.Off; /** * @param context everything needs a context :) * @param powerManager used to turn the screen off (the lock action). * @param context everything needs a context :( */ public GlobalActions(Context context, LocalPowerManager powerManager) { public GlobalActions(Context context) { mContext = context; mPowerManager = powerManager; mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); // receive broadcasts IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); context.registerReceiver(mBroadcastReceiver, filter); // get notified of phone state changes TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE); } /** Loading Loading @@ -123,29 +131,48 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } }; mItems = Lists.newArrayList( /* Disabled pending bug 1304831 -- key or touch events wake up device before it * can go to sleep. // first: lock screen new SinglePressAction(com.android.internal.R.drawable.ic_lock_lock, R.string.global_action_lock) { mAirplaneModeOn = new ToggleAction( R.drawable.ic_lock_airplane_mode, R.drawable.ic_lock_airplane_mode_off, R.string.global_actions_toggle_airplane_mode, R.string.global_actions_airplane_mode_on_status, R.string.global_actions_airplane_mode_off_status) { public void onPress() { mPowerManager.goToSleep(SystemClock.uptimeMillis() + 1); void onToggle(boolean on) { // Change the system setting Settings.System.putInt( mContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, on ? 1 : 0); Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); intent.putExtra("state", on); mContext.sendBroadcast(intent); } @Override protected void changeStateFromPress(boolean buttonOn) { mState = buttonOn ? State.TurningOn : State.TurningOff; mAirplaneState = mState; } public boolean showDuringKeyguard() { return false; return true; } public boolean showBeforeProvisioning() { return false; } }, */ // next: silent mode }; mItems = Lists.newArrayList( // silent mode mSilentModeToggle, // next: airplane mode mAirplaneModeOn, // last: power off new SinglePressAction(com.android.internal.R.drawable.ic_lock_power_off, R.string.global_action_power_off) { new SinglePressAction( com.android.internal.R.drawable.ic_lock_power_off, R.string.global_action_power_off) { public void onPress() { // shutdown by making sure radio and power are handled accordingly. Loading Loading @@ -180,10 +207,11 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } private void prepareDialog() { // TODO: May need another 'Vibrate' toggle button, but for now treat them the same final boolean silentModeOn = mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL; mSilentModeToggle.updateState(silentModeOn); mSilentModeToggle.updateState( silentModeOn ? ToggleAction.State.On : ToggleAction.State.Off); mAirplaneModeOn.updateState(mAirplaneState); mAdapter.notifyDataSetChanged(); if (mKeyguardShowing) { mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); Loading @@ -192,6 +220,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } } /** {@inheritDoc} */ public void onDismiss(DialogInterface dialog) { mStatusBar.disable(StatusBarManager.DISABLE_NONE); Loading Loading @@ -229,6 +258,16 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac return count; } @Override public boolean isEnabled(int position) { return getItem(position).isEnabled(); } @Override public boolean areAllItemsEnabled() { return false; } public Action getItem(int position) { int filteredPos = 0; Loading Loading @@ -259,7 +298,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac public View getView(int position, View convertView, ViewGroup parent) { Action action = getItem(position); return action.create(mContext, (LinearLayout) convertView, LayoutInflater.from(mContext)); return action.create(mContext, convertView, parent, LayoutInflater.from(mContext)); } } Loading @@ -273,7 +312,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac * What each item in the global actions dialog must be able to support. */ private interface Action { LinearLayout create(Context context, LinearLayout convertView, LayoutInflater inflater); View create(Context context, View convertView, ViewGroup parent, LayoutInflater inflater); void onPress(); Loading @@ -288,6 +327,8 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac * device is provisioned. */ boolean showBeforeProvisioning(); boolean isEnabled(); } /** Loading @@ -303,12 +344,17 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac mMessageResId = messageResId; } public boolean isEnabled() { return true; } abstract public void onPress(); public LinearLayout create(Context context, LinearLayout convertView, LayoutInflater inflater) { LinearLayout v = (LinearLayout) ((convertView != null) ? public View create( Context context, View convertView, ViewGroup parent, LayoutInflater inflater) { View v = (convertView != null) ? convertView : inflater.inflate(R.layout.global_actions_item, null)); 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); Loading @@ -326,9 +372,26 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac * A toggle action knows whether it is on or off, and displays an icon * and status message accordingly. */ static abstract class ToggleAction implements Action { private static abstract class ToggleAction implements Action { enum State { Off(false), TurningOn(true), TurningOff(true), On(false); private boolean mOn = false; private final boolean inTransition; State(boolean intermediate) { inTransition = intermediate; } public boolean inTransition() { return inTransition; } } protected State mState = State.Off; // prefs private final int mEnabledIconResId; Loading Loading @@ -356,12 +419,12 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac mDisabledStatusMessageResId = disabledStatusMessageResId; } public LinearLayout create(Context context, LinearLayout convertView, public View create(Context context, View convertView, ViewGroup parent, LayoutInflater inflater) { LinearLayout v = (LinearLayout) ((convertView != null) ? View v = (convertView != null) ? convertView : inflater.inflate(R .layout.global_actions_item, null)); .layout.global_actions_item, parent, false); ImageView icon = (ImageView) v.findViewById(R.id.icon); TextView messageView = (TextView) v.findViewById(R.id.message); Loading @@ -369,23 +432,50 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac messageView.setText(mMessageResId); boolean on = ((mState == State.On) || (mState == State.TurningOn)); icon.setImageDrawable(context.getResources().getDrawable( (mOn ? mEnabledIconResId : mDisabledIconResid))); statusView.setText(mOn ? mEnabledStatusMessageResId : mDisabledStatusMessageResId); (on ? mEnabledIconResId : mDisabledIconResid))); statusView.setText(on ? mEnabledStatusMessageResId : mDisabledStatusMessageResId); statusView.setVisibility(View.VISIBLE); final boolean enabled = isEnabled(); messageView.setEnabled(enabled); statusView.setEnabled(enabled); icon.setEnabled(enabled); v.setEnabled(enabled); return v; } public void onPress() { updateState(!mOn); onToggle(mOn); public final void onPress() { if (mState.inTransition()) { Log.w(TAG, "shouldn't be able to toggle when in transition"); return; } final boolean nowOn = !(mState == State.On); onToggle(nowOn); changeStateFromPress(nowOn); } public boolean isEnabled() { return !mState.inTransition(); } /** * Implementations may override this if their state can be in on of the intermediate * states until some notification is received (e.g airplane mode is 'turning off' until * we know the wireless connections are back online * @param buttonOn Whether the button was turned on or off */ protected void changeStateFromPress(boolean buttonOn) { mState = buttonOn ? State.On : State.Off; } abstract void onToggle(boolean on); public void updateState(boolean on) { mOn = on; public void updateState(State state) { mState = state; } } Loading @@ -401,6 +491,16 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } }; PhoneStateListener mPhoneStateListener = new PhoneStateListener() { @Override public void onServiceStateChanged(ServiceState serviceState) { final boolean inAirplaneMode = serviceState.getState() == ServiceState.STATE_POWER_OFF; mAirplaneState = inAirplaneMode ? ToggleAction.State.On : ToggleAction.State.Off; mAirplaneModeOn.updateState(mAirplaneState); mAdapter.notifyDataSetChanged(); } }; private static final int MESSAGE_DISMISS = 0; private Handler mHandler = new Handler() { public void handleMessage(Message msg) { Loading
policy/com/android/internal/policy/impl/KeyguardScreen.java +6 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,12 @@ package com.android.internal.policy.impl; */ public interface KeyguardScreen { /** * Return true if your view needs input, so should allow the soft * keyboard to be displayed. */ boolean needsInput(); /** * This screen is no longer in front of the user. */ Loading @@ -36,5 +42,4 @@ public interface KeyguardScreen { * This view is going away; a hook to do cleanup. */ void cleanUp(); }
policy/com/android/internal/policy/impl/KeyguardUpdateMonitor.java +2 −2 Original line number Diff line number Diff line Loading @@ -375,12 +375,12 @@ public class KeyguardUpdateMonitor { } /** * Is the keyboard currently open? * Is the (hard) keyboard currently open? */ boolean queryKeyboardOpen() { final Configuration configuration = mContext.getResources().getConfiguration(); return configuration.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO; return configuration.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO; } /** Loading
policy/com/android/internal/policy/impl/KeyguardViewBase.java +14 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.internal.policy.impl; import android.content.Context; import android.content.Intent; import android.media.AudioManager; import android.telephony.TelephonyManager; import android.view.KeyEvent; import android.view.View; import android.widget.FrameLayout; Loading @@ -36,6 +37,7 @@ public abstract class KeyguardViewBase extends FrameLayout { private KeyguardViewCallback mCallback; private AudioManager mAudioManager; private TelephonyManager mTelephonyManager = null; public KeyguardViewBase(Context context) { super(context); Loading Loading @@ -131,8 +133,18 @@ public abstract class KeyguardViewBase extends FrameLayout { final int keyCode = event.getKeyCode(); if (event.getAction() == KeyEvent.ACTION_DOWN) { switch (keyCode) { case KeyEvent.KEYCODE_HEADSETHOOK: case KeyEvent.KEYCODE_PLAYPAUSE: /* Suppress PLAYPAUSE toggle when phone is ringing or * in-call to avoid music playback */ if (mTelephonyManager == null) { mTelephonyManager = (TelephonyManager) getContext().getSystemService( Context.TELEPHONY_SERVICE); } if (mTelephonyManager != null && mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) { return true; // suppress key event } case KeyEvent.KEYCODE_HEADSETHOOK: case KeyEvent.KEYCODE_STOP: case KeyEvent.KEYCODE_NEXTSONG: case KeyEvent.KEYCODE_PREVIOUSSONG: Loading Loading @@ -167,6 +179,7 @@ public abstract class KeyguardViewBase extends FrameLayout { } } else if (event.getAction() == KeyEvent.ACTION_UP) { switch (keyCode) { case KeyEvent.KEYCODE_MUTE: case KeyEvent.KEYCODE_HEADSETHOOK: case KeyEvent.KEYCODE_PLAYPAUSE: case KeyEvent.KEYCODE_STOP: Loading