field public static final java.lang.String SET_TIME = "android.permission.SET_TIME";
field public static final java.lang.String SET_VOLUME_KEY_LONG_PRESS_LISTENER = "android.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER";
field public static final java.lang.String SET_WALLPAPER_COMPONENT = "android.permission.SET_WALLPAPER_COMPONENT";
+ field public static final java.lang.String SHOW_KEYGUARD_MESSAGE = "android.permission.SHOW_KEYGUARD_MESSAGE";
field public static final java.lang.String SHUTDOWN = "android.permission.SHUTDOWN";
field public static final java.lang.String SIGNAL_PERSISTENT_PROCESSES = "android.permission.SIGNAL_PERSISTENT_PROCESSES";
field public static final java.lang.String STATUS_BAR = "android.permission.STATUS_BAR";
public class KeyguardManager {
method public android.content.Intent createConfirmFactoryResetCredentialIntent(java.lang.CharSequence, java.lang.CharSequence, java.lang.CharSequence);
+ method public void requestDismissKeyguard(android.app.Activity, java.lang.CharSequence, android.app.KeyguardManager.KeyguardDismissCallback);
}
public class Notification implements android.os.Parcelable {
boolean updateDisplayOverrideConfiguration(in Configuration values, int displayId);
void moveStackToDisplay(int stackId, int displayId);
boolean requestAutofillData(in IAssistDataReceiver receiver, in Bundle receiverExtras,
- in IBinder activityToken, int flags);
- void dismissKeyguard(in IBinder token, in IKeyguardDismissCallback callback);
+ in IBinder activityToken, int flags);
+ void dismissKeyguard(in IBinder token, in IKeyguardDismissCallback callback,
+ in CharSequence message);
int restartUserInBackground(int userId);
/** Cancels the window transitions for the given task. */
*/
public void requestDismissKeyguard(@NonNull Activity activity,
@Nullable KeyguardDismissCallback callback) {
+ requestDismissKeyguard(activity, null /* message */, callback);
+ }
+
+ /**
+ * If the device is currently locked (see {@link #isKeyguardLocked()}, requests the Keyguard to
+ * be dismissed.
+ * <p>
+ * If the Keyguard is not secure or the device is currently in a trusted state, calling this
+ * method will immediately dismiss the Keyguard without any user interaction.
+ * <p>
+ * If the Keyguard is secure and the device is not in a trusted state, this will bring up the
+ * UI so the user can enter their credentials.
+ * <p>
+ * If the value set for the {@link Activity} attr {@link android.R.attr#turnScreenOn} is true,
+ * the screen will turn on when the keyguard is dismissed.
+ *
+ * @param activity The activity requesting the dismissal. The activity must be either visible
+ * by using {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} or must be in a state in
+ * which it would be visible if Keyguard would not be hiding it. If that's not
+ * the case, the request will fail immediately and
+ * {@link KeyguardDismissCallback#onDismissError} will be invoked.
+ * @param message A message that will be shown in the keyguard explaining why the user
+ * would want to dismiss it.
+ * @param callback The callback to be called if the request to dismiss Keyguard was successful
+ * or {@code null} if the caller isn't interested in knowing the result. The
+ * callback will not be invoked if the activity was destroyed before the
+ * callback was received.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.SHOW_KEYGUARD_MESSAGE)
+ @SystemApi
+ public void requestDismissKeyguard(@NonNull Activity activity, @Nullable CharSequence message,
+ @Nullable KeyguardDismissCallback callback) {
try {
mAm.dismissKeyguard(activity.getActivityToken(), new IKeyguardDismissCallback.Stub() {
@Override
activity.mHandler.post(callback::onDismissCancelled);
}
}
- });
+ }, message);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
void exitKeyguardSecurely(IOnKeyguardExitResult callback);
boolean isKeyguardLocked();
boolean isKeyguardSecure();
- void dismissKeyguard(IKeyguardDismissCallback callback);
+ void dismissKeyguard(IKeyguardDismissCallback callback, CharSequence message);
// Requires INTERACT_ACROSS_USERS_FULL permission
void setSwitchingUser(boolean switching);
void addStateMonitorCallback(IKeyguardStateCallback callback);
void verifyUnlock(IKeyguardExitCallback callback);
- void dismiss(IKeyguardDismissCallback callback);
+ void dismiss(IKeyguardDismissCallback callback, CharSequence message);
void onDreamingStarted();
void onDreamingStopped();
<permission android:name="android.permission.PROVIDE_TRUST_AGENT"
android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi Allows an application to show a message
+ on the keyguard when asking to dismiss it.
+ @hide For security reasons, this is a platform-only permission. -->
+ <permission android:name="android.permission.SHOW_KEYGUARD_MESSAGE"
+ android:protectionLevel="signature|privileged" />
+
<!-- Allows an application to launch the trust agent settings activity.
@hide -->
<permission android:name="android.permission.LAUNCH_TRUST_AGENT_SETTINGS"
final IWindowManager wm = IWindowManager.Stub
.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
try {
- wm.dismissKeyguard(null);
+ wm.dismissKeyguard(null, null);
} catch (Exception e) {
// ignore it
}
@Override
public void showPromptReason(int reason) {
if (reason != PROMPT_REASON_NONE) {
- int promtReasonStringRes = getPromtReasonStringRes(reason);
+ int promtReasonStringRes = getPromptReasonStringRes(reason);
if (promtReasonStringRes != 0) {
mSecurityMessageDisplay.setMessage(promtReasonStringRes);
}
}
@Override
- public void showMessage(String message, int color) {
+ public void showMessage(CharSequence message, int color) {
mSecurityMessageDisplay.setNextMessageColor(color);
mSecurityMessageDisplay.setMessage(message);
}
- protected abstract int getPromtReasonStringRes(int reason);
+ protected abstract int getPromptReasonStringRes(int reason);
// Cause a VIRTUAL_KEY vibration
public void doHapticKeyClick() {
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.settingslib.Utils;
import java.io.File;
mSecurityContainer.showPromptReason(reason);
}
- public void showMessage(String message, int color) {
+ public void showMessage(CharSequence message, int color) {
mSecurityContainer.showMessage(message, color);
}
+ public void showErrorMessage(CharSequence message) {
+ showMessage(message, Utils.getColorError(mContext));
+ }
+
/**
* Dismisses the keyguard by going to the next screen or making it gone.
* @param targetUserId a user that needs to be the foreground user at the dismissal completion.
}
@Override
- protected int getPromtReasonStringRes(int reason) {
+ protected int getPromptReasonStringRes(int reason) {
switch (reason) {
case PROMPT_REASON_RESTART:
return R.string.kg_prompt_reason_restart_password;
}
@Override
- public void showMessage(String message, int color) {
+ public void showMessage(CharSequence message, int color) {
mSecurityMessageDisplay.setNextMessageColor(color);
mSecurityMessageDisplay.setMessage(message);
}
}
@Override
- protected int getPromtReasonStringRes(int reason) {
+ protected int getPromptReasonStringRes(int reason) {
switch (reason) {
case PROMPT_REASON_RESTART:
return R.string.kg_prompt_reason_restart_pin;
}
}
-
- public void showMessage(String message, int color) {
+ public void showMessage(CharSequence message, int color) {
if (mCurrentSecuritySelection != SecurityMode.None) {
getSecurityView(mCurrentSecuritySelection).showMessage(message, color);
}
* @param message the message to show
* @param color the color to use
*/
- void showMessage(String message, int color);
+ void showMessage(CharSequence message, int color);
/**
* Instruct the view to show usability hints, if any.
}
@Override
- public void showMessage(String message, int color) {
+ public void showMessage(CharSequence message, int color) {
KeyguardSecurityView ksv = getSecurityView();
if (ksv != null) {
ksv.showMessage(message, color);
}
@Override
- protected int getPromtReasonStringRes(int reason) {
+ protected int getPromptReasonStringRes(int reason) {
// No message on SIM Pin
return 0;
}
}
@Override
- protected int getPromtReasonStringRes(int reason) {
+ protected int getPromptReasonStringRes(int reason) {
// No message on SIM Puk
return 0;
}
* Invoked when the secondary display showing a keyguard window changes.
*/
void onSecondaryDisplayShowingChanged(int displayId);
+
+ /**
+ * Consumes a message that was enqueued to be displayed on the next time the bouncer shows up.
+ * @return Message that should be displayed above the challenge.
+ */
+ CharSequence consumeCustomMessage();
}
}
@Override // Binder interface
- public void dismiss(IKeyguardDismissCallback callback) {
+ public void dismiss(IKeyguardDismissCallback callback, CharSequence message) {
checkPermission();
- mKeyguardViewMediator.dismiss(callback);
+ mKeyguardViewMediator.dismiss(callback, message);
}
@Override // Binder interface
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT;
-
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.NotificationManager;
private boolean mWakeAndUnlocking;
private IKeyguardDrawnCallback mDrawnCallback;
private boolean mLockWhenSimRemoved;
+ private CharSequence mCustomMessage;
KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
return;
} else if (info.isGuest() || info.isDemo()) {
// If we just switched to a guest, try to dismiss keyguard.
- dismiss(null /* callback */);
+ dismiss(null /* callback */, null /* message */);
}
}
}
}
@Override
+ public CharSequence consumeCustomMessage() {
+ final CharSequence message = mCustomMessage;
+ mCustomMessage = null;
+ return message;
+ }
+
+ @Override
public void onSecondaryDisplayShowingChanged(int displayId) {
synchronized (KeyguardViewMediator.this) {
setShowingLocked(mShowing, displayId, false);
/**
* Dismiss the keyguard through the security layers.
* @param callback Callback to be informed about the result
+ * @param message Message that should be displayed on the bouncer.
*/
- private void handleDismiss(IKeyguardDismissCallback callback) {
+ private void handleDismiss(IKeyguardDismissCallback callback, CharSequence message) {
if (mShowing) {
if (callback != null) {
mDismissCallbackRegistry.addCallback(callback);
}
+ mCustomMessage = message;
mStatusBarKeyguardViewManager.dismissAndCollapse();
} else if (callback != null) {
new DismissCallbackWrapper(callback).notifyDismissError();
}
}
- public void dismiss(IKeyguardDismissCallback callback) {
- mHandler.obtainMessage(DISMISS, callback).sendToTarget();
+ public void dismiss(IKeyguardDismissCallback callback, CharSequence message) {
+ mHandler.obtainMessage(DISMISS, new DismissMessage(callback, message)).sendToTarget();
}
/**
}
break;
case DISMISS:
- handleDismiss((IKeyguardDismissCallback) msg.obj);
+ final DismissMessage message = (DismissMessage) msg.obj;
+ handleDismiss(message.getCallback(), message.getMessage());
break;
case START_KEYGUARD_EXIT_ANIM:
Trace.beginSection("KeyguardViewMediator#handleMessage START_KEYGUARD_EXIT_ANIM");
}
}
}
+
+ private static class DismissMessage {
+ private final CharSequence mMessage;
+ private final IKeyguardDismissCallback mCallback;
+
+ DismissMessage(IKeyguardDismissCallback callback, CharSequence message) {
+ mCallback = callback;
+ mMessage = message;
+ }
+
+ public IKeyguardDismissCallback getCallback() {
+ return mCallback;
+ }
+
+ public CharSequence getMessage() {
+ return mMessage;
+ }
+ }
}
mRoot.setVisibility(View.VISIBLE);
mKeyguardView.onResume();
showPromptReason(mBouncerPromptReason);
+ final CharSequence customMessage = mCallback.consumeCustomMessage();
+ if (customMessage != null) {
+ mKeyguardView.showErrorMessage(customMessage);
+ }
// We might still be collapsed and the view didn't have time to layout yet or still
// be small, let's wait on the predraw to do the animation in that case.
if (mKeyguardView.getHeight() != 0 && mKeyguardView.getHeight() != mStatusBarHeight) {
public void dismissWithAction(OnDismissAction r, Runnable cancelAction,
boolean afterKeyguardGone) {
+ dismissWithAction(r, cancelAction, afterKeyguardGone, null /* message */);
+ }
+
+ public void dismissWithAction(OnDismissAction r, Runnable cancelAction,
+ boolean afterKeyguardGone, String message) {
if (mShowing) {
cancelPendingWakeupAction();
// If we're dozing, this needs to be delayed until after we wake up - unless we're
// wake-and-unlocking, because there dozing will last until the end of the transition.
if (mDozing && !isWakeAndUnlocking()) {
mPendingWakeupAction = new DismissWithActionRequest(
- r, cancelAction, afterKeyguardGone);
+ r, cancelAction, afterKeyguardGone, message);
return;
}
if (request != null) {
if (mShowing) {
dismissWithAction(request.dismissAction, request.cancelAction,
- request.afterKeyguardGone);
+ request.afterKeyguardGone, request.message);
} else if (request.dismissAction != null) {
request.dismissAction.onDismiss();
}
final OnDismissAction dismissAction;
final Runnable cancelAction;
final boolean afterKeyguardGone;
+ final String message;
DismissWithActionRequest(OnDismissAction dismissAction, Runnable cancelAction,
- boolean afterKeyguardGone) {
+ boolean afterKeyguardGone, String message) {
this.dismissAction = dismissAction;
this.cancelAction = cancelAction;
this.afterKeyguardGone = afterKeyguardGone;
+ this.message = message;
}
}
}
public void onDismissCancelled() throws RemoteException {
// Do nothing
}
- });
+ }, null /* message */);
} catch (RemoteException e) {
// Local call
}
}
@Override
- public void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback)
- throws RemoteException {
+ public void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback,
+ CharSequence message) throws RemoteException {
+ if (message != null) {
+ enforceCallingPermission(permission.SHOW_KEYGUARD_MESSAGE,
+ "dismissKeyguard()");
+ }
final long callingId = Binder.clearCallingIdentity();
try {
- mKeyguardController.dismissKeyguard(token, callback);
+ mKeyguardController.dismissKeyguard(token, callback, message);
} finally {
Binder.restoreCallingIdentity(callingId);
}
}
}
- void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback) {
+ void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback, CharSequence message) {
final ActivityRecord activityRecord = ActivityRecord.forTokenLocked(token);
if (activityRecord == null || !activityRecord.visibleIgnoringKeyguard) {
failCallback(callback);
mStackSupervisor.wakeUp("dismissKeyguard");
}
- mWindowManager.dismissKeyguard(callback);
+ mWindowManager.dismissKeyguard(callback, message);
}
private void setKeyguardGoingAway(boolean keyguardGoingAway) {
// insecure case, we actually show it on top of the lockscreen. See #canShowWhileOccluded.
if (!mOccluded && mDismissingKeyguardActivity != null
&& mWindowManager.isKeyguardSecure()) {
- mWindowManager.dismissKeyguard(null /* callback */);
+ mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
mDismissalRequested = true;
// If we are about to unocclude the Keyguard, but we can dismiss it without security,
USER_CURRENT) != 0;
if (shouldLockKeyguard) {
mWindowManager.lockNow(null);
- mWindowManager.dismissKeyguard(null /* callback */);
+ mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
getLockPatternUtils().requireCredentialEntry(USER_ALL);
}
} catch (Settings.SettingNotFoundException e) {
}
@Override
- public void dismissKeyguardLw(IKeyguardDismissCallback callback) {
+ public void dismissKeyguardLw(IKeyguardDismissCallback callback, CharSequence message) {
if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
// ask the keyguard to prompt the user to authenticate if necessary
- mKeyguardDelegate.dismiss(callback);
+ mKeyguardDelegate.dismiss(callback, message);
} else if (callback != null) {
try {
callback.onDismissError();
* Ask the policy to dismiss the keyguard, if it is currently shown.
*
* @param callback Callback to be informed about the result.
+ * @param message A message that should be displayed in the keyguard.
*/
- public void dismissKeyguardLw(@Nullable IKeyguardDismissCallback callback);
+ public void dismissKeyguardLw(@Nullable IKeyguardDismissCallback callback,
+ CharSequence message);
/**
* Ask the policy whether the Keyguard has drawn. If the Keyguard is disabled, this method
mKeyguardState.occluded = isOccluded;
}
- public void dismiss(IKeyguardDismissCallback callback) {
+ public void dismiss(IKeyguardDismissCallback callback, CharSequence message) {
if (mKeyguardService != null) {
- mKeyguardService.dismiss(callback);
+ mKeyguardService.dismiss(callback, message);
}
}
}
@Override // Binder interface
- public void dismiss(IKeyguardDismissCallback callback) {
+ public void dismiss(IKeyguardDismissCallback callback, CharSequence message) {
try {
- mService.dismiss(callback);
+ mService.dismiss(callback, message);
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}
}
@Override
- public void dismissKeyguard(IKeyguardDismissCallback callback) {
+ public void dismissKeyguard(IKeyguardDismissCallback callback, CharSequence message) {
checkCallingPermission(permission.CONTROL_KEYGUARD, "dismissKeyguard");
synchronized(mWindowMap) {
- mPolicy.dismissKeyguardLw(callback);
+ mPolicy.dismissKeyguardLw(callback, message);
}
}
}
private int runDismissKeyguard(PrintWriter pw) throws RemoteException {
- mInterface.dismissKeyguard(null /* callback */);
+ mInterface.dismissKeyguard(null /* callback */, null /* message */);
return 0;
}
return false;
}
mLockPatternUtils.setLockScreenDisabled(disabled, userId);
- mInjector.getIWindowManager().dismissKeyguard(null);
+ mInjector.getIWindowManager().dismissKeyguard(null /* callback */, null /* message */);
} catch (RemoteException e) {
// Same process, does not happen.
} finally {
}
@Override
- public void dismissKeyguardLw(@Nullable IKeyguardDismissCallback callback) {
+ public void dismissKeyguardLw(@Nullable IKeyguardDismissCallback callback,
+ CharSequence message) {
}
@Override