Merge "Send "early canceled" to privileged clients" into rvc-dev

This commit is contained in:
Kevin Chyn
2020-03-28 00:05:59 +00:00
committed by Android (Google) Code Review
11 changed files with 123 additions and 1 deletions

View File

@@ -204,4 +204,18 @@ public interface BiometricConstants {
* @hide
*/
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;
}

View File

@@ -63,6 +63,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
/**
* @hide
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
public static final String KEY_USE_DEFAULT_TITLE = "use_default_title";
/**
* @hide
@@ -75,14 +76,17 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
/**
* @hide
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
public static final String KEY_DEVICE_CREDENTIAL_TITLE = "device_credential_title";
/**
* @hide
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
public static final String KEY_DEVICE_CREDENTIAL_SUBTITLE = "device_credential_subtitle";
/**
* @hide
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
public static final String KEY_DEVICE_CREDENTIAL_DESCRIPTION = "device_credential_description";
/**
* @hide
@@ -106,7 +110,15 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
* If this is set, check the Device Policy Manager for allowed biometrics.
* @hide
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
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.
@@ -383,6 +395,18 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
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}.
*
@@ -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,
@@ -732,6 +763,12 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
*/
@Override
public void onAuthenticationAcquired(int acquireInfo) {}
/**
* Receiver for internal system events. See {@link Builder#setReceiveSystemEvents(boolean)}
* @hide
*/
public void onSystemEvent(int event) {}
}
/**

View File

@@ -30,4 +30,6 @@ oneway interface IBiometricServiceReceiver {
void onAcquired(int acquiredInfo, String message);
// Notifies that the SystemUI dialog has been dismissed.
void onDialogDismissed(int reason);
// Notifies the client that an internal event, e.g. back button has occurred.
void onSystemEvent(int event);
}

View File

@@ -42,4 +42,6 @@ oneway interface IBiometricServiceReceiverInternal {
void onTryAgainPressed();
// Notifies that the user has pressed the "use password" button on SystemUI
void onDeviceCredentialPressed();
// Notifies the client that an internal event, e.g. back button has occurred.
void onSystemEvent(int event);
}

View File

@@ -22,6 +22,7 @@ import android.annotation.Nullable;
import android.content.Context;
import android.graphics.PixelFormat;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -207,6 +208,7 @@ public class AuthContainerView extends LinearLayout
animateAway(AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED);
break;
case AuthBiometricView.Callback.ACTION_USER_CANCELED:
sendEarlyUserCanceled();
animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
break;
case AuthBiometricView.Callback.ACTION_BUTTON_NEGATIVE:
@@ -286,11 +288,13 @@ public class AuthContainerView extends LinearLayout
addView(mFrameLayout);
// TODO: De-dupe the logic with AuthCredentialPasswordView
setOnKeyListener((v, keyCode, event) -> {
if (keyCode != KeyEvent.KEYCODE_BACK) {
return false;
}
if (event.getAction() == KeyEvent.ACTION_UP) {
sendEarlyUserCanceled();
animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
}
return true;
@@ -300,6 +304,11 @@ public class AuthContainerView extends LinearLayout
requestFocus();
}
void sendEarlyUserCanceled() {
mConfig.mCallback.onSystemEvent(
BiometricConstants.BIOMETRIC_SYSTEM_EVENT_EARLY_USER_CANCEL);
}
@Override
public boolean isAllowDeviceCredentials() {
return Utils.isDeviceCredentialAllowed(mConfig.mBiometricPromptBundle);

View File

@@ -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
public void onDismissed(@DismissedReason int reason, @Nullable byte[] credentialAttestation) {
switch (reason) {

View File

@@ -51,11 +51,13 @@ public class AuthCredentialPasswordView extends AuthCredentialView
super.onFinishInflate();
mPasswordField = findViewById(R.id.lockPassword);
mPasswordField.setOnEditorActionListener(this);
// TODO: De-dupe the logic with AuthContainerView
mPasswordField.setOnKeyListener((v, keyCode, event) -> {
if (keyCode != KeyEvent.KEYCODE_BACK) {
return false;
}
if (event.getAction() == KeyEvent.ACTION_UP) {
mContainerView.sendEarlyUserCanceled();
mContainerView.animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
}
return true;

View File

@@ -58,4 +58,11 @@ public interface AuthDialogCallback {
* Invoked when the "use password" button is clicked
*/
void onDeviceCredentialPressed();
/**
* See {@link android.hardware.biometrics.BiometricPrompt.Builder
* #setReceiveSystemEvents(boolean)}
* @param event
*/
void onSystemEvent(int event);
}

View File

@@ -34,6 +34,7 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricPrompt;
import android.os.Bundle;
import android.os.IBinder;
@@ -89,6 +90,8 @@ public class AuthContainerViewTest extends SysuiTestCase {
mAuthContainer.mBiometricCallback.onAction(
AuthBiometricView.Callback.ACTION_USER_CANCELED);
verify(mCallback).onSystemEvent(eq(
BiometricConstants.BIOMETRIC_SYSTEM_EVENT_EARLY_USER_CANCEL));
verify(mCallback).onDismissed(
eq(AuthDialogCallback.DISMISSED_USER_CANCELED),
eq(null) /* credentialAttestation */);

View File

@@ -158,7 +158,8 @@ public class AuthService extends SystemService {
|| bundle.getCharSequence(
BiometricPrompt.KEY_DEVICE_CREDENTIAL_SUBTITLE) != null
|| bundle.getCharSequence(
BiometricPrompt.KEY_DEVICE_CREDENTIAL_DESCRIPTION) != null) {
BiometricPrompt.KEY_DEVICE_CREDENTIAL_DESCRIPTION) != null
|| bundle.getBoolean(BiometricPrompt.KEY_RECEIVE_SYSTEM_EVENTS, false)) {
checkInternalPermission();
}

View File

@@ -112,6 +112,7 @@ public class BiometricService extends SystemService {
private static final int MSG_CANCEL_AUTHENTICATION = 10;
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_SYSTEM_EVENT = 13;
/**
* Authentication either just called and we have not transitioned to the CALLED state, or
@@ -360,6 +361,11 @@ public class BiometricService extends SystemService {
break;
}
case MSG_ON_SYSTEM_EVENT: {
handleOnSystemEvent((int) msg.obj);
break;
}
default:
Slog.e(TAG, "Unknown message: " + msg);
break;
@@ -632,6 +638,11 @@ public class BiometricService extends SystemService {
public void onDeviceCredentialPressed() {
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;
}
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
* all biometrics are ready, this invokes the SystemUI dialog through StatusBar.