Merge "Send "early canceled" to privileged clients" into rvc-dev
This commit is contained in:
@@ -204,4 +204,18 @@ public interface BiometricConstants {
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
int BIOMETRIC_ACQUIRED_VENDOR_BASE = 1000;
|
int BIOMETRIC_ACQUIRED_VENDOR_BASE = 1000;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Internal messages.
|
||||||
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See {@link BiometricPrompt.Builder#setReceiveSystemEvents(boolean)}. This message is sent
|
||||||
|
* immediately when the user cancels authentication for example by tapping the back button or
|
||||||
|
* tapping the scrim. This is before {@link #BIOMETRIC_ERROR_USER_CANCELED}, which is sent when
|
||||||
|
* dismissal animation completes.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
int BIOMETRIC_SYSTEM_EVENT_EARLY_USER_CANCEL = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
|
|||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
|
||||||
public static final String KEY_USE_DEFAULT_TITLE = "use_default_title";
|
public static final String KEY_USE_DEFAULT_TITLE = "use_default_title";
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
@@ -75,14 +76,17 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
|
|||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
|
||||||
public static final String KEY_DEVICE_CREDENTIAL_TITLE = "device_credential_title";
|
public static final String KEY_DEVICE_CREDENTIAL_TITLE = "device_credential_title";
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
|
||||||
public static final String KEY_DEVICE_CREDENTIAL_SUBTITLE = "device_credential_subtitle";
|
public static final String KEY_DEVICE_CREDENTIAL_SUBTITLE = "device_credential_subtitle";
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
|
||||||
public static final String KEY_DEVICE_CREDENTIAL_DESCRIPTION = "device_credential_description";
|
public static final String KEY_DEVICE_CREDENTIAL_DESCRIPTION = "device_credential_description";
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
@@ -106,7 +110,15 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
|
|||||||
* If this is set, check the Device Policy Manager for allowed biometrics.
|
* If this is set, check the Device Policy Manager for allowed biometrics.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
|
||||||
public static final String EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS = "check_dpm";
|
public static final String EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS = "check_dpm";
|
||||||
|
/**
|
||||||
|
* Request to receive system events, such as back gesture/button. See
|
||||||
|
* {@link AuthenticationCallback#onSystemEvent(int)}
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
|
||||||
|
public static final String KEY_RECEIVE_SYSTEM_EVENTS = "receive_system_events";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error/help message will show for this amount of time.
|
* Error/help message will show for this amount of time.
|
||||||
@@ -383,6 +395,18 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set, receive internal events via {@link AuthenticationCallback#onSystemEvent(int)}
|
||||||
|
* @param set
|
||||||
|
* @return This builder.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public Builder setReceiveSystemEvents(boolean set) {
|
||||||
|
mBundle.putBoolean(KEY_RECEIVE_SYSTEM_EVENTS, set);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link BiometricPrompt}.
|
* Creates a {@link BiometricPrompt}.
|
||||||
*
|
*
|
||||||
@@ -493,6 +517,13 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSystemEvent(int event) throws RemoteException {
|
||||||
|
mExecutor.execute(() -> {
|
||||||
|
mAuthenticationCallback.onSystemEvent(event);
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private BiometricPrompt(Context context, Bundle bundle,
|
private BiometricPrompt(Context context, Bundle bundle,
|
||||||
@@ -732,6 +763,12 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onAuthenticationAcquired(int acquireInfo) {}
|
public void onAuthenticationAcquired(int acquireInfo) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receiver for internal system events. See {@link Builder#setReceiveSystemEvents(boolean)}
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public void onSystemEvent(int event) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -30,4 +30,6 @@ oneway interface IBiometricServiceReceiver {
|
|||||||
void onAcquired(int acquiredInfo, String message);
|
void onAcquired(int acquiredInfo, String message);
|
||||||
// Notifies that the SystemUI dialog has been dismissed.
|
// Notifies that the SystemUI dialog has been dismissed.
|
||||||
void onDialogDismissed(int reason);
|
void onDialogDismissed(int reason);
|
||||||
|
// Notifies the client that an internal event, e.g. back button has occurred.
|
||||||
|
void onSystemEvent(int event);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,4 +42,6 @@ oneway interface IBiometricServiceReceiverInternal {
|
|||||||
void onTryAgainPressed();
|
void onTryAgainPressed();
|
||||||
// Notifies that the user has pressed the "use password" button on SystemUI
|
// Notifies that the user has pressed the "use password" button on SystemUI
|
||||||
void onDeviceCredentialPressed();
|
void onDeviceCredentialPressed();
|
||||||
|
// Notifies the client that an internal event, e.g. back button has occurred.
|
||||||
|
void onSystemEvent(int event);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import android.annotation.Nullable;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
import android.hardware.biometrics.BiometricAuthenticator;
|
import android.hardware.biometrics.BiometricAuthenticator;
|
||||||
|
import android.hardware.biometrics.BiometricConstants;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@@ -207,6 +208,7 @@ public class AuthContainerView extends LinearLayout
|
|||||||
animateAway(AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED);
|
animateAway(AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED);
|
||||||
break;
|
break;
|
||||||
case AuthBiometricView.Callback.ACTION_USER_CANCELED:
|
case AuthBiometricView.Callback.ACTION_USER_CANCELED:
|
||||||
|
sendEarlyUserCanceled();
|
||||||
animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
|
animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
|
||||||
break;
|
break;
|
||||||
case AuthBiometricView.Callback.ACTION_BUTTON_NEGATIVE:
|
case AuthBiometricView.Callback.ACTION_BUTTON_NEGATIVE:
|
||||||
@@ -286,11 +288,13 @@ public class AuthContainerView extends LinearLayout
|
|||||||
|
|
||||||
addView(mFrameLayout);
|
addView(mFrameLayout);
|
||||||
|
|
||||||
|
// TODO: De-dupe the logic with AuthCredentialPasswordView
|
||||||
setOnKeyListener((v, keyCode, event) -> {
|
setOnKeyListener((v, keyCode, event) -> {
|
||||||
if (keyCode != KeyEvent.KEYCODE_BACK) {
|
if (keyCode != KeyEvent.KEYCODE_BACK) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (event.getAction() == KeyEvent.ACTION_UP) {
|
if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||||
|
sendEarlyUserCanceled();
|
||||||
animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
|
animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -300,6 +304,11 @@ public class AuthContainerView extends LinearLayout
|
|||||||
requestFocus();
|
requestFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sendEarlyUserCanceled() {
|
||||||
|
mConfig.mCallback.onSystemEvent(
|
||||||
|
BiometricConstants.BIOMETRIC_SYSTEM_EVENT_EARLY_USER_CANCEL);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAllowDeviceCredentials() {
|
public boolean isAllowDeviceCredentials() {
|
||||||
return Utils.isDeviceCredentialAllowed(mConfig.mBiometricPromptBundle);
|
return Utils.isDeviceCredentialAllowed(mConfig.mBiometricPromptBundle);
|
||||||
|
|||||||
@@ -164,6 +164,19 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSystemEvent(int event) {
|
||||||
|
if (mReceiver == null) {
|
||||||
|
Log.e(TAG, "onSystemEvent(" + event + "): Receiver is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
mReceiver.onSystemEvent(event);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "RemoteException when sending system event", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDismissed(@DismissedReason int reason, @Nullable byte[] credentialAttestation) {
|
public void onDismissed(@DismissedReason int reason, @Nullable byte[] credentialAttestation) {
|
||||||
switch (reason) {
|
switch (reason) {
|
||||||
|
|||||||
@@ -51,11 +51,13 @@ public class AuthCredentialPasswordView extends AuthCredentialView
|
|||||||
super.onFinishInflate();
|
super.onFinishInflate();
|
||||||
mPasswordField = findViewById(R.id.lockPassword);
|
mPasswordField = findViewById(R.id.lockPassword);
|
||||||
mPasswordField.setOnEditorActionListener(this);
|
mPasswordField.setOnEditorActionListener(this);
|
||||||
|
// TODO: De-dupe the logic with AuthContainerView
|
||||||
mPasswordField.setOnKeyListener((v, keyCode, event) -> {
|
mPasswordField.setOnKeyListener((v, keyCode, event) -> {
|
||||||
if (keyCode != KeyEvent.KEYCODE_BACK) {
|
if (keyCode != KeyEvent.KEYCODE_BACK) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (event.getAction() == KeyEvent.ACTION_UP) {
|
if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||||
|
mContainerView.sendEarlyUserCanceled();
|
||||||
mContainerView.animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
|
mContainerView.animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -58,4 +58,11 @@ public interface AuthDialogCallback {
|
|||||||
* Invoked when the "use password" button is clicked
|
* Invoked when the "use password" button is clicked
|
||||||
*/
|
*/
|
||||||
void onDeviceCredentialPressed();
|
void onDeviceCredentialPressed();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See {@link android.hardware.biometrics.BiometricPrompt.Builder
|
||||||
|
* #setReceiveSystemEvents(boolean)}
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
|
void onSystemEvent(int event);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import static org.mockito.Mockito.when;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.hardware.biometrics.BiometricAuthenticator;
|
import android.hardware.biometrics.BiometricAuthenticator;
|
||||||
|
import android.hardware.biometrics.BiometricConstants;
|
||||||
import android.hardware.biometrics.BiometricPrompt;
|
import android.hardware.biometrics.BiometricPrompt;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
@@ -89,6 +90,8 @@ public class AuthContainerViewTest extends SysuiTestCase {
|
|||||||
|
|
||||||
mAuthContainer.mBiometricCallback.onAction(
|
mAuthContainer.mBiometricCallback.onAction(
|
||||||
AuthBiometricView.Callback.ACTION_USER_CANCELED);
|
AuthBiometricView.Callback.ACTION_USER_CANCELED);
|
||||||
|
verify(mCallback).onSystemEvent(eq(
|
||||||
|
BiometricConstants.BIOMETRIC_SYSTEM_EVENT_EARLY_USER_CANCEL));
|
||||||
verify(mCallback).onDismissed(
|
verify(mCallback).onDismissed(
|
||||||
eq(AuthDialogCallback.DISMISSED_USER_CANCELED),
|
eq(AuthDialogCallback.DISMISSED_USER_CANCELED),
|
||||||
eq(null) /* credentialAttestation */);
|
eq(null) /* credentialAttestation */);
|
||||||
|
|||||||
@@ -158,7 +158,8 @@ public class AuthService extends SystemService {
|
|||||||
|| bundle.getCharSequence(
|
|| bundle.getCharSequence(
|
||||||
BiometricPrompt.KEY_DEVICE_CREDENTIAL_SUBTITLE) != null
|
BiometricPrompt.KEY_DEVICE_CREDENTIAL_SUBTITLE) != null
|
||||||
|| bundle.getCharSequence(
|
|| bundle.getCharSequence(
|
||||||
BiometricPrompt.KEY_DEVICE_CREDENTIAL_DESCRIPTION) != null) {
|
BiometricPrompt.KEY_DEVICE_CREDENTIAL_DESCRIPTION) != null
|
||||||
|
|| bundle.getBoolean(BiometricPrompt.KEY_RECEIVE_SYSTEM_EVENTS, false)) {
|
||||||
checkInternalPermission();
|
checkInternalPermission();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ public class BiometricService extends SystemService {
|
|||||||
private static final int MSG_CANCEL_AUTHENTICATION = 10;
|
private static final int MSG_CANCEL_AUTHENTICATION = 10;
|
||||||
private static final int MSG_ON_AUTHENTICATION_TIMED_OUT = 11;
|
private static final int MSG_ON_AUTHENTICATION_TIMED_OUT = 11;
|
||||||
private static final int MSG_ON_DEVICE_CREDENTIAL_PRESSED = 12;
|
private static final int MSG_ON_DEVICE_CREDENTIAL_PRESSED = 12;
|
||||||
|
private static final int MSG_ON_SYSTEM_EVENT = 13;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authentication either just called and we have not transitioned to the CALLED state, or
|
* Authentication either just called and we have not transitioned to the CALLED state, or
|
||||||
@@ -360,6 +361,11 @@ public class BiometricService extends SystemService {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case MSG_ON_SYSTEM_EVENT: {
|
||||||
|
handleOnSystemEvent((int) msg.obj);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Slog.e(TAG, "Unknown message: " + msg);
|
Slog.e(TAG, "Unknown message: " + msg);
|
||||||
break;
|
break;
|
||||||
@@ -632,6 +638,11 @@ public class BiometricService extends SystemService {
|
|||||||
public void onDeviceCredentialPressed() {
|
public void onDeviceCredentialPressed() {
|
||||||
mHandler.sendEmptyMessage(MSG_ON_DEVICE_CREDENTIAL_PRESSED);
|
mHandler.sendEmptyMessage(MSG_ON_DEVICE_CREDENTIAL_PRESSED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSystemEvent(int event) {
|
||||||
|
mHandler.obtainMessage(MSG_ON_SYSTEM_EVENT, event).sendToTarget();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -1579,6 +1590,27 @@ public class BiometricService extends SystemService {
|
|||||||
mCurrentAuthSession.mState = STATE_SHOWING_DEVICE_CREDENTIAL;
|
mCurrentAuthSession.mState = STATE_SHOWING_DEVICE_CREDENTIAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleOnSystemEvent(int event) {
|
||||||
|
final boolean shouldReceive = mCurrentAuthSession.mBundle
|
||||||
|
.getBoolean(BiometricPrompt.KEY_RECEIVE_SYSTEM_EVENTS, false);
|
||||||
|
Slog.d(TAG, "onSystemEvent: " + event + ", shouldReceive: " + shouldReceive);
|
||||||
|
|
||||||
|
if (mCurrentAuthSession == null) {
|
||||||
|
Slog.e(TAG, "Auth session null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shouldReceive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
mCurrentAuthSession.mClientReceiver.onSystemEvent(event);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.e(TAG, "RemoteException", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked when each service has notified that its client is ready to be started. When
|
* Invoked when each service has notified that its client is ready to be started. When
|
||||||
* all biometrics are ready, this invokes the SystemUI dialog through StatusBar.
|
* all biometrics are ready, this invokes the SystemUI dialog through StatusBar.
|
||||||
|
|||||||
Reference in New Issue
Block a user