diff options
6 files changed, 80 insertions, 22 deletions
diff --git a/core/java/android/app/admin/DevicePolicyKeyguardService.java b/core/java/android/app/admin/DevicePolicyKeyguardService.java index db833ec478bd..473725f40cf1 100644 --- a/core/java/android/app/admin/DevicePolicyKeyguardService.java +++ b/core/java/android/app/admin/DevicePolicyKeyguardService.java @@ -16,12 +16,15 @@ package android.app.admin; +import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.app.Service; import android.content.Intent; +import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.os.RemoteException; import android.util.Log; import android.view.SurfaceControlViewHost; @@ -41,27 +44,34 @@ import android.view.SurfaceControlViewHost; @SystemApi public class DevicePolicyKeyguardService extends Service { private static final String TAG = "DevicePolicyKeyguardService"; + private final Handler mHandler = new Handler(Looper.getMainLooper()); private IKeyguardCallback mCallback; private final IKeyguardClient mClient = new IKeyguardClient.Stub() { + @MainThread @Override public void onCreateKeyguardSurface(@Nullable IBinder hostInputToken, - IKeyguardCallback callback) { + @NonNull IKeyguardCallback callback) { mCallback = callback; - SurfaceControlViewHost.SurfacePackage surfacePackage = - DevicePolicyKeyguardService.this.onCreateKeyguardSurface(hostInputToken); + mHandler.post(() -> { + SurfaceControlViewHost.SurfacePackage surfacePackage = + DevicePolicyKeyguardService.this.onCreateKeyguardSurface(hostInputToken); - if (mCallback != null) { try { mCallback.onRemoteContentReady(surfacePackage); } catch (RemoteException e) { Log.e(TAG, "Failed to return created SurfacePackage", e); } - } + }); } }; @Override + public void onDestroy() { + mHandler.removeCallbacksAndMessages(null); + } + + @Override @Nullable public final IBinder onBind(@Nullable Intent intent) { return mClient.asBinder(); @@ -97,6 +107,10 @@ public class DevicePolicyKeyguardService extends Service { */ @Nullable public void dismiss() { + if (mCallback == null) { + Log.w(TAG, "KeyguardCallback was unexpectedly null"); + return; + } try { mCallback.onDismiss(); } catch (RemoteException e) { diff --git a/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java b/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java index 7eb5a8f2b06c..e99245fa438f 100644 --- a/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java +++ b/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java @@ -34,6 +34,8 @@ import android.view.ViewGroup; import com.android.internal.annotations.VisibleForTesting; +import java.util.NoSuchElementException; + /** * Encapsulates all logic for secondary lockscreen state management. */ @@ -79,7 +81,9 @@ public class AdminSecondaryLockScreenController { private final IKeyguardCallback mCallback = new IKeyguardCallback.Stub() { @Override public void onDismiss() { - dismiss(UserHandle.getCallingUserId()); + mHandler.post(() -> { + dismiss(UserHandle.getCallingUserId()); + }); } @Override @@ -91,7 +95,9 @@ public class AdminSecondaryLockScreenController { if (surfacePackage != null) { mView.setChildSurfacePackage(surfacePackage); } else { - dismiss(KeyguardUpdateMonitor.getCurrentUser()); + mHandler.post(() -> { + dismiss(KeyguardUpdateMonitor.getCurrentUser()); + }); } } }; @@ -122,6 +128,7 @@ public class AdminSecondaryLockScreenController { // If the remote content is not readied within the timeout period, // move on without the secondary lockscreen. dismiss(userId); + Log.w(TAG, "Timed out waiting for secondary lockscreen content."); }, REMOTE_CONTENT_READY_TIMEOUT_MILLIS); } @@ -150,8 +157,12 @@ public class AdminSecondaryLockScreenController { * Displays the Admin security Surface view. */ public void show(Intent serviceIntent) { - mContext.bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE); - mParent.addView(mView); + if (mClient == null) { + mContext.bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE); + } + if (!mView.isAttachedToWindow()) { + mParent.addView(mView); + } } /** @@ -162,7 +173,11 @@ public class AdminSecondaryLockScreenController { mParent.removeView(mView); } if (mClient != null) { - mClient.asBinder().unlinkToDeath(mKeyguardClientDeathRecipient, 0); + try { + mClient.asBinder().unlinkToDeath(mKeyguardClientDeathRecipient, 0); + } catch (NoSuchElementException e) { + Log.w(TAG, "IKeyguardClient death recipient already released"); + } mContext.unbindService(mConnection); mClient = null; } @@ -185,10 +200,12 @@ public class AdminSecondaryLockScreenController { private void dismiss(int userId) { mHandler.removeCallbacksAndMessages(null); - if (mView != null && mView.isAttachedToWindow() - && userId == KeyguardUpdateMonitor.getCurrentUser()) { + if (mView.isAttachedToWindow() && userId == KeyguardUpdateMonitor.getCurrentUser()) { hide(); - mKeyguardCallback.dismiss(true, userId); + if (mKeyguardCallback != null) { + mKeyguardCallback.dismiss(/* securityVerified= */ true, userId, + /* bypassSecondaryLockScreen= */true); + } } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java index d5a08dda9853..aa2fe3c7f8fc 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java @@ -85,7 +85,8 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback { // the user proved presence via some other way to the trust agent. Log.i(TAG, "TrustAgent dismissed Keyguard."); } - dismiss(false /* authenticated */, userId); + dismiss(false /* authenticated */, userId, + /* bypassSecondaryLockScreen */ false); } else { mViewMediatorCallback.playTrustedSound(); } @@ -190,7 +191,7 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback { * @return True if the keyguard is done. */ public boolean dismiss(int targetUserId) { - return dismiss(false, targetUserId); + return dismiss(false, targetUserId, false); } public boolean handleBackKey() { @@ -206,8 +207,10 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback { } @Override - public boolean dismiss(boolean authenticated, int targetUserId) { - return mSecurityContainer.showNextSecurityScreenOrFinish(authenticated, targetUserId); + public boolean dismiss(boolean authenticated, int targetUserId, + boolean bypassSecondaryLockScreen) { + return mSecurityContainer.showNextSecurityScreenOrFinish(authenticated, targetUserId, + bypassSecondaryLockScreen); } /** diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java index 49dcfffb0d72..e38472745234 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java @@ -25,6 +25,15 @@ public interface KeyguardSecurityCallback { void dismiss(boolean securityVerified, int targetUserId); /** + * Dismiss the given security screen. + * @param securityVerified true if the user correctly entered credentials for the given screen. + * @param targetUserId a user that needs to be the foreground user at the dismissal completion. + * @param bypassSecondaryLockScreen true if the user can bypass the secondary lock screen, + * if any, during this dismissal. + */ + void dismiss(boolean securityVerified, int targetUserId, boolean bypassSecondaryLockScreen); + + /** * Manually report user activity to keep the device awake. */ void userActivity(); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index ba8a1a945a77..1e1ce4e6d159 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -115,7 +115,8 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe // Used to notify the container when something interesting happens. public interface SecurityCallback { - public boolean dismiss(boolean authenticated, int targetUserId); + public boolean dismiss(boolean authenticated, int targetUserId, + boolean bypassSecondaryLockScreen); public void userActivity(); public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput); @@ -504,9 +505,12 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe * @param authenticated true if the user entered the correct authentication * @param targetUserId a user that needs to be the foreground user at the finish (if called) * completion. + * @param bypassSecondaryLockScreen true if the user is allowed to bypass the secondary + * secondary lock screen requirement, if any. * @return true if keyguard is done */ - boolean showNextSecurityScreenOrFinish(boolean authenticated, int targetUserId) { + boolean showNextSecurityScreenOrFinish(boolean authenticated, int targetUserId, + boolean bypassSecondaryLockScreen) { if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")"); boolean finish = false; boolean strongAuth = false; @@ -555,7 +559,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe } } // Check for device admin specified additional security measures. - if (finish) { + if (finish && !bypassSecondaryLockScreen) { Intent secondaryLockscreenIntent = mUpdateMonitor.getSecondaryLockscreenRequirement(targetUserId); if (secondaryLockscreenIntent != null) { @@ -636,8 +640,15 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe mUpdateMonitor.cancelFaceAuth(); } + @Override public void dismiss(boolean authenticated, int targetId) { - mSecurityCallback.dismiss(authenticated, targetId); + dismiss(authenticated, targetId, /* bypassSecondaryLockScreen */ false); + } + + @Override + public void dismiss(boolean authenticated, int targetId, + boolean bypassSecondaryLockScreen) { + mSecurityCallback.dismiss(authenticated, targetId, bypassSecondaryLockScreen); } public boolean isVerifyUnlockOnly() { @@ -689,6 +700,9 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe @Override public void dismiss(boolean securityVerified, int targetUserId) { } @Override + public void dismiss(boolean authenticated, int targetId, + boolean bypassSecondaryLockScreen) { } + @Override public void onUserInput() { } @Override public void reset() {} diff --git a/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java index cf1299fc66e0..ce032c94deab 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java @@ -115,6 +115,7 @@ public class AdminSecondaryLockScreenControllerTest extends SysuiTestCase { @Test public void testShow_dismissedByCallback() throws Exception { + doAnswer(answerVoid(Runnable::run)).when(mHandler).post(any(Runnable.class)); doAnswer(invocation -> { IKeyguardCallback callback = (IKeyguardCallback) invocation.getArguments()[1]; callback.onDismiss(); @@ -184,7 +185,7 @@ public class AdminSecondaryLockScreenControllerTest extends SysuiTestCase { private void verifyViewDismissed(SurfaceView v) throws Exception { verify(mParent).removeView(v); - verify(mKeyguardCallback).dismiss(true, TARGET_USER_ID); + verify(mKeyguardCallback).dismiss(true, TARGET_USER_ID, true); assertThat(mContext.isBound(mComponentName)).isFalse(); } } |