Update KeyguardManager & FeatureFlagUtils to support remote device lockscreen validation

Test: manual
Bug: 258505917
Change-Id: I411ad1d218abec434d5c3bbbd66746897b4ffef9
This commit is contained in:
Brian Lee
2023-01-27 15:34:08 -08:00
parent c9ea074e38
commit 84ae481860
6 changed files with 88 additions and 6 deletions

View File

@@ -911,6 +911,7 @@ package android.app {
public class KeyguardManager {
method @RequiresPermission(android.Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) public long addWeakEscrowToken(@NonNull byte[], @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull android.app.KeyguardManager.WeakEscrowTokenActivatedListener);
method @NonNull @RequiresPermission(android.Manifest.permission.CHECK_REMOTE_LOCKSCREEN) public android.content.Intent createConfirmDeviceCredentialForRemoteValidationIntent(@NonNull android.app.StartLockscreenValidationRequest, @NonNull android.content.ComponentName, @Nullable CharSequence, @Nullable CharSequence, @Nullable CharSequence, @Nullable CharSequence);
method public android.content.Intent createConfirmFactoryResetCredentialIntent(CharSequence, CharSequence, CharSequence);
method @RequiresPermission("android.permission.SET_INITIAL_LOCK") public int getMinLockLength(boolean, int);
method @RequiresPermission(android.Manifest.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS) public boolean getPrivateNotificationsAllowed();

View File

@@ -31,6 +31,7 @@ import android.app.admin.DevicePolicyManager.PasswordComplexity;
import android.app.admin.PasswordMetrics;
import android.app.trust.ITrustManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -108,6 +109,13 @@ public class KeyguardManager {
public static final String ACTION_CONFIRM_FRP_CREDENTIAL =
"android.app.action.CONFIRM_FRP_CREDENTIAL";
/**
* Intent used to prompt user to to validate the credentials of a remote device.
* @hide
*/
public static final String ACTION_CONFIRM_REMOTE_DEVICE_CREDENTIAL =
"android.app.action.CONFIRM_REMOTE_DEVICE_CREDENTIAL";
/**
* A CharSequence dialog title to show to the user when used with a
* {@link #ACTION_CONFIRM_DEVICE_CREDENTIAL}.
@@ -130,10 +138,27 @@ public class KeyguardManager {
public static final String EXTRA_ALTERNATE_BUTTON_LABEL =
"android.app.extra.ALTERNATE_BUTTON_LABEL";
/**
* A CharSequence label for the checkbox when used with
* {@link #ACTION_CONFIRM_REMOTE_DEVICE_CREDENTIAL}
* @hide
*/
public static final String EXTRA_CHECKBOX_LABEL = "android.app.extra.CHECKBOX_LABEL";
/**
* A {@link StartLockscreenValidationRequest} extra to be sent along with
* {@link #ACTION_CONFIRM_REMOTE_DEVICE_CREDENTIAL} containing the data needed to prompt for
* a remote device's lock screen.
* @hide
*/
public static final String EXTRA_START_LOCKSCREEN_VALIDATION_REQUEST =
"android.app.extra.START_LOCKSCREEN_VALIDATION_REQUEST";
/**
* Result code returned by the activity started by
* {@link #createConfirmFactoryResetCredentialIntent} indicating that the user clicked the
* alternate button.
* {@link #createConfirmFactoryResetCredentialIntent} or
* {@link #createConfirmDeviceCredentialForRemoteValidationIntent}
* indicating that the user clicked the alternate button.
*
* @hide
*/
@@ -331,6 +356,47 @@ public class KeyguardManager {
return intent;
}
/**
* Get an Intent to launch an activity to prompt the user to confirm the
* credentials (pin, pattern or password) of a remote device.
* @param startLockscreenValidationRequest contains information necessary to start remote device
* credential validation.
* @param remoteLockscreenValidationServiceComponent
* the {@link ComponentName} of the implementation of
* {@link android.service.remotelockscreenvalidation.RemoteLockscreenValidationService}
* @param checkboxLabel if not empty, a checkbox is provided with the given label. When checked,
* the validated remote device credential will be set as the device lock of
* the current device.
* @param alternateButtonLabel if not empty, a button is provided with the given label. Upon
* clicking this button, the activity returns
* {@link #RESULT_ALTERNATE}.
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.CHECK_REMOTE_LOCKSCREEN)
@NonNull
public Intent createConfirmDeviceCredentialForRemoteValidationIntent(
@NonNull StartLockscreenValidationRequest startLockscreenValidationRequest,
@NonNull ComponentName remoteLockscreenValidationServiceComponent,
@Nullable CharSequence title,
@Nullable CharSequence description,
@Nullable CharSequence checkboxLabel,
@Nullable CharSequence alternateButtonLabel) {
Intent intent = new Intent(ACTION_CONFIRM_REMOTE_DEVICE_CREDENTIAL)
.putExtra(
EXTRA_START_LOCKSCREEN_VALIDATION_REQUEST, startLockscreenValidationRequest)
.putExtra(Intent.EXTRA_COMPONENT_NAME, remoteLockscreenValidationServiceComponent)
.putExtra(EXTRA_TITLE, title)
.putExtra(EXTRA_DESCRIPTION, description)
.putExtra(EXTRA_CHECKBOX_LABEL, checkboxLabel)
.putExtra(EXTRA_ALTERNATE_BUTTON_LABEL, alternateButtonLabel);
// explicitly set the package for security
intent.setPackage(getSettingsPackageForIntent(intent));
return intent;
}
/**
* Controls whether notifications can be shown atop a securely locked screen in their full
* private form (same as when the device is unlocked).

View File

@@ -183,6 +183,14 @@ public class FeatureFlagUtils {
public static final String SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API =
"settings_enable_lockscreen_transfer_api";
/**
* Flag to enable remote device credential validation
* @hide
*/
public static final String SETTINGS_REMOTE_DEVICE_CREDENTIAL_VALIDATION =
"settings_remote_device_credential_validation";
private static final Map<String, String> DEFAULT_FLAGS;
static {
@@ -226,6 +234,7 @@ public class FeatureFlagUtils {
DEFAULT_FLAGS.put(SETTINGS_FLASH_ALERTS, "false");
DEFAULT_FLAGS.put(SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, "true");
DEFAULT_FLAGS.put(SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API, "false");
DEFAULT_FLAGS.put(SETTINGS_REMOTE_DEVICE_CREDENTIAL_VALIDATION, "false");
}
private static final Set<String> PERSISTENT_FLAGS;

View File

@@ -65,6 +65,7 @@ import com.google.android.collect.Lists;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
@@ -115,6 +116,13 @@ public class LockPatternUtils {
public static final int CREDENTIAL_TYPE_PIN = 3;
public static final int CREDENTIAL_TYPE_PASSWORD = 4;
/**
* Header used for the encryption and decryption of the device credential for
* remote device lockscreen validation.
*/
public static final byte[] ENCRYPTED_REMOTE_CREDENTIALS_HEADER =
"encrypted_remote_credentials".getBytes(StandardCharsets.UTF_8);
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"CREDENTIAL_TYPE_"}, value = {
CREDENTIAL_TYPE_NONE,

View File

@@ -102,8 +102,6 @@ public class RecoverableKeyStoreManager {
private static final String TAG = "RecoverableKeyStoreMgr";
private static final long SYNC_DELAY_MILLIS = 2000;
private static final int INVALID_REMOTE_GUESS_LIMIT = 5;
public static final byte[] ENCRYPTED_REMOTE_CREDENTIALS_HEADER =
"encrypted_remote_credentials".getBytes(StandardCharsets.UTF_8);
private static RecoverableKeyStoreManager mInstance;
@@ -1055,7 +1053,7 @@ public class RecoverableKeyStoreManager {
decryptedCredentials = SecureBox.decrypt(
session.getKeyPair().getPrivate(),
/* sharedSecret= */ null,
ENCRYPTED_REMOTE_CREDENTIALS_HEADER,
LockPatternUtils.ENCRYPTED_REMOTE_CREDENTIALS_HEADER,
encryptedCredential);
} catch (NoSuchAlgorithmException e) {
Log.wtf(TAG, "Missing SecureBox algorithm. AOSP required to support this.", e);

View File

@@ -1462,7 +1462,7 @@ public class RecoverableKeyStoreManagerTest {
return SecureBox.encrypt(
publicKey,
/* sharedSecret= */ null,
RecoverableKeyStoreManager.ENCRYPTED_REMOTE_CREDENTIALS_HEADER,
LockPatternUtils.ENCRYPTED_REMOTE_CREDENTIALS_HEADER,
credentials);
}