diff options
Diffstat (limited to 'packages/SystemUI/src/com')
29 files changed, 440 insertions, 490 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt deleted file mode 100644 index 0785cc3c04d2..000000000000 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.android.keyguard - -import android.annotation.CurrentTimeMillisLong - -/** - * Data class for tracking information associated with [KeyguardUpdateMonitor.shouldListenForFace] - * method calls. - */ -data class KeyguardFaceListenModel( - @CurrentTimeMillisLong val timeMillis: Long, - val userId: Int, - val isListeningForFace: Boolean, - val isBouncer: Boolean, - val isAuthInterruptActive: Boolean, - val isOccludingAppRequestingFaceAuth: Boolean, - val isKeyguardAwake: Boolean, - val isListeningForFaceAssistant: Boolean, - val isSwitchingUser: Boolean, - val isFaceDisabled: Boolean, - val isBecauseCannotSkipBouncer: Boolean, - val isKeyguardGoingAway: Boolean, - val isBiometricSettingEnabledForUser: Boolean, - val isLockIconPressed: Boolean, - val isScanningAllowedByStrongAuth: Boolean, - val isPrimaryUser: Boolean, - val isSecureCameraLaunched: Boolean, - val isFaceAuthenticated: Boolean -) diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt new file mode 100644 index 000000000000..9286175cc2ea --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt @@ -0,0 +1,77 @@ +package com.android.keyguard + +import android.annotation.CurrentTimeMillisLong +import android.hardware.biometrics.BiometricAuthenticator.Modality +import android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE +import android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT + +/** Verbose logging for various keyguard listening states. */ +sealed class KeyguardListenModel { + /** Timestamp of the state change. */ + abstract val timeMillis: Long + /** Current user */ + abstract val userId: Int + /** If keyguard is listening for the given [modality]. */ + abstract val listening: Boolean + /** Sensor type */ + @Modality abstract val modality: Int +} + +/** + * Verbose debug information associated with [KeyguardUpdateMonitor.shouldListenForFingerprint]. + */ +data class KeyguardFingerprintListenModel( + @CurrentTimeMillisLong override val timeMillis: Long, + override val userId: Int, + override val listening: Boolean, + // keep sorted + val biometricEnabledForUser: Boolean, + val bouncer: Boolean, + val canSkipBouncer: Boolean, + val credentialAttempted: Boolean, + val deviceInteractive: Boolean, + val dreaming: Boolean, + val encryptedOrLockdown: Boolean, + val fingerprintDisabled: Boolean, + val fingerprintLockedOut: Boolean, + val goingToSleep: Boolean, + val keyguardGoingAway: Boolean, + val keyguardIsVisible: Boolean, + val keyguardOccluded: Boolean, + val occludingAppRequestingFp: Boolean, + val primaryUser: Boolean, + val shouldListenForFingerprintAssistant: Boolean, + val switchingUser: Boolean, + val udfps: Boolean, + val userDoesNotHaveTrust: Boolean, + val userNeedsStrongAuth: Boolean +) : KeyguardListenModel() { + override val modality: Int = TYPE_FACE +} + +/** + * Verbose debug information associated with [KeyguardUpdateMonitor.shouldListenForFace]. + */ +data class KeyguardFaceListenModel( + @CurrentTimeMillisLong override val timeMillis: Long, + override val userId: Int, + override val listening: Boolean, + // keep sorted + val authInterruptActive: Boolean, + val becauseCannotSkipBouncer: Boolean, + val biometricSettingEnabledForUser: Boolean, + val bouncer: Boolean, + val faceAuthenticated: Boolean, + val faceDisabled: Boolean, + val keyguardAwake: Boolean, + val keyguardGoingAway: Boolean, + val listeningForFaceAssistant: Boolean, + val lockIconPressed: Boolean, + val occludingAppRequestingFaceAuth: Boolean, + val primaryUser: Boolean, + val scanningAllowedByStrongAuth: Boolean, + val secureCameraLaunched: Boolean, + val switchingUser: Boolean +) : KeyguardListenModel() { + override val modality: Int = TYPE_FINGERPRINT +} diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt new file mode 100644 index 000000000000..f13a59a84811 --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2021 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 com.android.keyguard + +import androidx.annotation.VisibleForTesting +import java.io.PrintWriter +import java.text.DateFormat +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale +import kotlin.collections.ArrayDeque + +private val DEFAULT_FORMATTING = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US) + +/** Queue for verbose logging checks for the listening state. */ +class KeyguardListenQueue( + val sizePerModality: Int = 20 +) { + private val faceQueue = ArrayDeque<KeyguardFaceListenModel>() + private val fingerprintQueue = ArrayDeque<KeyguardFingerprintListenModel>() + + @get:VisibleForTesting val models: List<KeyguardListenModel> + get() = faceQueue + fingerprintQueue + + /** Push a [model] to the queue (will be logged until the queue exceeds [sizePerModality]). */ + fun add(model: KeyguardListenModel) { + val queue = when (model) { + is KeyguardFaceListenModel -> faceQueue.apply { add(model) } + is KeyguardFingerprintListenModel -> fingerprintQueue.apply { add(model) } + } + + if (queue.size > sizePerModality) { + queue.removeFirstOrNull() + } + } + + /** Print verbose logs via the [writer]. */ + @JvmOverloads + fun print(writer: PrintWriter, dateFormat: DateFormat = DEFAULT_FORMATTING) { + val stringify: (KeyguardListenModel) -> String = { model -> + " ${dateFormat.format(Date(model.timeMillis))} $model" + } + + writer.println(" Face listen results (last ${faceQueue.size} calls):") + for (model in faceQueue) { + writer.println(stringify(model)) + } + writer.println(" Fingerprint listen results (last ${fingerprintQueue.size} calls):") + for (model in fingerprintQueue) { + writer.println(stringify(model)) + } + } +} diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 9e390e6bd3f4..1f4faf1a3d31 100755 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -119,13 +119,9 @@ import com.google.android.collect.Lists; import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.ref.WeakReference; -import java.text.SimpleDateFormat; -import java.util.ArrayDeque; import java.util.ArrayList; -import java.util.Date; import java.util.HashMap; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.TimeZone; @@ -146,6 +142,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private static final boolean DEBUG = KeyguardConstants.DEBUG; private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES; private static final boolean DEBUG_FACE = Build.IS_DEBUGGABLE; + private static final boolean DEBUG_FINGERPRINT = Build.IS_DEBUGGABLE; private static final boolean DEBUG_SPEW = false; private static final int FINGERPRINT_LOCKOUT_RESET_DELAY_MS = 600; @@ -345,13 +342,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private static final int HAL_ERROR_RETRY_TIMEOUT = 500; // ms private static final int HAL_ERROR_RETRY_MAX = 20; - private final Runnable mCancelNotReceived = new Runnable() { - @Override - public void run() { - Log.w(TAG, "Cancel not received, transitioning to STOPPED"); - mFingerprintRunningState = mFaceRunningState = BIOMETRIC_STATE_STOPPED; - updateBiometricListeningState(); - } + private final Runnable mFpCancelNotReceived = () -> { + Log.e(TAG, "Fp cancellation not received, transitioning to STOPPED"); + mFingerprintRunningState = BIOMETRIC_STATE_STOPPED; + updateFingerprintListeningState(); + }; + + private final Runnable mFaceCancelNotReceived = () -> { + Log.e(TAG, "Face cancellation not received, transitioning to STOPPED"); + mFaceRunningState = BIOMETRIC_STATE_STOPPED; + updateFaceListeningState(); }; private final Handler mHandler; @@ -417,9 +417,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @VisibleForTesting SparseArray<BiometricAuthenticated> mUserFaceAuthenticated = new SparseArray<>(); - // Keep track of recent calls to shouldListenForFace() for debugging. - private static final int FACE_LISTEN_CALLS_QUEUE_SIZE = 20; - private ArrayDeque<KeyguardFaceListenModel> mFaceListenModels; + // Keep track of recent calls to shouldListenFor*() for debugging. + private final KeyguardListenQueue mListenModels = new KeyguardListenQueue(); private static int sCurrentUser; private Runnable mUpdateBiometricListeningState = this::updateBiometricListeningState; @@ -769,19 +768,19 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private void handleFingerprintError(int msgId, String errString) { Assert.isMainThread(); - if (msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED && mHandler.hasCallbacks( - mCancelNotReceived)) { - mHandler.removeCallbacks(mCancelNotReceived); + if (mHandler.hasCallbacks(mFpCancelNotReceived)) { + mHandler.removeCallbacks(mFpCancelNotReceived); } + // Error is always the end of authentication lifecycle. + mFingerprintCancelSignal = null; + if (msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED && mFingerprintRunningState == BIOMETRIC_STATE_CANCELLING_RESTARTING) { setFingerprintRunningState(BIOMETRIC_STATE_STOPPED); updateFingerprintListeningState(); } else { setFingerprintRunningState(BIOMETRIC_STATE_STOPPED); - mFingerprintCancelSignal = null; - mFaceCancelSignal = null; } if (msgId == FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE) { @@ -883,6 +882,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private void handleFaceAuthFailed() { Assert.isMainThread(); + mFaceCancelSignal = null; setFaceRunningState(BIOMETRIC_STATE_STOPPED); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); @@ -961,10 +961,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private void handleFaceError(int msgId, String errString) { Assert.isMainThread(); if (DEBUG_FACE) Log.d(TAG, "Face error received: " + errString); - if (msgId == FaceManager.FACE_ERROR_CANCELED && mHandler.hasCallbacks(mCancelNotReceived)) { - mHandler.removeCallbacks(mCancelNotReceived); + if (mHandler.hasCallbacks(mFaceCancelNotReceived)) { + mHandler.removeCallbacks(mFaceCancelNotReceived); } + // Error is always the end of authentication lifecycle + mFaceCancelSignal = null; + if (msgId == FaceManager.FACE_ERROR_CANCELED && mFaceRunningState == BIOMETRIC_STATE_CANCELLING_RESTARTING) { setFaceRunningState(BIOMETRIC_STATE_STOPPED); @@ -2201,37 +2204,75 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @VisibleForTesting protected boolean shouldListenForFingerprint(boolean isUdfps) { - final boolean userDoesNotHaveTrust = !getUserHasTrust(getCurrentUser()); + final int user = getCurrentUser(); + final boolean userDoesNotHaveTrust = !getUserHasTrust(user); + final boolean shouldListenForFingerprintAssistant = shouldListenForFingerprintAssistant(); final boolean shouldListenKeyguardState = mKeyguardIsVisible || !mDeviceInteractive || (mBouncer && !mKeyguardGoingAway) || mGoingToSleep - || shouldListenForFingerprintAssistant() + || shouldListenForFingerprintAssistant || (mKeyguardOccluded && mIsDreaming) || (mKeyguardOccluded && userDoesNotHaveTrust && (mOccludingAppRequestingFp || isUdfps)); // Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an // instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware. + final boolean biometricEnabledForUser = mBiometricEnabledForUser.get(user); + final boolean userCanSkipBouncer = getUserCanSkipBouncer(user); + final boolean fingerprintDisabledForUser = isFingerprintDisabled(user); final boolean shouldListenUserState = !mSwitchingUser - && !isFingerprintDisabled(getCurrentUser()) + && !fingerprintDisabledForUser && (!mKeyguardGoingAway || !mDeviceInteractive) && mIsPrimaryUser - && mBiometricEnabledForUser.get(getCurrentUser()); + && biometricEnabledForUser; final boolean shouldListenBouncerState = !(mFingerprintLockedOut && mBouncer && mCredentialAttempted); + final boolean isEncryptedOrLockdownForUser = isEncryptedOrLockdown(user); + final boolean userNeedsStrongAuth = userNeedsStrongAuth(); final boolean shouldListenUdfpsState = !isUdfps - || (!getUserCanSkipBouncer(getCurrentUser()) - && !isEncryptedOrLockdown(getCurrentUser()) - && !userNeedsStrongAuth() + || (!userCanSkipBouncer + && !isEncryptedOrLockdownForUser + && !userNeedsStrongAuth && userDoesNotHaveTrust && !mFingerprintLockedOut); - return shouldListenKeyguardState && shouldListenUserState && shouldListenBouncerState - && shouldListenUdfpsState; + + final boolean shouldListen = shouldListenKeyguardState && shouldListenUserState + && shouldListenBouncerState && shouldListenUdfpsState; + + if (DEBUG_FINGERPRINT || DEBUG_SPEW) { + maybeLogListenerModelData( + new KeyguardFingerprintListenModel( + System.currentTimeMillis(), + user, + shouldListen, + biometricEnabledForUser, + mBouncer, + userCanSkipBouncer, + mCredentialAttempted, + mDeviceInteractive, + mIsDreaming, + isEncryptedOrLockdownForUser, + fingerprintDisabledForUser, + mFingerprintLockedOut, + mGoingToSleep, + mKeyguardGoingAway, + mKeyguardIsVisible, + mKeyguardOccluded, + mOccludingAppRequestingFp, + mIsPrimaryUser, + shouldListenForFingerprintAssistant, + mSwitchingUser, + isUdfps, + userDoesNotHaveTrust, + userNeedsStrongAuth)); + } + + return shouldListen; } /** @@ -2255,12 +2296,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT) || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_TIMEOUT); - boolean canBypass = mKeyguardBypassController != null + final boolean canBypass = mKeyguardBypassController != null && mKeyguardBypassController.canBypass(); // There's no reason to ask the HAL for authentication when the user can dismiss the // bouncer, unless we're bypassing and need to auto-dismiss the lock screen even when // TrustAgents or biometrics are keeping the device unlocked. - boolean becauseCannotSkipBouncer = !getUserCanSkipBouncer(user) || canBypass; + final boolean becauseCannotSkipBouncer = !getUserCanSkipBouncer(user) || canBypass; // Scan even when encrypted or timeout to show a preemptive bouncer when bypassing. // Lock-down mode shouldn't scan, since it is more explicit. @@ -2268,69 +2309,72 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab // If the device supports face detection (without authentication), allow it to happen // if the device is in lockdown mode. Otherwise, prevent scanning. - boolean supportsDetectOnly = !mFaceSensorProperties.isEmpty() + final boolean supportsDetectOnly = !mFaceSensorProperties.isEmpty() && mFaceSensorProperties.get(0).supportsFaceDetection; if (isLockDown && !supportsDetectOnly) { strongAuthAllowsScanning = false; } // If the face has recently been authenticated do not attempt to authenticate again. - boolean faceAuthenticated = getIsFaceAuthenticated(); + final boolean faceAuthenticated = getIsFaceAuthenticated(); + final boolean faceDisabledForUser = isFaceDisabled(user); + final boolean biometricEnabledForUser = mBiometricEnabledForUser.get(user); + final boolean shouldListenForFaceAssistant = shouldListenForFaceAssistant(); // Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an // instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware. final boolean shouldListen = (mBouncer || mAuthInterruptActive || mOccludingAppRequestingFace || awakeKeyguard - || shouldListenForFaceAssistant()) - && !mSwitchingUser && !isFaceDisabled(user) && becauseCannotSkipBouncer - && !mKeyguardGoingAway && mBiometricEnabledForUser.get(user) && !mLockIconPressed + || shouldListenForFaceAssistant) + && !mSwitchingUser && !faceDisabledForUser && becauseCannotSkipBouncer + && !mKeyguardGoingAway && biometricEnabledForUser && !mLockIconPressed && strongAuthAllowsScanning && mIsPrimaryUser && (!mSecureCameraLaunched || mOccludingAppRequestingFace) && !faceAuthenticated; // Aggregate relevant fields for debug logging. if (DEBUG_FACE || DEBUG_SPEW) { - final KeyguardFaceListenModel model = new KeyguardFaceListenModel( - System.currentTimeMillis(), - user, - shouldListen, - mBouncer, - mAuthInterruptActive, - mOccludingAppRequestingFace, - awakeKeyguard, - shouldListenForFaceAssistant(), - mSwitchingUser, - isFaceDisabled(user), - becauseCannotSkipBouncer, - mKeyguardGoingAway, - mBiometricEnabledForUser.get(user), - mLockIconPressed, - strongAuthAllowsScanning, - mIsPrimaryUser, - mSecureCameraLaunched, - faceAuthenticated); - maybeLogFaceListenerModelData(model); + maybeLogListenerModelData( + new KeyguardFaceListenModel( + System.currentTimeMillis(), + user, + shouldListen, + mAuthInterruptActive, + becauseCannotSkipBouncer, + biometricEnabledForUser, + mBouncer, + faceAuthenticated, + faceDisabledForUser, + awakeKeyguard, + mKeyguardGoingAway, + shouldListenForFaceAssistant, + mLockIconPressed, + mOccludingAppRequestingFace, + mIsPrimaryUser, + strongAuthAllowsScanning, + mSecureCameraLaunched, + mSwitchingUser)); } return shouldListen; } - private void maybeLogFaceListenerModelData(KeyguardFaceListenModel model) { + private void maybeLogListenerModelData(KeyguardListenModel model) { // Too chatty, but very useful when debugging issues. if (DEBUG_SPEW) { Log.v(TAG, model.toString()); } // Add model data to the historical buffer. - if (DEBUG_FACE && mFaceRunningState != BIOMETRIC_STATE_RUNNING - && model.isListeningForFace()) { - if (mFaceListenModels == null) { - mFaceListenModels = new ArrayDeque<>(FACE_LISTEN_CALLS_QUEUE_SIZE); - } - if (mFaceListenModels.size() >= FACE_LISTEN_CALLS_QUEUE_SIZE) { - mFaceListenModels.remove(); - } - mFaceListenModels.add(model); + final boolean notYetRunning = + (DEBUG_FACE + && model instanceof KeyguardFaceListenModel + && mFaceRunningState != BIOMETRIC_STATE_RUNNING) + || (DEBUG_FINGERPRINT + && model instanceof KeyguardFingerprintListenModel + && mFingerprintRunningState != BIOMETRIC_STATE_RUNNING); + if (notYetRunning && model.getListening()) { + mListenModels.add(model); } } @@ -2347,6 +2391,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } private void startListeningForFingerprint() { + final int userId = getCurrentUser(); + final boolean unlockPossible = isUnlockWithFingerprintPossible(userId); + if (mFingerprintCancelSignal != null) { + Log.e(TAG, "Cancellation signal is not null, high chance of bug in fp auth lifecycle" + + " management. FP state: " + mFingerprintRunningState + + ", unlockPossible: " + unlockPossible); + } + if (mFingerprintRunningState == BIOMETRIC_STATE_CANCELLING) { setFingerprintRunningState(BIOMETRIC_STATE_CANCELLING_RESTARTING); return; @@ -2356,11 +2408,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab return; } if (DEBUG) Log.v(TAG, "startListeningForFingerprint()"); - int userId = getCurrentUser(); - if (isUnlockWithFingerprintPossible(userId)) { - if (mFingerprintCancelSignal != null) { - mFingerprintCancelSignal.cancel(); - } + + if (unlockPossible) { mFingerprintCancelSignal = new CancellationSignal(); if (isEncryptedOrLockdown(userId)) { @@ -2376,6 +2425,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } private void startListeningForFace() { + final int userId = getCurrentUser(); + final boolean unlockPossible = isUnlockWithFacePossible(userId); + if (mFaceCancelSignal != null) { + Log.e(TAG, "Cancellation signal is not null, high chance of bug in face auth lifecycle" + + " management. Face state: " + mFaceRunningState + + ", unlockPossible: " + unlockPossible); + } + if (mFaceRunningState == BIOMETRIC_STATE_CANCELLING) { setFaceRunningState(BIOMETRIC_STATE_CANCELLING_RESTARTING); return; @@ -2384,11 +2441,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab return; } if (DEBUG) Log.v(TAG, "startListeningForFace(): " + mFaceRunningState); - int userId = getCurrentUser(); - if (isUnlockWithFacePossible(userId)) { - if (mFaceCancelSignal != null) { - mFaceCancelSignal.cancel(); - } + + if (unlockPossible) { mFaceCancelSignal = new CancellationSignal(); // This would need to be updated for multi-sensor devices @@ -2440,9 +2494,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab if (mFingerprintCancelSignal != null) { mFingerprintCancelSignal.cancel(); mFingerprintCancelSignal = null; - if (!mHandler.hasCallbacks(mCancelNotReceived)) { - mHandler.postDelayed(mCancelNotReceived, DEFAULT_CANCEL_SIGNAL_TIMEOUT); - } + mHandler.removeCallbacks(mFpCancelNotReceived); + mHandler.postDelayed(mFpCancelNotReceived, DEFAULT_CANCEL_SIGNAL_TIMEOUT); } setFingerprintRunningState(BIOMETRIC_STATE_CANCELLING); } @@ -2457,9 +2510,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab if (mFaceCancelSignal != null) { mFaceCancelSignal.cancel(); mFaceCancelSignal = null; - if (!mHandler.hasCallbacks(mCancelNotReceived)) { - mHandler.postDelayed(mCancelNotReceived, DEFAULT_CANCEL_SIGNAL_TIMEOUT); - } + mHandler.removeCallbacks(mFaceCancelNotReceived); + mHandler.postDelayed(mFaceCancelNotReceived, DEFAULT_CANCEL_SIGNAL_TIMEOUT); } setFaceRunningState(BIOMETRIC_STATE_CANCELLING); } @@ -2837,6 +2889,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mSecureCameraLaunched = false; } + if (mKeyguardBypassController != null) { + // LS visibility has changed, so reset deviceEntryIntent + mKeyguardBypassController.setUserHasDeviceEntryIntent(false); + } + for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -3465,15 +3522,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab pw.println(" enabledByUser=" + mBiometricEnabledForUser.get(userId)); pw.println(" mSecureCameraLaunched=" + mSecureCameraLaunched); } - if (mFaceListenModels != null && !mFaceListenModels.isEmpty()) { - final SimpleDateFormat dateFormat = - new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US); - pw.println(" Face listen results (last " + FACE_LISTEN_CALLS_QUEUE_SIZE + " calls):"); - for (final KeyguardFaceListenModel model : mFaceListenModels) { - final String time = dateFormat.format(new Date(model.getTimeMillis())); - pw.println(" " + time + " " + model.toString()); - } - } + mListenModels.print(pw); + if (mIsAutomotive) { pw.println(" Running on Automotive build"); } diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java index 4317e258d8f7..509ac8a6d9fe 100644 --- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java @@ -514,7 +514,15 @@ public class LockIconViewController extends ViewController<LockIconView> impleme if (!wasClickableOnDownEvent()) { return false; } + onAffordanceClick(); + return true; + } + public boolean onFling(MotionEvent e1, MotionEvent e2, + float velocityX, float velocityY) { + if (!wasClickableOnDownEvent()) { + return false; + } onAffordanceClick(); return true; } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java index 98ad87506819..ae3e94b9a1cb 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java @@ -44,11 +44,17 @@ public class AuthBiometricFaceToFingerprintView extends AuthBiometricFaceView { private static final String TAG = "BiometricPrompt/AuthBiometricFaceToFingerprintView"; protected static class UdfpsIconController extends IconController { + @BiometricState private int mIconState = STATE_IDLE; + protected UdfpsIconController( @NonNull Context context, @NonNull ImageView iconView, @NonNull TextView textView) { super(context, iconView, textView); } + void updateState(@BiometricState int newState) { + updateState(mIconState, newState); + } + @Override protected void updateState(int lastState, int newState) { final boolean lastStateIsErrorIcon = @@ -86,6 +92,7 @@ public class AuthBiometricFaceToFingerprintView extends AuthBiometricFaceView { } mState = newState; + mIconState = newState; } } @@ -191,11 +198,11 @@ public class AuthBiometricFaceToFingerprintView extends AuthBiometricFaceView { // Deactivate the face icon controller so it stops drawing to the view mFaceIconController.deactivate(); - // Then, activate this icon controller. We need to start in the "error" state - mUdfpsIconController.updateState(mState, newState); + // Then, activate this icon controller. We need to start in the "idle" state + mUdfpsIconController.updateState(STATE_IDLE); } } else { // Fingerprint - mUdfpsIconController.updateState(mState, newState); + mUdfpsIconController.updateState(newState); } super.updateState(newState); diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java index d122610c395d..d46426a03621 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java @@ -23,7 +23,6 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; -import android.animation.ValueAnimator; import android.content.Context; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; @@ -68,8 +67,6 @@ public class UdfpsKeyguardView extends UdfpsAnimationView { private float mBurnInProgress; private float mInterpolatedDarkAmount; - private ValueAnimator mHintAnimator; - public UdfpsKeyguardView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); mFingerprintDrawable = new UdfpsFpDrawable(context); @@ -94,9 +91,6 @@ public class UdfpsKeyguardView extends UdfpsAnimationView { new KeyPath("**"), LottieProperty.COLOR_FILTER, frameInfo -> new PorterDuffColorFilter(mTextColorPrimary, PorterDuff.Mode.SRC_ATOP) ); - - mHintAnimator = ObjectAnimator.ofFloat(mLockScreenFp, "progress", 1f, 0f, 1f); - mHintAnimator.setDuration(4000); } @Override @@ -183,19 +177,11 @@ public class UdfpsKeyguardView extends UdfpsAnimationView { } void onDozeAmountChanged(float linear, float eased) { - mHintAnimator.cancel(); mInterpolatedDarkAmount = eased; updateAlpha(); updateBurnInOffsets(); } - void animateHint() { - if (!isShadeLocked() && !mUdfpsRequested && mAlpha == 255 - && mLockScreenFp.isVisibleToUser()) { - mHintAnimator.start(); - } - } - /** * Animates in the bg protection circle behind the fp icon to highlight the icon. */ diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java index 58f1254da563..4896305daa2e 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java @@ -20,14 +20,10 @@ import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import android.annotation.NonNull; import android.content.res.Configuration; -import android.hardware.biometrics.BiometricSourceType; import android.util.MathUtils; import android.view.MotionEvent; -import androidx.annotation.Nullable; - import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.R; import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.KeyguardViewMediator; @@ -46,14 +42,8 @@ import java.io.PrintWriter; /** * Class that coordinates non-HBM animations during keyguard authentication. - * - * Highlights the udfps icon when: - * - Face authentication has failed - * - Face authentication has been run for > 2 seconds */ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<UdfpsKeyguardView> { - private static final long AFTER_FACE_AUTH_HINT_DELAY = 2000; - @NonNull private final StatusBarKeyguardViewManager mKeyguardViewManager; @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; @NonNull private final DelayableExecutor mExecutor; @@ -62,12 +52,10 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud @NonNull private final ConfigurationController mConfigurationController; @NonNull private final UdfpsController mUdfpsController; - @Nullable private Runnable mCancelDelayedHintRunnable; private boolean mShowingUdfpsBouncer; private boolean mUdfpsRequested; private boolean mQsExpanded; private boolean mFaceDetectRunning; - private boolean mHintShown; private int mStatusBarState; private float mTransitionToFullShadeProgress; private float mLastDozeAmount; @@ -110,10 +98,6 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud @Override protected void onViewAttached() { super.onViewAttached(); - mHintShown = false; - mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback); - updateFaceDetectRunning(mKeyguardUpdateMonitor.isFaceDetectionRunning()); - final float dozeAmount = mStatusBarStateController.getDozeAmount(); mLastDozeAmount = dozeAmount; mStateListener.onDozeAmountChanged(dozeAmount, dozeAmount); @@ -136,7 +120,6 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud @Override protected void onViewDetached() { super.onViewDetached(); - mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback); mFaceDetectRunning = false; mStatusBarStateController.removeCallback(mStateListener); @@ -146,11 +129,6 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud if (mLockScreenShadeTransitionController.getUdfpsKeyguardViewController() == this) { mLockScreenShadeTransitionController.setUdfpsKeyguardViewController(null); } - - if (mCancelDelayedHintRunnable != null) { - mCancelDelayedHintRunnable.run(); - mCancelDelayedHintRunnable = null; - } } @Override @@ -249,36 +227,6 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud } } - private void cancelDelayedHint() { - if (mCancelDelayedHintRunnable != null) { - mCancelDelayedHintRunnable.run(); - mCancelDelayedHintRunnable = null; - } - } - - private void updateFaceDetectRunning(boolean running) { - if (mFaceDetectRunning == running) { - return; - } - - // show udfps hint a few seconds after face auth started running - if (!mFaceDetectRunning && running && !mHintShown && mCancelDelayedHintRunnable == null) { - // Face detect started running, show udfps hint after a delay - mCancelDelayedHintRunnable = mExecutor.executeDelayed(() -> showHint(false), - AFTER_FACE_AUTH_HINT_DELAY); - } - - mFaceDetectRunning = running; - } - - private void showHint(boolean forceShow) { - cancelDelayedHint(); - if (!mHintShown || forceShow) { - mHintShown = true; - mView.animateHint(); - } - } - /** * Set the progress we're currently transitioning to the full shade. 0.0f means we're not * transitioning yet, while 1.0f means we've fully dragged down. @@ -318,39 +266,6 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud } }; - private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback = - new KeyguardUpdateMonitorCallback() { - public void onBiometricRunningStateChanged(boolean running, - BiometricSourceType biometricSourceType) { - if (biometricSourceType == BiometricSourceType.FACE) { - updateFaceDetectRunning(running); - } - } - - public void onBiometricAuthFailed(BiometricSourceType biometricSourceType) { - if (biometricSourceType == BiometricSourceType.FACE) { - // show udfps hint when face auth fails - showHint(true); - } - } - - public void onBiometricError(int msgId, String errString, - BiometricSourceType biometricSourceType) { - if (biometricSourceType == BiometricSourceType.FACE) { - // show udfps hint when face auth fails - showHint(true); - } - } - - public void onBiometricAuthenticated(int userId, - BiometricSourceType biometricSourceType, boolean isStrongBiometric) { - if (biometricSourceType == BiometricSourceType.FACE) { - // cancel delayed hint if face auth succeeded - cancelDelayedHint(); - } - } - }; - private final StatusBarKeyguardViewManager.AlternateAuthInterceptor mAlternateAuthInterceptor = new StatusBarKeyguardViewManager.AlternateAuthInterceptor() { @Override diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java index 23c44131ab60..b2db86f16104 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java @@ -115,6 +115,7 @@ public class DozeSensors { mSecureSettings = secureSettings; mCallback = callback; mProximitySensor = proximitySensor; + mProximitySensor.setTag(TAG); mSelectivelyRegisterProxSensors = dozeParameters.getSelectivelyRegisterSensorsUsingProx(); mListeningProxSensors = !mSelectivelyRegisterProxSensors; mScreenOffUdfpsEnabled = diff --git a/packages/SystemUI/src/com/android/systemui/doze/util/BurnInHelper.kt b/packages/SystemUI/src/com/android/systemui/doze/util/BurnInHelper.kt index 15e3f3a6b1e9..5c6478ed0895 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/util/BurnInHelper.kt +++ b/packages/SystemUI/src/com/android/systemui/doze/util/BurnInHelper.kt @@ -21,8 +21,8 @@ import android.util.MathUtils private const val MILLIS_PER_MINUTES = 1000 * 60f private const val BURN_IN_PREVENTION_PERIOD_Y = 521f private const val BURN_IN_PREVENTION_PERIOD_X = 83f -private const val BURN_IN_PREVENTION_PERIOD_SCALE = 180f -private const val BURN_IN_PREVENTION_PERIOD_PROGRESS = 120f +private const val BURN_IN_PREVENTION_PERIOD_SCALE = 181f +private const val BURN_IN_PREVENTION_PERIOD_PROGRESS = 89f /** * Returns the translation offset that should be used to avoid burn in at diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index ae2602baf6c7..b414961d21da 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -2633,7 +2633,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, if (mContext.getResources().getBoolean( com.android.internal.R.bool.config_guestUserAutoCreated)) { // TODO(b/191067027): Move post-boot guest creation to system_server - mUserSwitcherController.guaranteeGuestPresent(); + mUserSwitcherController.schedulePostBootGuestCreation(); } mBootCompleted = true; adjustStatusBarLocked(false, true); @@ -2789,7 +2789,10 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, // Don't hide the keyguard due to a doze change if there's a lock pending, because we're // just going to show it again. - if (mShowing || !mPendingLock) { + // If the device is not capable of controlling the screen off animation, SysUI needs to + // update lock screen state in ATMS here, otherwise ATMS tries to resume activities when + // enabling doze state. + if (mShowing || !mPendingLock || !mDozeParameters.canControlUnlockedScreenOff()) { setShowingLocked(mShowing); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java index ce1066ee41c2..1bd36644bbc5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java +++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java @@ -268,7 +268,7 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { } @Override - public void setExpansion(float expansion) { + public void setExpansion(float expansion, float proposedTranslation) { mLastExpansion = expansion; updateSelected(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java index c9230d684b1b..1c841eca65f3 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java @@ -498,11 +498,13 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca : headerTranslation); } int currentHeight = getView().getHeight(); - mLastHeaderTranslation = headerTranslation; - if (expansion == mLastQSExpansion && mLastKeyguardAndExpanded == onKeyguardAndExpanded - && mLastViewHeight == currentHeight) { + if (expansion == mLastQSExpansion + && mLastKeyguardAndExpanded == onKeyguardAndExpanded + && mLastViewHeight == currentHeight + && mLastHeaderTranslation == headerTranslation) { return; } + mLastHeaderTranslation = headerTranslation; mLastQSExpansion = expansion; mLastKeyguardAndExpanded = onKeyguardAndExpanded; mLastViewHeight = currentHeight; @@ -522,8 +524,8 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca } mFooter.setExpansion(onKeyguardAndExpanded ? 1 : expansion); mQSPanelController.setRevealExpansion(expansion); - mQSPanelController.getTileLayout().setExpansion(expansion); - mQuickQSPanelController.getTileLayout().setExpansion(expansion); + mQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation); + mQuickQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation); mQSPanelScrollView.setTranslationY(translationScaleY * heightDiff); if (fullyCollapsed) { mQSPanelScrollView.setScrollY(0); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 1b4ee734a491..cde80e66ba26 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -742,7 +742,7 @@ public class QSPanel extends LinearLayout implements Tunable { void setListening(boolean listening, UiEventLogger uiEventLogger); /** - * Set the minimum number of rows to show + * Sets the minimum number of rows to show * * @param minRows the minimum. */ @@ -751,7 +751,7 @@ public class QSPanel extends LinearLayout implements Tunable { } /** - * Set the max number of columns to show + * Sets the max number of columns to show * * @param maxColumns the maximum * @@ -761,7 +761,10 @@ public class QSPanel extends LinearLayout implements Tunable { return false; } - default void setExpansion(float expansion) {} + /** + * Sets the expansion value and proposedTranslation to panel. + */ + default void setExpansion(float expansion, float proposedTranslation) {} int getNumVisibleTiles(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java index 756ad9939886..541ee2c4fe8f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java @@ -51,7 +51,6 @@ import com.android.systemui.qs.external.TileServices; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.settings.UserTracker; import com.android.systemui.shared.plugins.PluginManager; -import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.phone.AutoTileManager; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarIconController; @@ -512,33 +511,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D } } } - // TODO(b/174753536): Move it into the config file. - // Only do the below hacking when at least one of the below tiles exist - // --InternetTile - // --WiFiTile - // --CellularTIle - if (tiles.contains("internet") || tiles.contains("wifi") || tiles.contains("cell")) { - if (FeatureFlags.isProviderModelSettingEnabled(context)) { - if (!tiles.contains("internet")) { - if (tiles.contains("wifi")) { - // Replace the WiFi with Internet, and remove the Cell - tiles.set(tiles.indexOf("wifi"), "internet"); - tiles.remove("cell"); - } else if (tiles.contains("cell")) { - // Replace the Cell with Internet - tiles.set(tiles.indexOf("cell"), "internet"); - } - } else { - tiles.remove("wifi"); - tiles.remove("cell"); - } - } else { - if (tiles.contains("internet")) { - tiles.set(tiles.indexOf("internet"), "wifi"); - tiles.add("cell"); - } - } - } return tiles; } @@ -558,14 +530,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D && GarbageMonitor.ADD_MEMORY_TILE_TO_DEFAULT_ON_DEBUGGABLE_BUILDS) { tiles.add(GarbageMonitor.MemoryTile.TILE_SPEC); } - // TODO(b/174753536): Change the config file directly. - // Filter out unused tiles from the default QS config. - if (FeatureFlags.isProviderModelSettingEnabled(context)) { - tiles.remove("cell"); - tiles.remove("wifi"); - } else { - tiles.remove("internet"); - } return tiles; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java index 985943bc8b05..c5bfe97403e7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java @@ -177,6 +177,8 @@ public class QuickQSPanel extends QSPanel { static class QQSSideLabelTileLayout extends SideLabelTileLayout { + private boolean mLastSelected; + QQSSideLabelTileLayout(Context context) { super(context, null); setClipChildren(false); @@ -222,5 +224,29 @@ public class QuickQSPanel extends QSPanel { } } } + + @Override + public void setExpansion(float expansion, float proposedTranslation) { + if (expansion > 0f && expansion < 1f) { + return; + } + // The cases we must set select for marquee when QQS/QS collapsed, and QS full expanded. + // Expansion == 0f is when QQS is fully showing (as opposed to 1f, which is QS). At this + // point we want them to be selected so the tiles will marquee (but not at other points + // of expansion. + boolean selected = (expansion == 1f || proposedTranslation < 0f); + if (mLastSelected == selected) { + return; + } + // We set it as not important while we change this, so setting each tile as selected + // will not cause them to announce themselves until the user has actually selected the + // item. + setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); + for (int i = 0; i < getChildCount(); i++) { + getChildAt(i).setSelected(selected); + } + setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); + mLastSelected = selected; + } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java index 3cb715cee8e9..3c2f35b954ea 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java @@ -41,7 +41,6 @@ import com.android.systemui.qs.dagger.QSScope; import com.android.systemui.qs.external.CustomTile; import com.android.systemui.qs.tileimpl.QSTileImpl.DrawableIcon; import com.android.systemui.settings.UserTracker; -import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.util.leak.GarbageMonitor; import java.util.ArrayList; @@ -63,7 +62,6 @@ public class TileQueryHelper { private final Executor mBgExecutor; private final Context mContext; private final UserTracker mUserTracker; - private final FeatureFlags mFeatureFlags; private TileStateListener mListener; private boolean mFinished; @@ -73,14 +71,12 @@ public class TileQueryHelper { Context context, UserTracker userTracker, @Main Executor mainExecutor, - @Background Executor bgExecutor, - FeatureFlags featureFlags + @Background Executor bgExecutor ) { mContext = context; mMainExecutor = mainExecutor; mBgExecutor = bgExecutor; mUserTracker = userTracker; - mFeatureFlags = featureFlags; } public void setListener(TileStateListener listener) { @@ -121,19 +117,11 @@ public class TileQueryHelper { } final ArrayList<QSTile> tilesToAdd = new ArrayList<>(); - // TODO(b/174753536): Move it into the config file. - if (mFeatureFlags.isProviderModelSettingEnabled()) { - possibleTiles.remove("cell"); - possibleTiles.remove("wifi"); - } else { - possibleTiles.remove("internet"); - } for (String spec : possibleTiles) { // Only add current and stock tiles that can be created from QSFactoryImpl. // Do not include CustomTile. Those will be created by `addPackageTiles`. if (spec.startsWith(CustomTile.PREFIX)) continue; - // TODO(b/174753536): Move it into the config file. final QSTile tile = host.createTile(spec); if (tile == null) { continue; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt index 70685a68e182..222539d49526 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt @@ -195,9 +195,6 @@ open class QSTileViewImpl @JvmOverloads constructor( // sibling methods to have special behavior for labelContainer. labelContainer.forceUnspecifiedMeasure = true secondaryLabel.alpha = 0f - // Do not marque in QQS - label.ellipsize = TextUtils.TruncateAt.END - secondaryLabel.ellipsize = TextUtils.TruncateAt.END } setLabelColor(getLabelColorForState(QSTile.State.DEFAULT_STATE)) setSecondaryLabelColor(getSecondaryLabelColorForState(QSTile.State.DEFAULT_STATE)) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java index acfd998ff6e4..8e6cf36f8e74 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java @@ -17,14 +17,10 @@ package com.android.systemui.statusbar; import android.content.Context; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.graphics.Point; import android.graphics.Rect; import android.os.Bundle; import android.os.Parcelable; import android.util.AttributeSet; -import android.view.DisplayCutout; import android.view.View; import android.widget.TextView; @@ -42,22 +38,14 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry. public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout { private static final String HEADS_UP_STATUS_BAR_VIEW_SUPER_PARCELABLE = "heads_up_status_bar_view_super_parcelable"; - private static final String FIRST_LAYOUT = "first_layout"; private static final String VISIBILITY = "visibility"; private static final String ALPHA = "alpha"; - private int mAbsoluteStartPadding; - private int mEndMargin; + private final Rect mLayoutedIconRect = new Rect(); + private final int[] mTmpPosition = new int[2]; + private final Rect mIconDrawingRect = new Rect(); private View mIconPlaceholder; private TextView mTextView; private NotificationEntry mShowingEntry; - private Rect mLayoutedIconRect = new Rect(); - private int[] mTmpPosition = new int[2]; - private boolean mFirstLayout = true; - private int mMaxWidth; - private int mSysWinInset; - private int mCutOutInset; - private Rect mIconDrawingRect = new Rect(); - private Point mDisplaySize; private Runnable mOnDrawingRectChangedListener; public HeadsUpStatusBarView(Context context) { @@ -75,40 +63,6 @@ public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout { public HeadsUpStatusBarView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); - Resources res = getResources(); - mAbsoluteStartPadding = res.getDimensionPixelSize(R.dimen.notification_side_paddings) - + res.getDimensionPixelSize( - com.android.internal.R.dimen.notification_content_margin_start); - mEndMargin = res.getDimensionPixelSize( - com.android.internal.R.dimen.notification_content_margin_end); - setPaddingRelative(mAbsoluteStartPadding, 0, mEndMargin, 0); - updateMaxWidth(); - } - - private void updateMaxWidth() { - int maxWidth = getResources().getDimensionPixelSize(R.dimen.qs_panel_width); - if (maxWidth != mMaxWidth) { - // maxWidth doesn't work with fill_parent, let's manually make it at most as big as the - // notification panel - mMaxWidth = maxWidth; - requestLayout(); - } - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - if (mMaxWidth > 0) { - int newSize = Math.min(MeasureSpec.getSize(widthMeasureSpec), mMaxWidth); - widthMeasureSpec = MeasureSpec.makeMeasureSpec(newSize, - MeasureSpec.getMode(widthMeasureSpec)); - } - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - - @Override - protected void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - updateMaxWidth(); } @Override @@ -116,7 +70,6 @@ public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout { Bundle bundle = new Bundle(); bundle.putParcelable(HEADS_UP_STATUS_BAR_VIEW_SUPER_PARCELABLE, super.onSaveInstanceState()); - bundle.putBoolean(FIRST_LAYOUT, mFirstLayout); bundle.putInt(VISIBILITY, getVisibility()); bundle.putFloat(ALPHA, getAlpha()); @@ -125,7 +78,7 @@ public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout { @Override public void onRestoreInstanceState(Parcelable state) { - if (state == null || !(state instanceof Bundle)) { + if (!(state instanceof Bundle)) { super.onRestoreInstanceState(state); return; } @@ -133,7 +86,6 @@ public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout { Bundle bundle = (Bundle) state; Parcelable superState = bundle.getParcelable(HEADS_UP_STATUS_BAR_VIEW_SUPER_PARCELABLE); super.onRestoreInstanceState(superState); - mFirstLayout = bundle.getBoolean(FIRST_LAYOUT, true); if (bundle.containsKey(VISIBILITY)) { setVisibility(bundle.getInt(VISIBILITY)); } @@ -185,70 +137,22 @@ public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout { protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); mIconPlaceholder.getLocationOnScreen(mTmpPosition); - int left = (int) (mTmpPosition[0] - getTranslationX()); + int left = mTmpPosition[0]; int top = mTmpPosition[1]; int right = left + mIconPlaceholder.getWidth(); int bottom = top + mIconPlaceholder.getHeight(); mLayoutedIconRect.set(left, top, right, bottom); updateDrawingRect(); - int targetPadding = mAbsoluteStartPadding + mSysWinInset + mCutOutInset; - boolean isRtl = isLayoutRtl(); - int start = isRtl ? (mDisplaySize.x - right) : left; - if (start != targetPadding) { - int newPadding = targetPadding - start + getPaddingStart(); - setPaddingRelative(newPadding, 0, mEndMargin, 0); - } - if (mFirstLayout) { - // we need to do the padding calculation in the first frame, so the layout specified - // our visibility to be INVISIBLE in the beginning. let's correct that and set it - // to GONE. - setVisibility(GONE); - mFirstLayout = false; - } - } - - /** In order to do UI alignment, this view will be notified by - * {@link com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout}. - * After scroller laid out, the scroller will tell this view about scroller's getX() - * @param translationX how to translate the horizontal position - */ - public void setPanelTranslation(float translationX) { - setTranslationX(translationX); - updateDrawingRect(); } private void updateDrawingRect() { float oldLeft = mIconDrawingRect.left; mIconDrawingRect.set(mLayoutedIconRect); - mIconDrawingRect.offset((int) getTranslationX(), 0); if (oldLeft != mIconDrawingRect.left && mOnDrawingRectChangedListener != null) { mOnDrawingRectChangedListener.run(); } } - @Override - protected boolean fitSystemWindows(Rect insets) { - boolean isRtl = isLayoutRtl(); - mSysWinInset = isRtl ? insets.right : insets.left; - DisplayCutout displayCutout = getRootWindowInsets().getDisplayCutout(); - mCutOutInset = (displayCutout != null) - ? (isRtl ? displayCutout.getSafeInsetRight() : displayCutout.getSafeInsetLeft()) - : 0; - - getDisplaySize(); - - // For Double Cut Out mode, the System window navigation bar is at the right - // side of the left cut out. In this condition, mSysWinInset include the left cut - // out width so we set mCutOutInset to be 0. For RTL, the condition is the same. - // The navigation bar is at the left side of the right cut out and include the - // right cut out width. - if (mSysWinInset != 0) { - mCutOutInset = 0; - } - - return super.fitSystemWindows(insets); - } - public NotificationEntry getShowingEntry() { return mShowingEntry; } @@ -264,17 +168,4 @@ public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout { public void setOnDrawingRectChangedListener(Runnable onDrawingRectChangedListener) { mOnDrawingRectChangedListener = onDrawingRectChangedListener; } - - private void getDisplaySize() { - if (mDisplaySize == null) { - mDisplaySize = new Point(); - } - getDisplay().getRealSize(mDisplaySize); - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - getDisplaySize(); - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index 3890c1aa4e4f..503b5c0ee4b0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -825,7 +825,11 @@ public class KeyguardIndicationController { if (mKeyguardUpdateMonitor.isUdfpsAvailable()) { // if udfps available, there will always be a tappable affordance to unlock // For example, the lock icon - showTransientIndication(R.string.keyguard_unlock_press); + if (mKeyguardBypassController.getUserHasDeviceEntryIntent()) { + showTransientIndication(R.string.keyguard_unlock_press); + } else { + showTransientIndication(R.string.keyguard_face_failed_use_fp); + } } else { showTransientIndication(R.string.keyguard_try_fingerprint); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt index db553e4b093b..002c9c7d2544 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt @@ -178,7 +178,8 @@ class NotificationShadeDepthController @Inject constructor( blurUtils.minBlurRadius, blurUtils.maxBlurRadius) var combinedBlur = (shadeSpring.radius * INTERACTION_BLUR_FRACTION + normalizedBlurRadius * ANIMATION_BLUR_FRACTION).toInt() - combinedBlur = max(combinedBlur, blurUtils.blurRadiusOfRatio(qsPanelExpansion)) + val qsExpandedRatio = qsPanelExpansion * shadeExpansion + combinedBlur = max(combinedBlur, blurUtils.blurRadiusOfRatio(qsExpandedRatio)) combinedBlur = max(combinedBlur, blurUtils.blurRadiusOfRatio(transitionToFullShadeProgress)) var shadeRadius = max(combinedBlur, wakeAndUnlockBlurRadius).toFloat() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java index 1b4ae9ea3f32..2c810c93b2ee 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java @@ -157,15 +157,13 @@ public class StackScrollAlgorithm { // After the shelf has updated its yTranslation, explicitly set alpha=0 for view below shelf // to skip rendering them in the hardware layer. We do not set them invisible because that // runs invalidate & onDraw when these views return onscreen, which is more expensive. + if (shelf.getViewState().hidden) { + // When the shelf is hidden, it won't clip views, so we don't hide rows + return; + } final float shelfTop = shelf.getViewState().yTranslation; for (ExpandableView view : algorithmState.visibleChildren) { - if (view instanceof ExpandableNotificationRow) { - ExpandableNotificationRow row = (ExpandableNotificationRow) view; - if (row.isHeadsUp() || row.isHeadsUpAnimatingAway()) { - continue; - } - } final float viewTop = view.getViewState().yTranslation; if (viewTop >= shelfTop) { view.getViewState().alpha = 0; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java index 68024726c5de..5a6db213d87f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java @@ -231,7 +231,9 @@ public class DozeParameters implements TunerService.Tunable, * possible if AOD isn't even enabled or if the flag is disabled. */ public boolean canControlUnlockedScreenOff() { - return getAlwaysOn() && mFeatureFlags.useNewLockscreenAnimations(); + return getAlwaysOn() + && mFeatureFlags.useNewLockscreenAnimations() + && !getDisplayNeedsBlanking(); } private boolean getBoolean(String propName, int resId) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java index f4830fbb0028..878fbbf39627 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java @@ -18,9 +18,7 @@ package com.android.systemui.statusbar.phone; import android.graphics.Point; import android.graphics.Rect; -import android.view.DisplayCutout; import android.view.View; -import android.view.WindowInsets; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.widget.ViewClippingUtil; @@ -61,7 +59,6 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, private final NotificationPanelViewController mNotificationPanelViewController; private final Consumer<ExpandableNotificationRow> mSetTrackingHeadsUp = this::setTrackingHeadsUp; - private final Runnable mUpdatePanelTranslation = this::updatePanelTranslation; private final BiConsumer<Float, Float> mSetExpandedHeight = this::setAppearFraction; private final KeyguardBypassController mBypassController; private final StatusBarStateController mStatusBarStateController; @@ -75,9 +72,6 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, float mAppearFraction; private ExpandableNotificationRow mTrackedChild; private boolean mShown; - private final View.OnLayoutChangeListener mStackScrollLayoutChangeListener = - (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) - -> updatePanelTranslation(); private final ViewClippingUtil.ClippingParameters mParentClippingParams = new ViewClippingUtil.ClippingParameters() { @Override @@ -134,10 +128,8 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, mStackScrollerController = stackScrollerController; mNotificationPanelViewController = notificationPanelViewController; notificationPanelViewController.addTrackingHeadsUpListener(mSetTrackingHeadsUp); - notificationPanelViewController.setVerticalTranslationListener(mUpdatePanelTranslation); notificationPanelViewController.setHeadsUpAppearanceController(this); mStackScrollerController.addOnExpandedHeightChangedListener(mSetExpandedHeight); - mStackScrollerController.addOnLayoutChangeListener(mStackScrollLayoutChangeListener); mStackScrollerController.setHeadsUpAppearanceController(this); mClockView = clockView; mOperatorNameView = operatorNameView; @@ -174,7 +166,6 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, mNotificationPanelViewController.setVerticalTranslationListener(null); mNotificationPanelViewController.setHeadsUpAppearanceController(null); mStackScrollerController.removeOnExpandedHeightChangedListener(mSetExpandedHeight); - mStackScrollerController.removeOnLayoutChangeListener(mStackScrollLayoutChangeListener); mDarkIconDispatcher.removeDarkReceiver(this); } @@ -189,63 +180,6 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, updateHeader(entry); } - /** To count the distance from the window right boundary to scroller right boundary. The - * distance formula is the following: - * Y = screenSize - (SystemWindow's width + Scroller.getRight()) - * There are four modes MUST to be considered in Cut Out of RTL. - * No Cut Out: - * Scroller + NB - * NB + Scroller - * => SystemWindow = NavigationBar's width - * => Y = screenSize - (SystemWindow's width + Scroller.getRight()) - * Corner Cut Out or Tall Cut Out: - * cut out + Scroller + NB - * NB + Scroller + cut out - * => SystemWindow = NavigationBar's width - * => Y = screenSize - (SystemWindow's width + Scroller.getRight()) - * Double Cut Out: - * cut out left + Scroller + (NB + cut out right) - * SystemWindow = NavigationBar's width + cut out right width - * => Y = screenSize - (SystemWindow's width + Scroller.getRight()) - * (cut out left + NB) + Scroller + cut out right - * SystemWindow = NavigationBar's width + cut out left width - * => Y = screenSize - (SystemWindow's width + Scroller.getRight()) - * @return the translation X value for RTL. In theory, it should be negative. i.e. -Y - */ - private int getRtlTranslation() { - if (mPoint == null) { - mPoint = new Point(); - } - - int realDisplaySize = 0; - if (mStackScrollerController.getDisplay() != null) { - mStackScrollerController.getDisplay().getRealSize(mPoint); - realDisplaySize = mPoint.x; - } - - WindowInsets windowInset = mStackScrollerController.getRootWindowInsets(); - DisplayCutout cutout = (windowInset != null) ? windowInset.getDisplayCutout() : null; - int sysWinLeft = (windowInset != null) ? windowInset.getStableInsetLeft() : 0; - int sysWinRight = (windowInset != null) ? windowInset.getStableInsetRight() : 0; - int cutoutLeft = (cutout != null) ? cutout.getSafeInsetLeft() : 0; - int cutoutRight = (cutout != null) ? cutout.getSafeInsetRight() : 0; - int leftInset = Math.max(sysWinLeft, cutoutLeft); - int rightInset = Math.max(sysWinRight, cutoutRight); - - return leftInset + mStackScrollerController.getRight() + rightInset - realDisplaySize; - } - - public void updatePanelTranslation() { - float newTranslation; - if (mStackScrollerController.isLayoutRtl()) { - newTranslation = getRtlTranslation(); - } else { - newTranslation = mStackScrollerController.getLeft(); - } - newTranslation += mStackScrollerController.getTranslationX(); - mHeadsUpStatusBarView.setPanelTranslation(newTranslation); - } - private void updateTopEntry() { NotificationEntry newEntry = null; if (shouldBeVisible()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt index a5b868b6f8a3..6b52dca42eda 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt @@ -149,14 +149,18 @@ class UnlockedScreenOffAnimationController @Inject constructor( lightRevealAnimationPlaying = false aodUiAnimationPlaying = false - // Make sure the status bar is in the correct keyguard state, forcing it if necessary. This - // is required if the screen off animation is cancelled, since it might be incorrectly left - // in the KEYGUARD or SHADE states depending on when it was cancelled and whether 'lock - // instantly' is enabled. We need to force it so that the state is set even if we're going - // from SHADE to SHADE or KEYGUARD to KEYGUARD, since we might have changed parts of the UI - // (such as showing AOD in the shade) without actually changing the StatusBarState. This - // ensures that the UI definitely reflects the desired state. - statusBar.updateIsKeyguard(true /* force */) + // If we can't control the screen off animation, we shouldn't mess with the StatusBar's + // keyguard state unnecessarily. + if (dozeParameters.get().canControlUnlockedScreenOff()) { + // Make sure the status bar is in the correct keyguard state, forcing it if necessary. + // This is required if the screen off animation is cancelled, since it might be + // incorrectly left in the KEYGUARD or SHADE states depending on when it was cancelled + // and whether 'lock instantly' is enabled. We need to force it so that the state is set + // even if we're going from SHADE to SHADE or KEYGUARD to KEYGUARD, since we might have + // changed parts of the UI (such as showing AOD in the shade) without actually changing + // the StatusBarState. This ensures that the UI definitely reflects the desired state. + statusBar.updateIsKeyguard(true /* force */) + } } override fun onStartedGoingToSleep() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt index 16fa5da9e979..6982631766f7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt @@ -218,6 +218,10 @@ class OngoingCallController @Inject constructor( isCallAppVisible = isProcessVisibleToUser( iActivityManager.getUidProcessState(currentCallNotificationInfo.uid, null)) + if (uidObserver != null) { + iActivityManager.unregisterUidObserver(uidObserver) + } + uidObserver = object : IUidObserver.Stub() { override fun onUidStateChanged( uid: Int, procState: Int, procStateSeq: Long, capability: Int) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java index 8f1a5782e779..251ecc626387 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java @@ -26,6 +26,7 @@ import android.app.ActivityManager; import android.app.AlertDialog; import android.app.Dialog; import android.app.IActivityTaskManager; +import android.app.admin.DevicePolicyManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; @@ -114,6 +115,8 @@ public class UserSwitcherController implements Dumpable { @VisibleForTesting final GuestResumeSessionReceiver mGuestResumeSessionReceiver; private final KeyguardStateController mKeyguardStateController; + private final DeviceProvisionedController mDeviceProvisionedController; + private final DevicePolicyManager mDevicePolicyManager; protected final Handler mHandler; private final ActivityStarter mActivityStarter; private final BroadcastDispatcher mBroadcastDispatcher; @@ -149,6 +152,8 @@ public class UserSwitcherController implements Dumpable { UserManager userManager, UserTracker userTracker, KeyguardStateController keyguardStateController, + DeviceProvisionedController deviceProvisionedController, + DevicePolicyManager devicePolicyManager, @Main Handler handler, ActivityStarter activityStarter, BroadcastDispatcher broadcastDispatcher, @@ -178,6 +183,8 @@ public class UserSwitcherController implements Dumpable { mGuestIsResetting = new AtomicBoolean(); mGuestCreationScheduled = new AtomicBoolean(); mKeyguardStateController = keyguardStateController; + mDeviceProvisionedController = deviceProvisionedController; + mDevicePolicyManager = devicePolicyManager; mHandler = handler; mActivityStarter = activityStarter; mUserManager = userManager; @@ -336,8 +343,7 @@ public class UserSwitcherController implements Dumpable { true /* isGuest */, false /* isCurrent */, false /* isAddUser */, false /* isRestricted */, isSwitchToGuestEnabled); - // Don't call checkIfAddUserDisallowedByAdminOnly if - // config_guestUserAutoCreated=true. + checkIfAddUserDisallowedByAdminOnly(guestRecord); records.add(guestRecord); } else if (canCreateGuest) { guestRecord = new UserRecord(null /* info */, null /* picture */, @@ -733,10 +739,27 @@ public class UserSwitcherController implements Dumpable { } /** + * Guarantee guest is present only if the device is provisioned. Otherwise, create a content + * observer to wait until the device is provisioned, then schedule the guest creation. + */ + public void schedulePostBootGuestCreation() { + if (isDeviceAllowedToAddGuest()) { + guaranteeGuestPresent(); + } else { + mDeviceProvisionedController.addCallback(mGuaranteeGuestPresentAfterProvisioned); + } + } + + private boolean isDeviceAllowedToAddGuest() { + return mDeviceProvisionedController.isDeviceProvisioned() + && !mDevicePolicyManager.isDeviceManaged(); + } + + /** * If there is no guest on the device, schedule creation of a new guest user in the background. */ - public void guaranteeGuestPresent() { - if (mUserManager.findCurrentGuestUser() == null) { + private void guaranteeGuestPresent() { + if (isDeviceAllowedToAddGuest() && mUserManager.findCurrentGuestUser() == null) { scheduleGuestCreation(); } } @@ -1056,6 +1079,21 @@ public class UserSwitcherController implements Dumpable { } }; + private final DeviceProvisionedController.DeviceProvisionedListener + mGuaranteeGuestPresentAfterProvisioned = + new DeviceProvisionedController.DeviceProvisionedListener() { + @Override + public void onDeviceProvisionedChanged() { + if (isDeviceAllowedToAddGuest()) { + mBgExecutor.execute( + () -> mDeviceProvisionedController.removeCallback( + mGuaranteeGuestPresentAfterProvisioned)); + guaranteeGuestPresent(); + } + } + }; + + private final class ExitGuestDialog extends SystemUIDialog implements DialogInterface.OnClickListener { diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java index b38fc77fd131..90e022a52d7a 100644 --- a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java +++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java @@ -290,15 +290,18 @@ public class ProximitySensor implements ThresholdSensor { return; } - if (!mSecondaryThresholdSensor.isLoaded()) { + + if (!mSecondaryThresholdSensor.isLoaded()) { // No secondary logDebug("Primary sensor event: " + event.getBelow() + ". No secondary."); onSensorEvent(event); - } else if (event.getBelow()) { + } else if (event.getBelow()) { // Covered? Check secondary. logDebug("Primary sensor event: " + event.getBelow() + ". Checking secondary."); if (mCancelSecondaryRunnable != null) { mCancelSecondaryRunnable.run(); } mSecondaryThresholdSensor.resume(); + } else { // Uncovered. Report immediately. + onSensorEvent(event); } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index 3320852ca1f4..60b92ef45291 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -2248,6 +2248,11 @@ public class VolumeDialogImpl implements VolumeDialog, @Override public void onClick(View view) { + // If the ringer drawer isn't open, don't let anything in it be clicked. + if (!mIsRingerDrawerOpen) { + return; + } + setRingerMode(mClickedRingerMode); mRingerDrawerIconAnimatingSelected = getDrawerIconViewForMode(mClickedRingerMode); |