From 1870e2dec4c397e6e758c2325e11e6826dcae520 Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Mon, 2 Apr 2018 14:34:21 -0400 Subject: [PATCH] ConfirmationPrompt: Update for API review. Misc. changes but notably the ConfirmationDialog class was renamed to ConfirmationPrompt. Manually tested by updating sample Android Confirmations application to use updated API. Bug: 77242268 Test: Manually tested. Change-Id: I1caa3c6bff9486b43ba111329d1ef83c3b67baf9 --- api/current.txt | 34 +++++------ .../security/ConfirmationCallback.java | 10 ++-- ...ionDialog.java => ConfirmationPrompt.java} | 57 +++++++++++-------- 3 files changed, 54 insertions(+), 47 deletions(-) rename core/java/android/security/{ConfirmationDialog.java => ConfirmationPrompt.java} (89%) diff --git a/api/current.txt b/api/current.txt index 670f6cae13191..f1d0ef013e296 100644 --- a/api/current.txt +++ b/api/current.txt @@ -38428,23 +38428,10 @@ package android.security { public abstract class ConfirmationCallback { ctor public ConfirmationCallback(); - method public void onConfirmedByUser(byte[]); - method public void onDismissedByApplication(); - method public void onDismissedByUser(); - method public void onError(java.lang.Exception); - } - - public class ConfirmationDialog { - method public void cancelPrompt(); - method public static boolean isSupported(); - method public void presentPrompt(java.util.concurrent.Executor, android.security.ConfirmationCallback) throws android.security.ConfirmationAlreadyPresentingException, android.security.ConfirmationNotAvailableException; - } - - public static class ConfirmationDialog.Builder { - ctor public ConfirmationDialog.Builder(); - method public android.security.ConfirmationDialog build(android.content.Context); - method public android.security.ConfirmationDialog.Builder setExtraData(byte[]); - method public android.security.ConfirmationDialog.Builder setPromptText(java.lang.CharSequence); + method public void onCanceled(); + method public void onConfirmed(byte[]); + method public void onDismissed(); + method public void onError(java.lang.Throwable); } public class ConfirmationNotAvailableException extends java.lang.Exception { @@ -38452,6 +38439,19 @@ package android.security { ctor public ConfirmationNotAvailableException(java.lang.String); } + public class ConfirmationPrompt { + method public void cancelPrompt(); + method public static boolean isSupported(android.content.Context); + method public void presentPrompt(java.util.concurrent.Executor, android.security.ConfirmationCallback) throws android.security.ConfirmationAlreadyPresentingException, android.security.ConfirmationNotAvailableException; + } + + public static final class ConfirmationPrompt.Builder { + ctor public ConfirmationPrompt.Builder(android.content.Context); + method public android.security.ConfirmationPrompt build(); + method public android.security.ConfirmationPrompt.Builder setExtraData(byte[]); + method public android.security.ConfirmationPrompt.Builder setPromptText(java.lang.CharSequence); + } + public final class KeyChain { ctor public KeyChain(); method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String); diff --git a/core/java/android/security/ConfirmationCallback.java b/core/java/android/security/ConfirmationCallback.java index 4670bce3a9e0d..fd027f0f31f10 100644 --- a/core/java/android/security/ConfirmationCallback.java +++ b/core/java/android/security/ConfirmationCallback.java @@ -33,22 +33,22 @@ public abstract class ConfirmationCallback { * * @param dataThatWasConfirmed the data that was confirmed, see above for the format. */ - public void onConfirmedByUser(@NonNull byte[] dataThatWasConfirmed) {} + public void onConfirmed(@NonNull byte[] dataThatWasConfirmed) {} /** * Called when the requested prompt was dismissed (not accepted) by the user. */ - public void onDismissedByUser() {} + public void onDismissed() {} /** * Called when the requested prompt was dismissed by the application. */ - public void onDismissedByApplication() {} + public void onCanceled() {} /** * Called when the requested prompt was dismissed because of a low-level error. * - * @param e an exception representing the error. + * @param e a throwable representing the error. */ - public void onError(Exception e) {} + public void onError(Throwable e) {} } diff --git a/core/java/android/security/ConfirmationDialog.java b/core/java/android/security/ConfirmationPrompt.java similarity index 89% rename from core/java/android/security/ConfirmationDialog.java rename to core/java/android/security/ConfirmationPrompt.java index 1697106c37822..5330cffee3db4 100644 --- a/core/java/android/security/ConfirmationDialog.java +++ b/core/java/android/security/ConfirmationPrompt.java @@ -68,7 +68,7 @@ import java.util.concurrent.Executor; * {@link #presentPrompt presentPrompt()} method. The Relying Party stores the nonce locally * since it'll use it in a later step. *
  • If the user approves the prompt a Confirmation Response is returned in the - * {@link ConfirmationCallback#onConfirmedByUser onConfirmedByUser(byte[])} callback as the + * {@link ConfirmationCallback#onConfirmed onConfirmed(byte[])} callback as the * dataThatWasConfirmed parameter. This blob contains the text that was shown to the * user, the extraData parameter, and possibly other data. *
  • The application signs the Confirmation Response with the previously created key and @@ -82,8 +82,8 @@ import java.util.concurrent.Executor; * last bullet, is to have the Relying Party generate promptText and store it * along the nonce in the extraData blob. */ -public class ConfirmationDialog { - private static final String TAG = "ConfirmationDialog"; +public class ConfirmationPrompt { + private static final String TAG = "ConfirmationPrompt"; private CharSequence mPromptText; private byte[] mExtraData; @@ -97,15 +97,15 @@ public class ConfirmationDialog { ConfirmationCallback callback) { switch (responseCode) { case KeyStore.CONFIRMATIONUI_OK: - callback.onConfirmedByUser(dataThatWasConfirmed); + callback.onConfirmed(dataThatWasConfirmed); break; case KeyStore.CONFIRMATIONUI_CANCELED: - callback.onDismissedByUser(); + callback.onDismissed(); break; case KeyStore.CONFIRMATIONUI_ABORTED: - callback.onDismissedByApplication(); + callback.onCanceled(); break; case KeyStore.CONFIRMATIONUI_SYSTEM_ERROR: @@ -145,21 +145,25 @@ public class ConfirmationDialog { }; /** - * A builder that collects arguments, to be shown on the system-provided confirmation dialog. + * A builder that collects arguments, to be shown on the system-provided confirmation prompt. */ - public static class Builder { + public static final class Builder { + private Context mContext; private CharSequence mPromptText; private byte[] mExtraData; /** - * Creates a builder for the confirmation dialog. + * Creates a builder for the confirmation prompt. + * + * @param context the application context */ - public Builder() { + public Builder(Context context) { + mContext = context; } /** - * Sets the prompt text for the dialog. + * Sets the prompt text for the prompt. * * @param promptText the text to present in the prompt. * @return the builder. @@ -170,7 +174,7 @@ public class ConfirmationDialog { } /** - * Sets the extra data for the dialog. + * Sets the extra data for the prompt. * * @param extraData data to include in the response data. * @return the builder. @@ -181,24 +185,23 @@ public class ConfirmationDialog { } /** - * Creates a {@link ConfirmationDialog} with the arguments supplied to this builder. + * Creates a {@link ConfirmationPrompt} with the arguments supplied to this builder. * - * @param context the application context - * @return a {@link ConfirmationDialog} + * @return a {@link ConfirmationPrompt} * @throws IllegalArgumentException if any of the required fields are not set. */ - public ConfirmationDialog build(Context context) { + public ConfirmationPrompt build() { if (TextUtils.isEmpty(mPromptText)) { throw new IllegalArgumentException("prompt text must be set and non-empty"); } if (mExtraData == null) { throw new IllegalArgumentException("extraData must be set"); } - return new ConfirmationDialog(context, mPromptText, mExtraData); + return new ConfirmationPrompt(mContext, mPromptText, mExtraData); } } - private ConfirmationDialog(Context context, CharSequence promptText, byte[] extraData) { + private ConfirmationPrompt(Context context, CharSequence promptText, byte[] extraData) { mContext = context; mPromptText = promptText; mExtraData = extraData; @@ -227,10 +230,10 @@ public class ConfirmationDialog { return uiOptionsAsFlags; } - private boolean isAccessibilityServiceRunning() { + private static boolean isAccessibilityServiceRunning(Context context) { boolean serviceRunning = false; try { - ContentResolver contentResolver = mContext.getContentResolver(); + ContentResolver contentResolver = context.getContentResolver(); int a11yEnabled = Settings.Secure.getInt(contentResolver, Settings.Secure.ACCESSIBILITY_ENABLED); if (a11yEnabled == 1) { @@ -249,12 +252,12 @@ public class ConfirmationDialog { * When the prompt is no longer being presented, one of the methods in * {@link ConfirmationCallback} is called on the supplied callback object. * - * Confirmation dialogs may not be available when accessibility services are running so this + * Confirmation prompts may not be available when accessibility services are running so this * may fail with a {@link ConfirmationNotAvailableException} exception even if * {@link #isSupported} returns {@code true}. * * @param executor the executor identifying the thread that will receive the callback. - * @param callback the callback to use when the dialog is done showing. + * @param callback the callback to use when the prompt is done showing. * @throws IllegalArgumentException if the prompt text is too long or malfomed. * @throws ConfirmationAlreadyPresentingException if another prompt is being presented. * @throws ConfirmationNotAvailableException if confirmation prompts are not supported. @@ -265,7 +268,7 @@ public class ConfirmationDialog { if (mCallback != null) { throw new ConfirmationAlreadyPresentingException(); } - if (isAccessibilityServiceRunning()) { + if (isAccessibilityServiceRunning(mContext)) { throw new ConfirmationNotAvailableException(); } mCallback = callback; @@ -301,7 +304,7 @@ public class ConfirmationDialog { * Cancels a prompt currently being displayed. * * On success, the - * {@link ConfirmationCallback#onDismissedByApplication onDismissedByApplication()} method on + * {@link ConfirmationCallback#onCanceled onCanceled()} method on * the supplied callback object will be called asynchronously. * * @throws IllegalStateException if no prompt is currently being presented. @@ -324,9 +327,13 @@ public class ConfirmationDialog { /** * Checks if the device supports confirmation prompts. * + * @param context the application context. * @return true if confirmation prompts are supported by the device. */ - public static boolean isSupported() { + public static boolean isSupported(Context context) { + if (isAccessibilityServiceRunning(context)) { + return false; + } return KeyStore.getInstance().isConfirmationPromptSupported(); } }