Changes to support reducing noise in active unlock notifications.
1. Add additional trigger onUserMayRequestUnlock - point existing trigger points from SystemUI to this 2. Argument added to onUserRequestedUnlock to indicate if user wants to dismiss keyguard. 3. Callback for result of grantTrust calls. - curently only calls back if device was unlocked as a result of the call See design: go/au-noise-reduction Note: changes made to SystemUI are manually tested and may need refactoring which is being skipped now to meet the API Freeze deadline. Bug: 225231929 Test: atest TrustTests Test: Manual interaction with wake & fingerprint sensor CTS-Coverage-Bug: 213944235 Change-Id: I8d08229f09c9a1f2295b7eb464d12cad0c6b8303
This commit is contained in:
parent
34fba3edc7
commit
6c707a47da
@ -11830,11 +11830,23 @@ package android.service.translation {
|
||||
|
||||
package android.service.trust {
|
||||
|
||||
public final class GrantTrustResult implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public int getStatus();
|
||||
method @NonNull public static String statusToString(int);
|
||||
method @NonNull public static android.service.trust.GrantTrustResult withStatus(int);
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.service.trust.GrantTrustResult> CREATOR;
|
||||
field public static final int STATUS_UNKNOWN = 0; // 0x0
|
||||
field public static final int STATUS_UNLOCKED_BY_GRANT = 1; // 0x1
|
||||
}
|
||||
|
||||
public class TrustAgentService extends android.app.Service {
|
||||
ctor public TrustAgentService();
|
||||
method public final void addEscrowToken(byte[], android.os.UserHandle);
|
||||
method @Deprecated public final void grantTrust(CharSequence, long, boolean);
|
||||
method public final void grantTrust(CharSequence, long, int);
|
||||
method @Deprecated public final void grantTrust(CharSequence, long, int);
|
||||
method public final void grantTrust(@NonNull CharSequence, long, int, @Nullable java.util.function.Consumer<android.service.trust.GrantTrustResult>);
|
||||
method public final void isEscrowTokenActive(long, android.os.UserHandle);
|
||||
method public final void lockUser();
|
||||
method public final android.os.IBinder onBind(android.content.Intent);
|
||||
@ -11847,7 +11859,8 @@ package android.service.trust {
|
||||
method public void onEscrowTokenStateReceived(long, int);
|
||||
method public void onTrustTimeout();
|
||||
method public void onUnlockAttempt(boolean);
|
||||
method public void onUserRequestedUnlock();
|
||||
method public void onUserMayRequestUnlock();
|
||||
method public void onUserRequestedUnlock(boolean);
|
||||
method public final void removeEscrowToken(long, android.os.UserHandle);
|
||||
method public final void revokeTrust();
|
||||
method public final void setManagingTrust(boolean);
|
||||
|
@ -26,7 +26,8 @@ import android.hardware.biometrics.BiometricSourceType;
|
||||
*/
|
||||
interface ITrustManager {
|
||||
void reportUnlockAttempt(boolean successful, int userId);
|
||||
void reportUserRequestedUnlock(int userId);
|
||||
void reportUserRequestedUnlock(int userId, boolean dismissKeyguard);
|
||||
void reportUserMayRequestUnlock(int userId);
|
||||
void reportUnlockLockout(int timeoutMs, int userId);
|
||||
void reportEnabledTrustAgentsChanged(int userId);
|
||||
void registerTrustListener(in ITrustListener trustListener);
|
||||
|
@ -92,10 +92,25 @@ public class TrustManager {
|
||||
* Reports that the user {@code userId} is likely interested in unlocking the device.
|
||||
*
|
||||
* Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
|
||||
*
|
||||
* @param dismissKeyguard whether the user wants to dismiss keyguard
|
||||
*/
|
||||
public void reportUserRequestedUnlock(int userId) {
|
||||
public void reportUserRequestedUnlock(int userId, boolean dismissKeyguard) {
|
||||
try {
|
||||
mService.reportUserRequestedUnlock(userId);
|
||||
mService.reportUserRequestedUnlock(userId, dismissKeyguard);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports that the user {@code userId} may want to unlock the device soon.
|
||||
*
|
||||
* Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
|
||||
*/
|
||||
public void reportUserMayRequestUnlock(int userId) {
|
||||
try {
|
||||
mService.reportUserMayRequestUnlock(userId);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
|
19
core/java/android/service/trust/GrantTrustResult.aidl
Normal file
19
core/java/android/service/trust/GrantTrustResult.aidl
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.service.trust;
|
||||
|
||||
parcelable GrantTrustResult;
|
179
core/java/android/service/trust/GrantTrustResult.java
Normal file
179
core/java/android/service/trust/GrantTrustResult.java
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.service.trust;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.SystemApi;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.android.internal.util.DataClass;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Result type for a callback in a call to
|
||||
* {@link TrustAgentService#grantTrust(CharSequence, long, int)}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@DataClass(genHiddenConstructor = true)
|
||||
@SystemApi
|
||||
public final class GrantTrustResult implements Parcelable {
|
||||
|
||||
/** Result status is unknown to this version of the SDK. */
|
||||
public static final int STATUS_UNKNOWN = 0;
|
||||
|
||||
/** The device went from locked to unlocked as a result of the call. */
|
||||
public static final int STATUS_UNLOCKED_BY_GRANT = 1;
|
||||
|
||||
@Status
|
||||
private int mStatus;
|
||||
|
||||
/** Returns a new {@link GrantTrustResult} with the specified status. */
|
||||
@NonNull
|
||||
public static GrantTrustResult withStatus(@Status int status) {
|
||||
return new GrantTrustResult(status);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Code below generated by codegen v1.0.23.
|
||||
//
|
||||
// DO NOT MODIFY!
|
||||
// CHECKSTYLE:OFF Generated code
|
||||
//
|
||||
// To regenerate run:
|
||||
// $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/trust/GrantTrustResult.java
|
||||
//
|
||||
// To exclude the generated code from IntelliJ auto-formatting enable (one-time):
|
||||
// Settings > Editor > Code Style > Formatter Control
|
||||
//@formatter:off
|
||||
|
||||
|
||||
/** @hide */
|
||||
@IntDef(prefix = "STATUS_", value = {
|
||||
STATUS_UNKNOWN,
|
||||
STATUS_UNLOCKED_BY_GRANT
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@DataClass.Generated.Member
|
||||
public @interface Status {}
|
||||
|
||||
@NonNull
|
||||
@DataClass.Generated.Member
|
||||
public static String statusToString(@Status int value) {
|
||||
switch (value) {
|
||||
case STATUS_UNKNOWN:
|
||||
return "STATUS_UNKNOWN";
|
||||
case STATUS_UNLOCKED_BY_GRANT:
|
||||
return "STATUS_UNLOCKED_BY_GRANT";
|
||||
default: return Integer.toHexString(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new GrantTrustResult.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@DataClass.Generated.Member
|
||||
public GrantTrustResult(
|
||||
@Status int status) {
|
||||
this.mStatus = status;
|
||||
|
||||
if (!(mStatus == STATUS_UNKNOWN)
|
||||
&& !(mStatus == STATUS_UNLOCKED_BY_GRANT)) {
|
||||
throw new java.lang.IllegalArgumentException(
|
||||
"status was " + mStatus + " but must be one of: "
|
||||
+ "STATUS_UNKNOWN(" + STATUS_UNKNOWN + "), "
|
||||
+ "STATUS_UNLOCKED_BY_GRANT(" + STATUS_UNLOCKED_BY_GRANT + ")");
|
||||
}
|
||||
|
||||
|
||||
// onConstructed(); // You can define this method to get a callback
|
||||
}
|
||||
|
||||
@DataClass.Generated.Member
|
||||
public @Status int getStatus() {
|
||||
return mStatus;
|
||||
}
|
||||
|
||||
@Override
|
||||
@DataClass.Generated.Member
|
||||
public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
|
||||
// You can override field parcelling by defining methods like:
|
||||
// void parcelFieldName(Parcel dest, int flags) { ... }
|
||||
|
||||
dest.writeInt(mStatus);
|
||||
}
|
||||
|
||||
@Override
|
||||
@DataClass.Generated.Member
|
||||
public int describeContents() { return 0; }
|
||||
|
||||
/** @hide */
|
||||
@SuppressWarnings({"unchecked", "RedundantCast"})
|
||||
@DataClass.Generated.Member
|
||||
/* package-private */ GrantTrustResult(@NonNull android.os.Parcel in) {
|
||||
// You can override field unparcelling by defining methods like:
|
||||
// static FieldType unparcelFieldName(Parcel in) { ... }
|
||||
|
||||
int status = in.readInt();
|
||||
|
||||
this.mStatus = status;
|
||||
|
||||
if (!(mStatus == STATUS_UNKNOWN)
|
||||
&& !(mStatus == STATUS_UNLOCKED_BY_GRANT)) {
|
||||
throw new java.lang.IllegalArgumentException(
|
||||
"status was " + mStatus + " but must be one of: "
|
||||
+ "STATUS_UNKNOWN(" + STATUS_UNKNOWN + "), "
|
||||
+ "STATUS_UNLOCKED_BY_GRANT(" + STATUS_UNLOCKED_BY_GRANT + ")");
|
||||
}
|
||||
|
||||
|
||||
// onConstructed(); // You can define this method to get a callback
|
||||
}
|
||||
|
||||
@DataClass.Generated.Member
|
||||
public static final @NonNull Parcelable.Creator<GrantTrustResult> CREATOR
|
||||
= new Parcelable.Creator<GrantTrustResult>() {
|
||||
@Override
|
||||
public GrantTrustResult[] newArray(int size) {
|
||||
return new GrantTrustResult[size];
|
||||
}
|
||||
|
||||
@Override
|
||||
public GrantTrustResult createFromParcel(@NonNull android.os.Parcel in) {
|
||||
return new GrantTrustResult(in);
|
||||
}
|
||||
};
|
||||
|
||||
@DataClass.Generated(
|
||||
time = 1647878197834L,
|
||||
codegenVersion = "1.0.23",
|
||||
sourceFile = "frameworks/base/core/java/android/service/trust/GrantTrustResult.java",
|
||||
inputSignatures = "public static final int STATUS_UNKNOWN\npublic static final int STATUS_UNLOCKED_BY_GRANT\nprivate @android.service.trust.GrantTrustResult.Status int mStatus\npublic static @android.annotation.NonNull android.service.trust.GrantTrustResult withStatus(int)\nclass GrantTrustResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true)")
|
||||
@Deprecated
|
||||
private void __metadata() {}
|
||||
|
||||
|
||||
//@formatter:on
|
||||
// End of generated code
|
||||
|
||||
}
|
@ -25,7 +25,8 @@ import android.service.trust.ITrustAgentServiceCallback;
|
||||
*/
|
||||
interface ITrustAgentService {
|
||||
oneway void onUnlockAttempt(boolean successful);
|
||||
oneway void onUserRequestedUnlock();
|
||||
oneway void onUserRequestedUnlock(boolean dismissKeyguard);
|
||||
oneway void onUserMayRequestUnlock();
|
||||
oneway void onUnlockLockout(int timeoutMs);
|
||||
oneway void onTrustTimeout();
|
||||
oneway void onDeviceLocked();
|
||||
|
@ -18,13 +18,15 @@ package android.service.trust;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.UserHandle;
|
||||
import com.android.internal.infra.AndroidFuture;
|
||||
|
||||
/**
|
||||
* Communication channel from the TrustAgentService back to TrustManagerService.
|
||||
* @hide
|
||||
*/
|
||||
oneway interface ITrustAgentServiceCallback {
|
||||
void grantTrust(CharSequence message, long durationMs, int flags);
|
||||
void grantTrust(
|
||||
CharSequence message, long durationMs, int flags, in AndroidFuture resultCallback);
|
||||
void revokeTrust();
|
||||
void lockUser();
|
||||
void setManagingTrust(boolean managingTrust);
|
||||
|
@ -19,6 +19,7 @@ package android.service.trust;
|
||||
import android.Manifest;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.SystemApi;
|
||||
import android.app.Service;
|
||||
@ -39,9 +40,12 @@ import android.os.UserManager;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.infra.AndroidFuture;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* A service that notifies the system about whether it believes the environment of the device
|
||||
@ -183,6 +187,7 @@ public class TrustAgentService extends Service {
|
||||
private static final int MSG_ESCROW_TOKEN_STATE_RECEIVED = 8;
|
||||
private static final int MSG_ESCROW_TOKEN_REMOVED = 9;
|
||||
private static final int MSG_USER_REQUESTED_UNLOCK = 10;
|
||||
private static final int MSG_USER_MAY_REQUEST_UNLOCK = 11;
|
||||
|
||||
private static final String EXTRA_TOKEN = "token";
|
||||
private static final String EXTRA_TOKEN_HANDLE = "token_handle";
|
||||
@ -217,7 +222,10 @@ public class TrustAgentService extends Service {
|
||||
onUnlockAttempt(msg.arg1 != 0);
|
||||
break;
|
||||
case MSG_USER_REQUESTED_UNLOCK:
|
||||
onUserRequestedUnlock();
|
||||
onUserRequestedUnlock(msg.arg1 != 0);
|
||||
break;
|
||||
case MSG_USER_MAY_REQUEST_UNLOCK:
|
||||
onUserMayRequestUnlock();
|
||||
break;
|
||||
case MSG_UNLOCK_LOCKOUT:
|
||||
onDeviceUnlockLockout(msg.arg1);
|
||||
@ -296,17 +304,38 @@ public class TrustAgentService extends Service {
|
||||
public void onUnlockAttempt(boolean successful) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the user has interacted with the locked device such that they are likely to want
|
||||
* it to be unlocked soon. This approximates the timing when, for example, the platform would
|
||||
* check for face authentication to unlock the device.
|
||||
*
|
||||
* This signal can be used for the agent to make preparations to quickly unlock the device
|
||||
* with {@link #onUserRequestedUnlock}. Agents should not unlock the device based solely on this
|
||||
* signal. There is no guarantee that this method will be called before
|
||||
* {@link #onUserRequestedUnlock(boolean)}.
|
||||
*/
|
||||
public void onUserMayRequestUnlock() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the user has interacted with the locked device such that they likely want it
|
||||
* to be unlocked. This approximates the timing when, for example, the platform would check for
|
||||
* face authentication to unlock the device.
|
||||
* to be unlocked.
|
||||
*
|
||||
* When this is called, there is a high probability that the user wants to unlock the device and
|
||||
* that a biometric method is either not available or not the optimal method at this time. For
|
||||
* example, this may be called after some kinds of biometric authentication failure.
|
||||
*
|
||||
* A call to this method may be preceded by a call to {@link #onUserMayRequestUnlock} which
|
||||
* the agent can use as a signal to prepare for a subsequent call to this method.
|
||||
*
|
||||
* To attempt to unlock the device, the agent needs to call
|
||||
* {@link #grantTrust(CharSequence, long, int)}.
|
||||
*
|
||||
* @param dismissKeyguard true when the user wants keyguard dismissed
|
||||
*
|
||||
* @see #FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE
|
||||
*/
|
||||
public void onUserRequestedUnlock() {
|
||||
public void onUserRequestedUnlock(boolean dismissKeyguard) {
|
||||
}
|
||||
|
||||
/**
|
||||
@ -399,26 +428,10 @@ public class TrustAgentService extends Service {
|
||||
}
|
||||
|
||||
/**
|
||||
* Call to grant trust on the device.
|
||||
* Attempts to grant trust on the device.
|
||||
*
|
||||
* @param message describes why the device is trusted, e.g. "Trusted by location".
|
||||
* @param durationMs amount of time in milliseconds to keep the device in a trusted state.
|
||||
* Trust for this agent will automatically be revoked when the timeout expires unless
|
||||
* extended by a subsequent call to this function. The timeout is measured from the
|
||||
* invocation of this function as dictated by {@link SystemClock#elapsedRealtime())}.
|
||||
* For security reasons, the value should be no larger than necessary.
|
||||
* The value may be adjusted by the system as necessary to comply with a policy controlled
|
||||
* by the system or {@link DevicePolicyManager} restrictions. See {@link #onTrustTimeout()}
|
||||
* for determining when trust expires.
|
||||
* @param initiatedByUser this is a hint to the system that trust is being granted as the
|
||||
* direct result of user action - such as solving a security challenge. The hint is used
|
||||
* by the system to optimize the experience. Behavior may vary by device and release, so
|
||||
* one should only set this parameter if it meets the above criteria rather than relying on
|
||||
* the behavior of any particular device or release. Corresponds to
|
||||
* {@link #FLAG_GRANT_TRUST_INITIATED_BY_USER}.
|
||||
* @throws IllegalStateException if the agent is not currently managing trust.
|
||||
*
|
||||
* @deprecated use {@link #grantTrust(CharSequence, long, int)} instead.
|
||||
* @param initiatedByUser see {@link #FLAG_GRANT_TRUST_INITIATED_BY_USER}
|
||||
* @deprecated use {@link #grantTrust(CharSequence, long, int, Consumer)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public final void grantTrust(
|
||||
@ -427,7 +440,17 @@ public class TrustAgentService extends Service {
|
||||
}
|
||||
|
||||
/**
|
||||
* Call to grant trust on the device.
|
||||
* Attempts to grant trust on the device.
|
||||
* @deprecated use {@link #grantTrust(CharSequence, long, int, Consumer)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public final void grantTrust(
|
||||
final CharSequence message, final long durationMs, @GrantTrustFlags final int flags) {
|
||||
grantTrust(message, durationMs, flags, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to grant trust on the device.
|
||||
*
|
||||
* @param message describes why the device is trusted, e.g. "Trusted by location".
|
||||
* @param durationMs amount of time in milliseconds to keep the device in a trusted state.
|
||||
@ -438,19 +461,36 @@ public class TrustAgentService extends Service {
|
||||
* The value may be adjusted by the system as necessary to comply with a policy controlled
|
||||
* by the system or {@link DevicePolicyManager} restrictions. See {@link #onTrustTimeout()}
|
||||
* for determining when trust expires.
|
||||
* @param flags TBDocumented
|
||||
* @param flags flags to control call: see constants prefixed by {@code FLAG_GRANT_TRUST_}.
|
||||
* @param resultCallback may be called with the results of the grant
|
||||
* @throws IllegalStateException if the agent is not currently managing trust.
|
||||
*
|
||||
* See {@link GrantTrustResult} for the cases where {@code resultCallback} will be called.
|
||||
*/
|
||||
public final void grantTrust(
|
||||
final CharSequence message, final long durationMs, @GrantTrustFlags final int flags) {
|
||||
@NonNull final CharSequence message,
|
||||
final long durationMs,
|
||||
@GrantTrustFlags final int flags,
|
||||
@Nullable final Consumer<GrantTrustResult> resultCallback) {
|
||||
synchronized (mLock) {
|
||||
if (!mManagingTrust) {
|
||||
throw new IllegalStateException("Cannot grant trust if agent is not managing trust."
|
||||
+ " Call setManagingTrust(true) first.");
|
||||
}
|
||||
|
||||
// Prepare future for the IPC
|
||||
AndroidFuture<GrantTrustResult> future = new AndroidFuture<>();
|
||||
future.thenAccept(result -> {
|
||||
if (resultCallback != null) {
|
||||
// Instead of taking an explicit executor, we post this to mHandler to be
|
||||
// consistent with the other event methods in this class.
|
||||
mHandler.post(() -> resultCallback.accept(result));
|
||||
}
|
||||
});
|
||||
|
||||
if (mCallback != null) {
|
||||
try {
|
||||
mCallback.grantTrust(message.toString(), durationMs, flags);
|
||||
mCallback.grantTrust(message.toString(), durationMs, flags, future);
|
||||
} catch (RemoteException e) {
|
||||
onError("calling enableTrust()");
|
||||
}
|
||||
@ -460,7 +500,7 @@ public class TrustAgentService extends Service {
|
||||
mPendingGrantTrustTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
grantTrust(message, durationMs, flags);
|
||||
grantTrust(message, durationMs, flags, resultCallback);
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -666,8 +706,14 @@ public class TrustAgentService extends Service {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUserRequestedUnlock() {
|
||||
mHandler.obtainMessage(MSG_USER_REQUESTED_UNLOCK).sendToTarget();
|
||||
public void onUserRequestedUnlock(boolean dismissKeyguard) {
|
||||
mHandler.obtainMessage(MSG_USER_REQUESTED_UNLOCK, dismissKeyguard ? 1 : 0, 0)
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUserMayRequestUnlock() {
|
||||
mHandler.obtainMessage(MSG_USER_MAY_REQUEST_UNLOCK).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1486,6 +1486,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
@Override
|
||||
public void onAuthenticationFailed() {
|
||||
handleFingerprintAuthFailed();
|
||||
|
||||
// TODO(b/225231929): Refactor as needed, add tests, etc.
|
||||
mTrustManager.reportUserRequestedUnlock(
|
||||
KeyguardUpdateMonitor.getCurrentUser(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -2258,7 +2262,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
}
|
||||
|
||||
if (shouldTriggerActiveUnlock()) {
|
||||
mTrustManager.reportUserRequestedUnlock(KeyguardUpdateMonitor.getCurrentUser());
|
||||
// TODO(b/225231929): Refactor surrounding code to reflect calling of new method
|
||||
mTrustManager.reportUserMayRequestUnlock(KeyguardUpdateMonitor.getCurrentUser());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,12 +40,16 @@ import android.os.PersistableBundle;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.service.trust.GrantTrustResult;
|
||||
import android.service.trust.ITrustAgentService;
|
||||
import android.service.trust.ITrustAgentServiceCallback;
|
||||
import android.service.trust.TrustAgentService;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.infra.AndroidFuture;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@ -156,7 +160,9 @@ public class TrustAgentWrapper {
|
||||
}
|
||||
mTrusted = true;
|
||||
mTrustable = false;
|
||||
mMessage = (CharSequence) msg.obj;
|
||||
Pair<CharSequence, AndroidFuture<GrantTrustResult>> pair = (Pair) msg.obj;
|
||||
mMessage = pair.first;
|
||||
AndroidFuture<GrantTrustResult> resultCallback = pair.second;
|
||||
int flags = msg.arg1;
|
||||
mDisplayTrustGrantedMessage = (flags & FLAG_GRANT_TRUST_DISPLAY_MESSAGE) != 0;
|
||||
if ((flags & FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) != 0) {
|
||||
@ -189,7 +195,7 @@ public class TrustAgentWrapper {
|
||||
mTrustManagerService.mArchive.logGrantTrust(mUserId, mName,
|
||||
(mMessage != null ? mMessage.toString() : null),
|
||||
durationMs, flags);
|
||||
mTrustManagerService.updateTrust(mUserId, flags);
|
||||
mTrustManagerService.updateTrust(mUserId, flags, resultCallback);
|
||||
break;
|
||||
case MSG_TRUST_TIMEOUT:
|
||||
if (DEBUG) Slog.d(TAG, "Trust timed out : " + mName.flattenToShortString());
|
||||
@ -314,13 +320,18 @@ public class TrustAgentWrapper {
|
||||
private ITrustAgentServiceCallback mCallback = new ITrustAgentServiceCallback.Stub() {
|
||||
|
||||
@Override
|
||||
public void grantTrust(CharSequence message, long durationMs, int flags) {
|
||||
public void grantTrust(
|
||||
CharSequence message,
|
||||
long durationMs,
|
||||
int flags,
|
||||
AndroidFuture resultCallback) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "enableTrust(" + message + ", durationMs = " + durationMs
|
||||
+ ", flags = " + flags + ")");
|
||||
}
|
||||
|
||||
Message msg = mHandler.obtainMessage(MSG_GRANT_TRUST, flags, 0, message);
|
||||
Message msg = mHandler.obtainMessage(
|
||||
MSG_GRANT_TRUST, flags, 0, Pair.create(message, resultCallback));
|
||||
msg.getData().putLong(DATA_DURATION, durationMs);
|
||||
msg.sendToTarget();
|
||||
}
|
||||
@ -514,12 +525,23 @@ public class TrustAgentWrapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see android.service.trust.TrustAgentService#onUserRequestedUnlock()
|
||||
* @see android.service.trust.TrustAgentService#onUserRequestedUnlock(boolean)
|
||||
*/
|
||||
public void onUserRequestedUnlock() {
|
||||
public void onUserRequestedUnlock(boolean dismissKeyguard) {
|
||||
try {
|
||||
if (mTrustAgentService != null) {
|
||||
mTrustAgentService.onUserRequestedUnlock();
|
||||
mTrustAgentService.onUserRequestedUnlock(dismissKeyguard);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
onError(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** @see android.service.trust.TrustAgentService#onUserMayRequestUnlock() */
|
||||
public void onUserMayRequestUnlock() {
|
||||
try {
|
||||
if (mTrustAgentService != null) {
|
||||
mTrustAgentService.onUserMayRequestUnlock();
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
onError(e);
|
||||
|
@ -61,6 +61,7 @@ import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.security.Authorization;
|
||||
import android.service.trust.GrantTrustResult;
|
||||
import android.service.trust.TrustAgentService;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
@ -77,6 +78,7 @@ import android.view.WindowManagerGlobal;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.content.PackageMonitor;
|
||||
import com.android.internal.infra.AndroidFuture;
|
||||
import com.android.internal.util.DumpUtils;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.server.LocalServices;
|
||||
@ -131,6 +133,7 @@ public class TrustManagerService extends SystemService {
|
||||
private static final int MSG_SCHEDULE_TRUST_TIMEOUT = 15;
|
||||
private static final int MSG_USER_REQUESTED_UNLOCK = 16;
|
||||
private static final int MSG_REFRESH_TRUSTABLE_TIMERS_AFTER_AUTH = 17;
|
||||
private static final int MSG_USER_MAY_REQUEST_UNLOCK = 18;
|
||||
|
||||
private static final String REFRESH_DEVICE_LOCKED_EXCEPT_USER = "except";
|
||||
|
||||
@ -495,13 +498,28 @@ public class TrustManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
public void updateTrust(int userId, int flags) {
|
||||
updateTrust(userId, flags, false /* isFromUnlock */);
|
||||
/** Triggers a trust update. */
|
||||
public void updateTrust(
|
||||
int userId,
|
||||
int flags) {
|
||||
updateTrust(userId, flags, null);
|
||||
}
|
||||
|
||||
private void updateTrust(int userId, int flags, boolean isFromUnlock) {
|
||||
/** Triggers a trust update. */
|
||||
public void updateTrust(
|
||||
int userId,
|
||||
int flags,
|
||||
@Nullable AndroidFuture<GrantTrustResult> resultCallback) {
|
||||
updateTrust(userId, flags, false /* isFromUnlock */, resultCallback);
|
||||
}
|
||||
|
||||
private void updateTrust(
|
||||
int userId,
|
||||
int flags,
|
||||
boolean isFromUnlock,
|
||||
@Nullable AndroidFuture<GrantTrustResult> resultCallback) {
|
||||
if (ENABLE_ACTIVE_UNLOCK_FLAG) {
|
||||
updateTrustWithRenewableUnlock(userId, flags, isFromUnlock);
|
||||
updateTrustWithRenewableUnlock(userId, flags, isFromUnlock, resultCallback);
|
||||
} else {
|
||||
updateTrustWithNonrenewableTrust(userId, flags, isFromUnlock);
|
||||
}
|
||||
@ -553,7 +571,11 @@ public class TrustManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTrustWithRenewableUnlock(int userId, int flags, boolean isFromUnlock) {
|
||||
private void updateTrustWithRenewableUnlock(
|
||||
int userId,
|
||||
int flags,
|
||||
boolean isFromUnlock,
|
||||
@Nullable AndroidFuture<GrantTrustResult> resultCallback) {
|
||||
boolean managed = aggregateIsTrustManaged(userId);
|
||||
dispatchOnTrustManagedChanged(managed, userId);
|
||||
if (mStrongAuthTracker.isTrustAllowedForUser(userId)
|
||||
@ -614,8 +636,18 @@ public class TrustManagerService extends SystemService {
|
||||
isTrustableTimeout /* isTrustableTimeout */);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean wasLocked = !alreadyUnlocked;
|
||||
boolean shouldSendCallback = wasLocked && pendingTrustState == TrustState.TRUSTED;
|
||||
if (shouldSendCallback) {
|
||||
if (resultCallback != null) {
|
||||
if (DEBUG) Slog.d(TAG, "calling back with UNLOCKED_BY_GRANT");
|
||||
resultCallback.complete(
|
||||
GrantTrustResult.withStatus(
|
||||
GrantTrustResult.STATUS_UNLOCKED_BY_GRANT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTrustUsuallyManaged(int userId, boolean managed) {
|
||||
synchronized (mTrustUsuallyManagedForUser) {
|
||||
@ -1190,7 +1222,7 @@ public class TrustManagerService extends SystemService {
|
||||
if (successful) {
|
||||
mStrongAuthTracker.allowTrustFromUnlock(userId);
|
||||
// Allow the presence of trust on a successful unlock attempt to extend unlock
|
||||
updateTrust(userId, 0 /* flags */, true);
|
||||
updateTrust(userId, 0 /* flags */, true, null);
|
||||
mHandler.obtainMessage(MSG_REFRESH_TRUSTABLE_TIMERS_AFTER_AUTH, userId).sendToTarget();
|
||||
}
|
||||
|
||||
@ -1202,11 +1234,27 @@ public class TrustManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private void dispatchUserRequestedUnlock(int userId) {
|
||||
private void dispatchUserRequestedUnlock(int userId, boolean dismissKeyguard) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "dispatchUserRequestedUnlock(user=" + userId + ", dismissKeyguard="
|
||||
+ dismissKeyguard + ")");
|
||||
}
|
||||
for (int i = 0; i < mActiveAgents.size(); i++) {
|
||||
AgentInfo info = mActiveAgents.valueAt(i);
|
||||
if (info.userId == userId) {
|
||||
info.agent.onUserRequestedUnlock();
|
||||
info.agent.onUserRequestedUnlock(dismissKeyguard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void dispatchUserMayRequestUnlock(int userId) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "dispatchUserMayRequestUnlock(user=" + userId + ")");
|
||||
}
|
||||
for (int i = 0; i < mActiveAgents.size(); i++) {
|
||||
AgentInfo info = mActiveAgents.valueAt(i);
|
||||
if (info.userId == userId) {
|
||||
info.agent.onUserMayRequestUnlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1341,9 +1389,17 @@ public class TrustManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportUserRequestedUnlock(int userId) throws RemoteException {
|
||||
public void reportUserRequestedUnlock(int userId, boolean dismissKeyguard)
|
||||
throws RemoteException {
|
||||
enforceReportPermission();
|
||||
mHandler.obtainMessage(MSG_USER_REQUESTED_UNLOCK, userId).sendToTarget();
|
||||
mHandler.obtainMessage(MSG_USER_REQUESTED_UNLOCK, userId, dismissKeyguard ? 1 : 0)
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportUserMayRequestUnlock(int userId) throws RemoteException {
|
||||
enforceReportPermission();
|
||||
mHandler.obtainMessage(MSG_USER_MAY_REQUEST_UNLOCK, userId).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1683,7 +1739,10 @@ public class TrustManagerService extends SystemService {
|
||||
dispatchUnlockAttempt(msg.arg1 != 0, msg.arg2);
|
||||
break;
|
||||
case MSG_USER_REQUESTED_UNLOCK:
|
||||
dispatchUserRequestedUnlock(msg.arg1);
|
||||
dispatchUserRequestedUnlock(msg.arg1, msg.arg2 != 0);
|
||||
break;
|
||||
case MSG_USER_MAY_REQUEST_UNLOCK:
|
||||
dispatchUserMayRequestUnlock(msg.arg1);
|
||||
break;
|
||||
case MSG_DISPATCH_UNLOCK_LOCKOUT:
|
||||
dispatchUnlockLockout(msg.arg1, msg.arg2);
|
||||
@ -1725,7 +1784,7 @@ public class TrustManagerService extends SystemService {
|
||||
break;
|
||||
case MSG_REFRESH_DEVICE_LOCKED_FOR_USER:
|
||||
if (msg.arg2 == 1) {
|
||||
updateTrust(msg.arg1, 0 /* flags */, true /* isFromUnlock */);
|
||||
updateTrust(msg.arg1, 0 /* flags */, true /* isFromUnlock */, null);
|
||||
}
|
||||
final int unlockedUser = msg.getData().getInt(
|
||||
REFRESH_DEVICE_LOCKED_EXCEPT_USER, UserHandle.USER_NULL);
|
||||
|
@ -25,6 +25,8 @@ android_test {
|
||||
"androidx.test.rules",
|
||||
"androidx.test.ext.junit",
|
||||
"androidx.test.uiautomator",
|
||||
"mockito-target-minus-junit4",
|
||||
"servicestests-utils",
|
||||
"truth-prebuilt",
|
||||
],
|
||||
libs: [
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package android.trust.test
|
||||
|
||||
import android.service.trust.GrantTrustResult
|
||||
import android.trust.BaseTrustAgentService
|
||||
import android.trust.TrustTestActivity
|
||||
import android.trust.test.lib.LockStateTrackingRule
|
||||
@ -25,11 +26,13 @@ import androidx.test.ext.junit.rules.ActivityScenarioRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
|
||||
import androidx.test.uiautomator.UiDevice
|
||||
import com.android.server.testutils.mock
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.RuleChain
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mockito.verifyZeroInteractions
|
||||
|
||||
/**
|
||||
* Test for testing revokeTrust & grantTrust for non-renewable trust.
|
||||
@ -66,7 +69,7 @@ class GrantAndRevokeTrustTest {
|
||||
|
||||
@Test
|
||||
fun grantKeepsDeviceUnlocked() {
|
||||
trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 10000, 0)
|
||||
trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 10000, 0) {}
|
||||
uiDevice.sleep()
|
||||
|
||||
lockStateTrackingRule.assertUnlocked()
|
||||
@ -74,7 +77,7 @@ class GrantAndRevokeTrustTest {
|
||||
|
||||
@Test
|
||||
fun grantKeepsDeviceUnlocked_untilRevoked() {
|
||||
trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, 0)
|
||||
trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, 0) {}
|
||||
await()
|
||||
uiDevice.sleep()
|
||||
trustAgentRule.agent.revokeTrust()
|
||||
@ -82,6 +85,15 @@ class GrantAndRevokeTrustTest {
|
||||
lockStateTrackingRule.assertLocked()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun grantDoesNotCallBack() {
|
||||
val callback = mock<(GrantTrustResult) -> Unit>()
|
||||
trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, 0, callback)
|
||||
await()
|
||||
|
||||
verifyZeroInteractions(callback)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "GrantAndRevokeTrustTest"
|
||||
private const val GRANT_MESSAGE = "granted by test"
|
||||
|
@ -16,16 +16,20 @@
|
||||
|
||||
package android.trust.test
|
||||
|
||||
import android.service.trust.GrantTrustResult
|
||||
import android.service.trust.GrantTrustResult.STATUS_UNLOCKED_BY_GRANT
|
||||
import android.service.trust.TrustAgentService.FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE
|
||||
import android.trust.BaseTrustAgentService
|
||||
import android.trust.TrustTestActivity
|
||||
import android.trust.test.lib.LockStateTrackingRule
|
||||
import android.trust.test.lib.ScreenLockRule
|
||||
import android.trust.test.lib.TrustAgentRule
|
||||
import android.util.Log
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
|
||||
import androidx.test.uiautomator.UiDevice
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
@ -70,7 +74,8 @@ class TemporaryAndRenewableTrustTest {
|
||||
uiDevice.sleep()
|
||||
lockStateTrackingRule.assertLocked()
|
||||
|
||||
trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE)
|
||||
trustAgentRule.agent.grantTrust(
|
||||
GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) {}
|
||||
uiDevice.wakeUp()
|
||||
|
||||
lockStateTrackingRule.assertLocked()
|
||||
@ -78,7 +83,8 @@ class TemporaryAndRenewableTrustTest {
|
||||
|
||||
@Test
|
||||
fun grantTrustUnlockedDevice_deviceLocksOnScreenOff() {
|
||||
trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE)
|
||||
trustAgentRule.agent.grantTrust(
|
||||
GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) {}
|
||||
uiDevice.sleep()
|
||||
|
||||
lockStateTrackingRule.assertLocked()
|
||||
@ -86,20 +92,48 @@ class TemporaryAndRenewableTrustTest {
|
||||
|
||||
@Test
|
||||
fun grantTrustLockedDevice_grantTrustOnLockedDeviceUnlocksDevice() {
|
||||
trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE)
|
||||
trustAgentRule.agent.grantTrust(
|
||||
GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) {}
|
||||
uiDevice.sleep()
|
||||
|
||||
lockStateTrackingRule.assertLocked()
|
||||
|
||||
trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE)
|
||||
trustAgentRule.agent.grantTrust(
|
||||
GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) {}
|
||||
uiDevice.wakeUp()
|
||||
|
||||
lockStateTrackingRule.assertUnlocked()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun grantTrustLockedDevice_callsBackWhenUnlocked() {
|
||||
Log.i(TAG, "Granting renewable trust while unlocked")
|
||||
trustAgentRule.agent.grantTrust(
|
||||
GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) {}
|
||||
await(1000)
|
||||
|
||||
Log.i(TAG, "Locking device")
|
||||
uiDevice.sleep()
|
||||
|
||||
lockStateTrackingRule.assertLocked()
|
||||
|
||||
Log.i(TAG, "Renewing trust and unlocking")
|
||||
var result: GrantTrustResult? = null
|
||||
trustAgentRule.agent.grantTrust(
|
||||
GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) {
|
||||
Log.i(TAG, "Callback received; status=${it.status}")
|
||||
result = it
|
||||
}
|
||||
uiDevice.wakeUp()
|
||||
lockStateTrackingRule.assertUnlocked()
|
||||
|
||||
assertThat(result?.status).isEqualTo(STATUS_UNLOCKED_BY_GRANT)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun grantTrustLockedDevice_revokeTrustPreventsSubsequentUnlock() {
|
||||
trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE)
|
||||
trustAgentRule.agent.grantTrust(
|
||||
GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) {}
|
||||
uiDevice.sleep()
|
||||
|
||||
lockStateTrackingRule.assertLocked()
|
||||
@ -109,7 +143,8 @@ class TemporaryAndRenewableTrustTest {
|
||||
uiDevice.wakeUp()
|
||||
await(500)
|
||||
|
||||
trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE)
|
||||
trustAgentRule.agent.grantTrust(
|
||||
GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) {}
|
||||
|
||||
lockStateTrackingRule.assertLocked()
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ import org.junit.rules.RuleChain
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
/**
|
||||
* Test for testing the user unlock trigger.
|
||||
* Test for the user unlock triggers.
|
||||
*
|
||||
* atest TrustTests:UserUnlockRequestTest
|
||||
*/
|
||||
@ -53,13 +53,32 @@ class UserUnlockRequestTest {
|
||||
@Test
|
||||
fun reportUserRequestedUnlock_propagatesToAgent() {
|
||||
val oldCount = trustAgentRule.agent.onUserRequestedUnlockCallCount
|
||||
trustManager.reportUserRequestedUnlock(userId)
|
||||
trustManager.reportUserRequestedUnlock(userId, false)
|
||||
await()
|
||||
|
||||
assertThat(trustAgentRule.agent.onUserRequestedUnlockCallCount)
|
||||
.isEqualTo(oldCount + 1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun reportUserRequestedUnlock_propagatesToAgentWithDismissKeyguard() {
|
||||
trustManager.reportUserRequestedUnlock(userId, true)
|
||||
await()
|
||||
|
||||
assertThat(trustAgentRule.agent.lastCallDismissKeyguard)
|
||||
.isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun reportUserMayRequestUnlock_propagatesToAgent() {
|
||||
val oldCount = trustAgentRule.agent.onUserMayRequestUnlockCallCount
|
||||
trustManager.reportUserMayRequestUnlock(userId)
|
||||
await()
|
||||
|
||||
assertThat(trustAgentRule.agent.onUserMayRequestUnlockCallCount)
|
||||
.isEqualTo(oldCount + 1)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "UserUnlockRequestTest"
|
||||
private fun await() = Thread.sleep(250)
|
||||
@ -69,10 +88,20 @@ class UserUnlockRequestTest {
|
||||
class UserUnlockRequestTrustAgent : BaseTrustAgentService() {
|
||||
var onUserRequestedUnlockCallCount: Long = 0
|
||||
private set
|
||||
var onUserMayRequestUnlockCallCount: Long = 0
|
||||
private set
|
||||
var lastCallDismissKeyguard: Boolean = false
|
||||
private set
|
||||
|
||||
override fun onUserRequestedUnlock() {
|
||||
Log.i(TAG, "onUserRequestedUnlock")
|
||||
override fun onUserRequestedUnlock(dismissKeyguard: Boolean) {
|
||||
Log.i(TAG, "onUserRequestedUnlock($dismissKeyguard)")
|
||||
onUserRequestedUnlockCallCount++
|
||||
lastCallDismissKeyguard = dismissKeyguard
|
||||
}
|
||||
|
||||
override fun onUserMayRequestUnlock() {
|
||||
Log.i(TAG, "onUserMayRequestUnlock")
|
||||
onUserMayRequestUnlockCallCount++
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -56,12 +56,22 @@ class LockStateTrackingRule : TestRule {
|
||||
val maxWaits = 50
|
||||
var waitCount = 0
|
||||
|
||||
// First verify we get the call in LockState via TrustListener
|
||||
while ((lockState.locked == false) && waitCount < maxWaits) {
|
||||
Log.i(TAG, "phone still locked, wait 50ms more ($waitCount)")
|
||||
Log.i(TAG, "phone still unlocked (TrustListener), wait 50ms more ($waitCount)")
|
||||
Thread.sleep(50)
|
||||
waitCount++
|
||||
}
|
||||
assertThat(lockState.locked).isTrue()
|
||||
|
||||
// TODO(b/225231929): refactor checks into one loop and re-use for assertUnlocked
|
||||
// Then verify we get the window manager locked
|
||||
while (!windowManager.isKeyguardLocked && waitCount < maxWaits) {
|
||||
Log.i(TAG, "phone still unlocked (WindowManager), wait 50ms more ($waitCount)")
|
||||
Thread.sleep(50)
|
||||
waitCount++
|
||||
}
|
||||
assertThat(windowManager.isKeyguardLocked).isTrue()
|
||||
}
|
||||
|
||||
fun assertUnlocked() {
|
||||
|
@ -69,6 +69,17 @@ class ScreenLockRule : TestRule {
|
||||
while (windowManager.isKeyguardLocked && waitCount < maxWaits) {
|
||||
Log.i(TAG, "Keyguard still showing; attempting to dismiss and wait 50ms ($waitCount)")
|
||||
windowManager.dismissKeyguard(null, null)
|
||||
|
||||
// Sometimes, bouncer gets shown due to a race, so we have to put display to sleep
|
||||
// and wake it back up to get it to go away
|
||||
if (waitCount >= 10 && waitCount % 5 == 0) {
|
||||
Log.i(TAG, "Escalation: attempting screen off/on to get rid of bouncer (+500ms)")
|
||||
uiDevice.sleep()
|
||||
Thread.sleep(250)
|
||||
uiDevice.wakeUp()
|
||||
Thread.sleep(250)
|
||||
}
|
||||
|
||||
Thread.sleep(50)
|
||||
waitCount++
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user