Loading policy/Android.mk 0 → 100644 +12 −0 Original line number Diff line number Diff line LOCAL_PATH:= $(call my-dir) # the library # ============================================================ include $(CLEAR_VARS) LOCAL_SRC_FILES := \ $(call all-subdir-java-files) LOCAL_MODULE:= android.policy include $(BUILD_JAVA_LIBRARY) policy/com/android/internal/policy/impl/AccountUnlockScreen.java 0 → 100644 +190 −0 Original line number Diff line number Diff line /* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.policy.impl; import com.android.internal.R; import com.android.internal.widget.LockPatternUtils; import android.accounts.AccountsServiceConstants; import android.accounts.IAccountsService; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.graphics.Rect; import android.os.IBinder; import android.os.RemoteException; import android.text.InputFilter; import android.text.LoginFilter; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.RelativeLayout; import android.widget.TextView; /** * When the user forgets their password a bunch of times, we fall back on their * account's login/password to unlock the phone (and reset their lock pattern). * * <p>This class is useful only on platforms that support the * IAccountsService. */ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScreen, View.OnClickListener, ServiceConnection { private static final String LOCK_PATTERN_PACKAGE = "com.android.settings"; private static final String LOCK_PATTERN_CLASS = "com.android.settings.ChooseLockPattern"; private final KeyguardScreenCallback mCallback; private final LockPatternUtils mLockPatternUtils; private IAccountsService mAccountsService; private TextView mTopHeader; private TextView mInstructions; private EditText mLogin; private EditText mPassword; private Button mOk; private Button mEmergencyCall; /** * AccountUnlockScreen constructor. * * @throws IllegalStateException if the IAccountsService is not * available on the current platform. */ public AccountUnlockScreen(Context context, KeyguardScreenCallback callback, LockPatternUtils lockPatternUtils) { super(context); mCallback = callback; mLockPatternUtils = lockPatternUtils; LayoutInflater.from(context).inflate( R.layout.keyguard_screen_glogin_unlock, this, true); mTopHeader = (TextView) findViewById(R.id.topHeader); mInstructions = (TextView) findViewById(R.id.instructions); mLogin = (EditText) findViewById(R.id.login); mLogin.setFilters(new InputFilter[] { new LoginFilter.UsernameFilterGeneric() } ); mPassword = (EditText) findViewById(R.id.password); mOk = (Button) findViewById(R.id.ok); mOk.setOnClickListener(this); mEmergencyCall = (Button) findViewById(R.id.emergencyCall); mEmergencyCall.setOnClickListener(this); Log.v("AccountUnlockScreen", "debug: Connecting to accounts service"); final boolean connected = mContext.bindService(AccountsServiceConstants.SERVICE_INTENT, this, Context.BIND_AUTO_CREATE); if (!connected) { Log.v("AccountUnlockScreen", "debug: Couldn't connect to accounts service"); throw new IllegalStateException("couldn't bind to accounts service"); } } @Override protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) { // send focus to the login field return mLogin.requestFocus(direction, previouslyFocusedRect); } /** {@inheritDoc} */ public void onPause() { } /** {@inheritDoc} */ public void onResume() { // start fresh mLogin.setText(""); mPassword.setText(""); mLogin.requestFocus(); } /** {@inheritDoc} */ public void cleanUp() { mContext.unbindService(this); } /** {@inheritDoc} */ public void onClick(View v) { if (v == mOk) { if (checkPassword()) { // clear out forgotten password mLockPatternUtils.setPermanentlyLocked(false); // launch the 'choose lock pattern' activity so // the user can pick a new one if they want to Intent intent = new Intent(); intent.setClassName(LOCK_PATTERN_PACKAGE, LOCK_PATTERN_CLASS); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(intent); // close the keyguard mCallback.keyguardDone(true); } else { mInstructions.setText(R.string.lockscreen_glogin_invalid_input); mPassword.setText(""); } } if (v == mEmergencyCall) { mCallback.takeEmergencyCallAction(); } } @Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_BACK) { mCallback.goToLockScreen(); return true; } return super.dispatchKeyEvent(event); } private boolean checkPassword() { final String login = mLogin.getText().toString(); final String password = mPassword.getText().toString(); try { return mAccountsService.shouldUnlock(login, password); } catch (RemoteException e) { return false; } } /** {@inheritDoc} */ public void onServiceConnected(ComponentName name, IBinder service) { Log.v("AccountUnlockScreen", "debug: About to grab as interface"); mAccountsService = IAccountsService.Stub.asInterface(service); } /** {@inheritDoc} */ public void onServiceDisconnected(ComponentName name) { mAccountsService = null; } } policy/com/android/internal/policy/impl/GlobalActions.java 0 → 100644 +414 −0 Original line number Diff line number Diff line /* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 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.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.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 java.util.ArrayList; /** * Helper to show the global actions dialog. Each item is an {@link Action} that * may show depending on whether the keyguard is showing, and whether the device * is provisioned. */ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterface.OnClickListener { 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 MyAdapter mAdapter; private boolean mKeyguardShowing = false; private boolean mDeviceProvisioned = false; /** * @param context everything needs a context :) * @param powerManager used to turn the screen off (the lock action). */ public GlobalActions(Context context, LocalPowerManager powerManager) { 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); } /** * Show the global actions dialog (creating if necessary) * @param keyguardShowing True if keyguard is showing */ public void showDialog(boolean keyguardShowing, boolean isDeviceProvisioned) { mKeyguardShowing = keyguardShowing; mDeviceProvisioned = isDeviceProvisioned; if (mDialog == null) { mStatusBar = (StatusBarManager)mContext.getSystemService(Context.STATUS_BAR_SERVICE); mDialog = createDialog(); } prepareDialog(); mStatusBar.disable(StatusBarManager.DISABLE_EXPAND); mDialog.show(); } /** * Create the global actions dialog. * @return A new dialog. */ private AlertDialog createDialog() { mSilentModeToggle = new ToggleAction( R.drawable.ic_lock_silent_mode, R.drawable.ic_lock_silent_mode_off, R.string.global_action_toggle_silent_mode, R.string.global_action_silent_mode_on_status, R.string.global_action_silent_mode_off_status) { void onToggle(boolean on) { mAudioManager.setRingerMode(on ? AudioManager.RINGER_MODE_SILENT : AudioManager.RINGER_MODE_NORMAL); } public boolean showDuringKeyguard() { return true; } public boolean showBeforeProvisioning() { return false; } }; 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) { public void onPress() { mPowerManager.goToSleep(SystemClock.uptimeMillis() + 1); } public boolean showDuringKeyguard() { return false; } public boolean showBeforeProvisioning() { return false; } }, */ // next: silent mode mSilentModeToggle, // last: 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. ShutdownThread.shutdownAfterDisablingRadio(mContext, true); } public boolean showDuringKeyguard() { return true; } 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); final AlertDialog dialog = ab.create(); dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND, WindowManager.LayoutParams.FLAG_BLUR_BEHIND); dialog.setOnDismissListener(this); return dialog; } 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); mAdapter.notifyDataSetChanged(); if (mKeyguardShowing) { mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); } else { mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); } } /** {@inheritDoc} */ public void onDismiss(DialogInterface dialog) { mStatusBar.disable(StatusBarManager.DISABLE_NONE); } /** {@inheritDoc} */ public void onClick(DialogInterface dialog, int which) { 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 * {@link GlobalActions#mKeyguardShowing} and whether the device is provisioned * via {@link GlobalActions#mDeviceProvisioned}. */ private class MyAdapter extends BaseAdapter { public int getCount() { int count = 0; for (int i = 0; i < mItems.size(); i++) { final Action action = mItems.get(i); if (mKeyguardShowing && !action.showDuringKeyguard()) { continue; } if (!mDeviceProvisioned && !action.showBeforeProvisioning()) { continue; } count++; } return count; } public Action getItem(int position) { int filteredPos = 0; for (int i = 0; i < mItems.size(); i++) { final Action action = mItems.get(i); if (mKeyguardShowing && !action.showDuringKeyguard()) { continue; } if (!mDeviceProvisioned && !action.showBeforeProvisioning()) { continue; } if (filteredPos == position) { return action; } filteredPos++; } throw new IllegalArgumentException("position " + position + " out of " + "range of showable actions, filtered count = " + "= " + getCount() + ", keyguardshowing=" + mKeyguardShowing + ", provisioned=" + mDeviceProvisioned); } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { Action action = getItem(position); return action.create(mContext, (LinearLayout) convertView, LayoutInflater.from(mContext)); } } // note: the scheme below made more sense when we were planning on having // 8 different things in the global actions dialog. seems overkill with // only 3 items now, but may as well keep this flexible approach so it will // be easy should someone decide at the last minute to include something // else, such as 'enable wifi', or 'enable bluetooth' /** * What each item in the global actions dialog must be able to support. */ private interface Action { LinearLayout create(Context context, LinearLayout convertView, LayoutInflater inflater); void onPress(); /** * @return whether this action should appear in the dialog when the keygaurd * is showing. */ boolean showDuringKeyguard(); /** * @return whether this action should appear in the dialog before the * device is provisioned. */ boolean showBeforeProvisioning(); } /** * A single press action maintains no state, just responds to a press * and takes an action. */ private static abstract class SinglePressAction implements Action { private final int mIconResId; private final int mMessageResId; protected SinglePressAction(int iconResId, int messageResId) { mIconResId = iconResId; mMessageResId = messageResId; } abstract public void onPress(); public LinearLayout create(Context context, LinearLayout convertView, LayoutInflater inflater) { LinearLayout v = (LinearLayout) ((convertView != null) ? convertView : inflater.inflate(R.layout.global_actions_item, null)); ImageView icon = (ImageView) v.findViewById(R.id.icon); TextView messageView = (TextView) v.findViewById(R.id.message); v.findViewById(R.id.status).setVisibility(View.GONE); icon.setImageDrawable(context.getResources().getDrawable(mIconResId)); messageView.setText(mMessageResId); return v; } } /** * 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 boolean mOn = false; // prefs private final int mEnabledIconResId; private final int mDisabledIconResid; private final int mMessageResId; private final int mEnabledStatusMessageResId; private final int mDisabledStatusMessageResId; /** * @param enabledIconResId The icon for when this action is on. * @param disabledIconResid The icon for when this action is off. * @param essage The general information message, e.g 'Silent Mode' * @param enabledStatusMessageResId The on status message, e.g 'sound disabled' * @param disabledStatusMessageResId The off status message, e.g. 'sound enabled' */ public ToggleAction(int enabledIconResId, int disabledIconResid, int essage, int enabledStatusMessageResId, int disabledStatusMessageResId) { mEnabledIconResId = enabledIconResId; mDisabledIconResid = disabledIconResid; mMessageResId = essage; mEnabledStatusMessageResId = enabledStatusMessageResId; mDisabledStatusMessageResId = disabledStatusMessageResId; } public LinearLayout create(Context context, LinearLayout convertView, LayoutInflater inflater) { LinearLayout v = (LinearLayout) ((convertView != null) ? convertView : inflater.inflate(R .layout.global_actions_item, null)); ImageView icon = (ImageView) v.findViewById(R.id.icon); TextView messageView = (TextView) v.findViewById(R.id.message); TextView statusView = (TextView) v.findViewById(R.id.status); messageView.setText(mMessageResId); icon.setImageDrawable(context.getResources().getDrawable( (mOn ? mEnabledIconResId : mDisabledIconResid))); statusView.setText(mOn ? mEnabledStatusMessageResId : mDisabledStatusMessageResId); statusView.setVisibility(View.VISIBLE); return v; } public void onPress() { updateState(!mOn); onToggle(mOn); } abstract void onToggle(boolean on); public void updateState(boolean on) { mOn = on; } } private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) { String reason = intent.getStringExtra(PhoneWindowManager.SYSTEM_DIALOG_REASON_KEY); if (! PhoneWindowManager.SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS.equals(reason)) { mHandler.sendEmptyMessage(MESSAGE_DISMISS); } } } }; private static final int MESSAGE_DISMISS = 0; private Handler mHandler = new Handler() { public void handleMessage(Message msg) { if (msg.what == MESSAGE_DISMISS) { if (mDialog != null) { mDialog.dismiss(); } } } }; } policy/com/android/internal/policy/impl/KeyguardScreen.java 0 → 100644 +40 −0 Original line number Diff line number Diff line /* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.policy.impl; /** * Common interface of each {@link android.view.View} that is a screen of * {@link LockPatternKeyguardView}. */ public interface KeyguardScreen { /** * This screen is no longer in front of the user. */ void onPause(); /** * This screen is going to be in front of the user. */ void onResume(); /** * This view is going away; a hook to do cleanup. */ void cleanUp(); } policy/com/android/internal/policy/impl/KeyguardScreenCallback.java 0 → 100644 +61 −0 Original line number Diff line number Diff line /* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.policy.impl; /** * Within a keyguard, there may be several screens that need a callback * to the host keyguard view. */ public interface KeyguardScreenCallback extends KeyguardViewCallback { /** * Transition to the lock screen. */ void goToLockScreen(); /** * Transitino to th unlock screen. */ void goToUnlockScreen(); /** * @return Whether the keyguard requires some sort of PIN. */ boolean isSecure(); /** * @return Whether we are in a mode where we only want to verify the * user can get past the keyguard. */ boolean isVerifyUnlockOnly(); /** * Stay on me, but recreate me (so I can use a different layout). */ void recreateMe(); /** * Take action to send an emergency call. */ void takeEmergencyCallAction(); /** * Report that the user had a failed attempt unlocking via the pattern. */ void reportFailedPatternAttempt(); } Loading
policy/Android.mk 0 → 100644 +12 −0 Original line number Diff line number Diff line LOCAL_PATH:= $(call my-dir) # the library # ============================================================ include $(CLEAR_VARS) LOCAL_SRC_FILES := \ $(call all-subdir-java-files) LOCAL_MODULE:= android.policy include $(BUILD_JAVA_LIBRARY)
policy/com/android/internal/policy/impl/AccountUnlockScreen.java 0 → 100644 +190 −0 Original line number Diff line number Diff line /* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.policy.impl; import com.android.internal.R; import com.android.internal.widget.LockPatternUtils; import android.accounts.AccountsServiceConstants; import android.accounts.IAccountsService; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.graphics.Rect; import android.os.IBinder; import android.os.RemoteException; import android.text.InputFilter; import android.text.LoginFilter; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.RelativeLayout; import android.widget.TextView; /** * When the user forgets their password a bunch of times, we fall back on their * account's login/password to unlock the phone (and reset their lock pattern). * * <p>This class is useful only on platforms that support the * IAccountsService. */ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScreen, View.OnClickListener, ServiceConnection { private static final String LOCK_PATTERN_PACKAGE = "com.android.settings"; private static final String LOCK_PATTERN_CLASS = "com.android.settings.ChooseLockPattern"; private final KeyguardScreenCallback mCallback; private final LockPatternUtils mLockPatternUtils; private IAccountsService mAccountsService; private TextView mTopHeader; private TextView mInstructions; private EditText mLogin; private EditText mPassword; private Button mOk; private Button mEmergencyCall; /** * AccountUnlockScreen constructor. * * @throws IllegalStateException if the IAccountsService is not * available on the current platform. */ public AccountUnlockScreen(Context context, KeyguardScreenCallback callback, LockPatternUtils lockPatternUtils) { super(context); mCallback = callback; mLockPatternUtils = lockPatternUtils; LayoutInflater.from(context).inflate( R.layout.keyguard_screen_glogin_unlock, this, true); mTopHeader = (TextView) findViewById(R.id.topHeader); mInstructions = (TextView) findViewById(R.id.instructions); mLogin = (EditText) findViewById(R.id.login); mLogin.setFilters(new InputFilter[] { new LoginFilter.UsernameFilterGeneric() } ); mPassword = (EditText) findViewById(R.id.password); mOk = (Button) findViewById(R.id.ok); mOk.setOnClickListener(this); mEmergencyCall = (Button) findViewById(R.id.emergencyCall); mEmergencyCall.setOnClickListener(this); Log.v("AccountUnlockScreen", "debug: Connecting to accounts service"); final boolean connected = mContext.bindService(AccountsServiceConstants.SERVICE_INTENT, this, Context.BIND_AUTO_CREATE); if (!connected) { Log.v("AccountUnlockScreen", "debug: Couldn't connect to accounts service"); throw new IllegalStateException("couldn't bind to accounts service"); } } @Override protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) { // send focus to the login field return mLogin.requestFocus(direction, previouslyFocusedRect); } /** {@inheritDoc} */ public void onPause() { } /** {@inheritDoc} */ public void onResume() { // start fresh mLogin.setText(""); mPassword.setText(""); mLogin.requestFocus(); } /** {@inheritDoc} */ public void cleanUp() { mContext.unbindService(this); } /** {@inheritDoc} */ public void onClick(View v) { if (v == mOk) { if (checkPassword()) { // clear out forgotten password mLockPatternUtils.setPermanentlyLocked(false); // launch the 'choose lock pattern' activity so // the user can pick a new one if they want to Intent intent = new Intent(); intent.setClassName(LOCK_PATTERN_PACKAGE, LOCK_PATTERN_CLASS); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(intent); // close the keyguard mCallback.keyguardDone(true); } else { mInstructions.setText(R.string.lockscreen_glogin_invalid_input); mPassword.setText(""); } } if (v == mEmergencyCall) { mCallback.takeEmergencyCallAction(); } } @Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_BACK) { mCallback.goToLockScreen(); return true; } return super.dispatchKeyEvent(event); } private boolean checkPassword() { final String login = mLogin.getText().toString(); final String password = mPassword.getText().toString(); try { return mAccountsService.shouldUnlock(login, password); } catch (RemoteException e) { return false; } } /** {@inheritDoc} */ public void onServiceConnected(ComponentName name, IBinder service) { Log.v("AccountUnlockScreen", "debug: About to grab as interface"); mAccountsService = IAccountsService.Stub.asInterface(service); } /** {@inheritDoc} */ public void onServiceDisconnected(ComponentName name) { mAccountsService = null; } }
policy/com/android/internal/policy/impl/GlobalActions.java 0 → 100644 +414 −0 Original line number Diff line number Diff line /* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 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.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.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 java.util.ArrayList; /** * Helper to show the global actions dialog. Each item is an {@link Action} that * may show depending on whether the keyguard is showing, and whether the device * is provisioned. */ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterface.OnClickListener { 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 MyAdapter mAdapter; private boolean mKeyguardShowing = false; private boolean mDeviceProvisioned = false; /** * @param context everything needs a context :) * @param powerManager used to turn the screen off (the lock action). */ public GlobalActions(Context context, LocalPowerManager powerManager) { 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); } /** * Show the global actions dialog (creating if necessary) * @param keyguardShowing True if keyguard is showing */ public void showDialog(boolean keyguardShowing, boolean isDeviceProvisioned) { mKeyguardShowing = keyguardShowing; mDeviceProvisioned = isDeviceProvisioned; if (mDialog == null) { mStatusBar = (StatusBarManager)mContext.getSystemService(Context.STATUS_BAR_SERVICE); mDialog = createDialog(); } prepareDialog(); mStatusBar.disable(StatusBarManager.DISABLE_EXPAND); mDialog.show(); } /** * Create the global actions dialog. * @return A new dialog. */ private AlertDialog createDialog() { mSilentModeToggle = new ToggleAction( R.drawable.ic_lock_silent_mode, R.drawable.ic_lock_silent_mode_off, R.string.global_action_toggle_silent_mode, R.string.global_action_silent_mode_on_status, R.string.global_action_silent_mode_off_status) { void onToggle(boolean on) { mAudioManager.setRingerMode(on ? AudioManager.RINGER_MODE_SILENT : AudioManager.RINGER_MODE_NORMAL); } public boolean showDuringKeyguard() { return true; } public boolean showBeforeProvisioning() { return false; } }; 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) { public void onPress() { mPowerManager.goToSleep(SystemClock.uptimeMillis() + 1); } public boolean showDuringKeyguard() { return false; } public boolean showBeforeProvisioning() { return false; } }, */ // next: silent mode mSilentModeToggle, // last: 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. ShutdownThread.shutdownAfterDisablingRadio(mContext, true); } public boolean showDuringKeyguard() { return true; } 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); final AlertDialog dialog = ab.create(); dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND, WindowManager.LayoutParams.FLAG_BLUR_BEHIND); dialog.setOnDismissListener(this); return dialog; } 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); mAdapter.notifyDataSetChanged(); if (mKeyguardShowing) { mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); } else { mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); } } /** {@inheritDoc} */ public void onDismiss(DialogInterface dialog) { mStatusBar.disable(StatusBarManager.DISABLE_NONE); } /** {@inheritDoc} */ public void onClick(DialogInterface dialog, int which) { 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 * {@link GlobalActions#mKeyguardShowing} and whether the device is provisioned * via {@link GlobalActions#mDeviceProvisioned}. */ private class MyAdapter extends BaseAdapter { public int getCount() { int count = 0; for (int i = 0; i < mItems.size(); i++) { final Action action = mItems.get(i); if (mKeyguardShowing && !action.showDuringKeyguard()) { continue; } if (!mDeviceProvisioned && !action.showBeforeProvisioning()) { continue; } count++; } return count; } public Action getItem(int position) { int filteredPos = 0; for (int i = 0; i < mItems.size(); i++) { final Action action = mItems.get(i); if (mKeyguardShowing && !action.showDuringKeyguard()) { continue; } if (!mDeviceProvisioned && !action.showBeforeProvisioning()) { continue; } if (filteredPos == position) { return action; } filteredPos++; } throw new IllegalArgumentException("position " + position + " out of " + "range of showable actions, filtered count = " + "= " + getCount() + ", keyguardshowing=" + mKeyguardShowing + ", provisioned=" + mDeviceProvisioned); } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { Action action = getItem(position); return action.create(mContext, (LinearLayout) convertView, LayoutInflater.from(mContext)); } } // note: the scheme below made more sense when we were planning on having // 8 different things in the global actions dialog. seems overkill with // only 3 items now, but may as well keep this flexible approach so it will // be easy should someone decide at the last minute to include something // else, such as 'enable wifi', or 'enable bluetooth' /** * What each item in the global actions dialog must be able to support. */ private interface Action { LinearLayout create(Context context, LinearLayout convertView, LayoutInflater inflater); void onPress(); /** * @return whether this action should appear in the dialog when the keygaurd * is showing. */ boolean showDuringKeyguard(); /** * @return whether this action should appear in the dialog before the * device is provisioned. */ boolean showBeforeProvisioning(); } /** * A single press action maintains no state, just responds to a press * and takes an action. */ private static abstract class SinglePressAction implements Action { private final int mIconResId; private final int mMessageResId; protected SinglePressAction(int iconResId, int messageResId) { mIconResId = iconResId; mMessageResId = messageResId; } abstract public void onPress(); public LinearLayout create(Context context, LinearLayout convertView, LayoutInflater inflater) { LinearLayout v = (LinearLayout) ((convertView != null) ? convertView : inflater.inflate(R.layout.global_actions_item, null)); ImageView icon = (ImageView) v.findViewById(R.id.icon); TextView messageView = (TextView) v.findViewById(R.id.message); v.findViewById(R.id.status).setVisibility(View.GONE); icon.setImageDrawable(context.getResources().getDrawable(mIconResId)); messageView.setText(mMessageResId); return v; } } /** * 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 boolean mOn = false; // prefs private final int mEnabledIconResId; private final int mDisabledIconResid; private final int mMessageResId; private final int mEnabledStatusMessageResId; private final int mDisabledStatusMessageResId; /** * @param enabledIconResId The icon for when this action is on. * @param disabledIconResid The icon for when this action is off. * @param essage The general information message, e.g 'Silent Mode' * @param enabledStatusMessageResId The on status message, e.g 'sound disabled' * @param disabledStatusMessageResId The off status message, e.g. 'sound enabled' */ public ToggleAction(int enabledIconResId, int disabledIconResid, int essage, int enabledStatusMessageResId, int disabledStatusMessageResId) { mEnabledIconResId = enabledIconResId; mDisabledIconResid = disabledIconResid; mMessageResId = essage; mEnabledStatusMessageResId = enabledStatusMessageResId; mDisabledStatusMessageResId = disabledStatusMessageResId; } public LinearLayout create(Context context, LinearLayout convertView, LayoutInflater inflater) { LinearLayout v = (LinearLayout) ((convertView != null) ? convertView : inflater.inflate(R .layout.global_actions_item, null)); ImageView icon = (ImageView) v.findViewById(R.id.icon); TextView messageView = (TextView) v.findViewById(R.id.message); TextView statusView = (TextView) v.findViewById(R.id.status); messageView.setText(mMessageResId); icon.setImageDrawable(context.getResources().getDrawable( (mOn ? mEnabledIconResId : mDisabledIconResid))); statusView.setText(mOn ? mEnabledStatusMessageResId : mDisabledStatusMessageResId); statusView.setVisibility(View.VISIBLE); return v; } public void onPress() { updateState(!mOn); onToggle(mOn); } abstract void onToggle(boolean on); public void updateState(boolean on) { mOn = on; } } private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) { String reason = intent.getStringExtra(PhoneWindowManager.SYSTEM_DIALOG_REASON_KEY); if (! PhoneWindowManager.SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS.equals(reason)) { mHandler.sendEmptyMessage(MESSAGE_DISMISS); } } } }; private static final int MESSAGE_DISMISS = 0; private Handler mHandler = new Handler() { public void handleMessage(Message msg) { if (msg.what == MESSAGE_DISMISS) { if (mDialog != null) { mDialog.dismiss(); } } } }; }
policy/com/android/internal/policy/impl/KeyguardScreen.java 0 → 100644 +40 −0 Original line number Diff line number Diff line /* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.policy.impl; /** * Common interface of each {@link android.view.View} that is a screen of * {@link LockPatternKeyguardView}. */ public interface KeyguardScreen { /** * This screen is no longer in front of the user. */ void onPause(); /** * This screen is going to be in front of the user. */ void onResume(); /** * This view is going away; a hook to do cleanup. */ void cleanUp(); }
policy/com/android/internal/policy/impl/KeyguardScreenCallback.java 0 → 100644 +61 −0 Original line number Diff line number Diff line /* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.policy.impl; /** * Within a keyguard, there may be several screens that need a callback * to the host keyguard view. */ public interface KeyguardScreenCallback extends KeyguardViewCallback { /** * Transition to the lock screen. */ void goToLockScreen(); /** * Transitino to th unlock screen. */ void goToUnlockScreen(); /** * @return Whether the keyguard requires some sort of PIN. */ boolean isSecure(); /** * @return Whether we are in a mode where we only want to verify the * user can get past the keyguard. */ boolean isVerifyUnlockOnly(); /** * Stay on me, but recreate me (so I can use a different layout). */ void recreateMe(); /** * Take action to send an emergency call. */ void takeEmergencyCallAction(); /** * Report that the user had a failed attempt unlocking via the pattern. */ void reportFailedPatternAttempt(); }