summaryrefslogtreecommitdiff
path: root/packages/SystemUI/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/SystemUI/src')
-rw-r--r--packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java6
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt3
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java9
-rwxr-xr-xpackages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java106
-rw-r--r--packages/SystemUI/src/com/android/keyguard/LockIconViewController.java104
-rw-r--r--packages/SystemUI/src/com/android/keyguard/NumPadButton.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/Dependency.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/Prefs.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/BiometricOrientationEventListener.kt33
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java84
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java56
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java47
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java87
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java53
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java58
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java87
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java586
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt231
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java44
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt55
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java16
61 files changed, 1150 insertions, 997 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
index c89cda98c8a5..92f89d6b90fd 100644
--- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
@@ -134,11 +134,15 @@ public class AnimatableClockController extends ViewController<AnimatableClockVie
};
@Override
+ protected void onInit() {
+ mIsDozing = mStatusBarStateController.isDozing();
+ }
+
+ @Override
protected void onViewAttached() {
updateLocale();
mBroadcastDispatcher.registerReceiver(mLocaleBroadcastReceiver,
new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
- mIsDozing = mStatusBarStateController.isDozing();
mDozeAmount = mStatusBarStateController.getDozeAmount();
mBatteryController.addCallback(mBatteryCallback);
mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
index ff20805c5ea4..0785cc3c04d2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
@@ -23,5 +23,6 @@ data class KeyguardFaceListenModel(
val isLockIconPressed: Boolean,
val isScanningAllowedByStrongAuth: Boolean,
val isPrimaryUser: Boolean,
- val isSecureCameraLaunched: Boolean
+ val isSecureCameraLaunched: Boolean,
+ val isFaceAuthenticated: Boolean
)
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
index 933a919efaad..92f8454fc93e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
@@ -27,6 +27,7 @@ import android.text.method.TextKeyListener;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup.MarginLayoutParams;
+import android.view.WindowInsets;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
@@ -227,12 +228,16 @@ public class KeyguardPasswordViewController
super.onPause();
});
}
- mInputMethodManager.hideSoftInputFromWindow(mView.getWindowToken(), 0);
+ if (mPasswordEntry.isAttachedToWindow()) {
+ mPasswordEntry.getWindowInsetsController().hide(WindowInsets.Type.ime());
+ }
}
@Override
public void onStartingToHide() {
- mInputMethodManager.hideSoftInputFromWindow(mView.getWindowToken(), 0);
+ if (mPasswordEntry.isAttachedToWindow()) {
+ mPasswordEntry.getWindowInsetsController().hide(WindowInsets.Type.ime());
+ }
}
private void updateSwitchImeButton() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 5c9afa5cf4c9..33af16464965 100755
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -124,10 +124,13 @@ import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -470,16 +473,39 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
List<SubscriptionInfo> subscriptionInfos = getSubscriptionInfo(true /* forceReload */);
// Hack level over 9000: Because the subscription id is not yet valid when we see the
- // first update in handleSimStateChange, we need to force refresh all all SIM states
+ // first update in handleSimStateChange, we need to force refresh all SIM states
// so the subscription id for them is consistent.
ArrayList<SubscriptionInfo> changedSubscriptions = new ArrayList<>();
+ Set<Integer> activeSubIds = new HashSet<>();
for (int i = 0; i < subscriptionInfos.size(); i++) {
SubscriptionInfo info = subscriptionInfos.get(i);
+ activeSubIds.add(info.getSubscriptionId());
boolean changed = refreshSimState(info.getSubscriptionId(), info.getSimSlotIndex());
if (changed) {
changedSubscriptions.add(info);
}
}
+
+ // It is possible for active subscriptions to become invalid (-1), and these will not be
+ // present in the subscriptionInfo list
+ Iterator<Map.Entry<Integer, SimData>> iter = mSimDatas.entrySet().iterator();
+ while (iter.hasNext()) {
+ Map.Entry<Integer, SimData> simData = iter.next();
+ if (!activeSubIds.contains(simData.getKey())) {
+ Log.i(TAG, "Previously active sub id " + simData.getKey() + " is now invalid, "
+ + "will remove");
+ iter.remove();
+
+ SimData data = simData.getValue();
+ for (int j = 0; j < mCallbacks.size(); j++) {
+ KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
+ if (cb != null) {
+ cb.onSimStateChanged(data.subId, data.slotId, data.simState);
+ }
+ }
+ }
+ }
+
for (int i = 0; i < changedSubscriptions.size(); i++) {
SimData data = mSimDatas.get(changedSubscriptions.get(i).getSimSlotIndex());
for (int j = 0; j < mCallbacks.size(); j++) {
@@ -1059,9 +1085,18 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|| isSimPinSecure());
}
+ private boolean getIsFaceAuthenticated() {
+ boolean faceAuthenticated = false;
+ BiometricAuthenticated bioFaceAuthenticated = mUserFaceAuthenticated.get(getCurrentUser());
+ if (bioFaceAuthenticated != null) {
+ faceAuthenticated = bioFaceAuthenticated.mAuthenticated;
+ }
+ return faceAuthenticated;
+ }
+
private void requireStrongAuthIfAllLockedOut() {
final boolean faceLock =
- mFaceLockedOutPermanent || !shouldListenForFace();
+ (mFaceLockedOutPermanent || !shouldListenForFace()) && !getIsFaceAuthenticated();
final boolean fpLock =
mFingerprintLockedOutPermanent || !shouldListenForFingerprint(isUdfpsEnrolled());
@@ -1429,32 +1464,42 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
final FaceManager.AuthenticationCallback mFaceAuthenticationCallback
= new FaceManager.AuthenticationCallback() {
- @Override
- public void onAuthenticationFailed() {
- handleFaceAuthFailed();
- }
+ @Override
+ public void onAuthenticationFailed() {
+ handleFaceAuthFailed();
+ if (mKeyguardBypassController != null) {
+ mKeyguardBypassController.setUserHasDeviceEntryIntent(false);
+ }
+ }
- @Override
- public void onAuthenticationSucceeded(FaceManager.AuthenticationResult result) {
- Trace.beginSection("KeyguardUpdateMonitor#onAuthenticationSucceeded");
- handleFaceAuthenticated(result.getUserId(), result.isStrongBiometric());
- Trace.endSection();
- }
+ @Override
+ public void onAuthenticationSucceeded(FaceManager.AuthenticationResult result) {
+ Trace.beginSection("KeyguardUpdateMonitor#onAuthenticationSucceeded");
+ handleFaceAuthenticated(result.getUserId(), result.isStrongBiometric());
+ Trace.endSection();
- @Override
- public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
- handleFaceHelp(helpMsgId, helpString.toString());
- }
+ if (mKeyguardBypassController != null) {
+ mKeyguardBypassController.setUserHasDeviceEntryIntent(false);
+ }
+ }
- @Override
- public void onAuthenticationError(int errMsgId, CharSequence errString) {
- handleFaceError(errMsgId, errString.toString());
- }
+ @Override
+ public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
+ handleFaceHelp(helpMsgId, helpString.toString());
+ }
- @Override
- public void onAuthenticationAcquired(int acquireInfo) {
- handleFaceAcquired(acquireInfo);
- }
+ @Override
+ public void onAuthenticationError(int errMsgId, CharSequence errString) {
+ handleFaceError(errMsgId, errString.toString());
+ if (mKeyguardBypassController != null) {
+ mKeyguardBypassController.setUserHasDeviceEntryIntent(false);
+ }
+ }
+
+ @Override
+ public void onAuthenticationAcquired(int acquireInfo) {
+ handleFaceAcquired(acquireInfo);
+ }
};
private CancellationSignal mFingerprintCancelSignal;
@@ -2232,6 +2277,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
strongAuthAllowsScanning = false;
}
+ // If the face has recently been authenticated do not attempt to authenticate again.
+ boolean faceAuthenticated = getIsFaceAuthenticated();
+
// 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 =
@@ -2240,7 +2288,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
&& !mSwitchingUser && !isFaceDisabled(user) && becauseCannotSkipBouncer
&& !mKeyguardGoingAway && mBiometricEnabledForUser.get(user) && !mLockIconPressed
&& strongAuthAllowsScanning && mIsPrimaryUser
- && (!mSecureCameraLaunched || mOccludingAppRequestingFace);
+ && (!mSecureCameraLaunched || mOccludingAppRequestingFace)
+ && !faceAuthenticated;
// Aggregate relevant fields for debug logging.
if (DEBUG_FACE || DEBUG_SPEW) {
@@ -2261,7 +2310,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mLockIconPressed,
strongAuthAllowsScanning,
mIsPrimaryUser,
- mSecureCameraLaunched);
+ mSecureCameraLaunched,
+ faceAuthenticated);
maybeLogFaceListenerModelData(model);
}
@@ -3386,6 +3436,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
pw.println(" trustManaged=" + getUserTrustIsManaged(userId));
pw.println(" udfpsEnrolled=" + isUdfpsEnrolled());
pw.println(" mFingerprintLockedOut=" + mFingerprintLockedOut);
+ pw.println(" mFingerprintLockedOutPermanent=" + mFingerprintLockedOutPermanent);
pw.println(" enabledByUser=" + mBiometricEnabledForUser.get(userId));
if (isUdfpsEnrolled()) {
pw.println(" shouldListenForUdfps=" + shouldListenForFingerprint(true));
@@ -3407,8 +3458,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
+ getStrongAuthTracker().hasUserAuthenticatedSinceBoot());
pw.println(" disabled(DPM)=" + isFaceDisabled(userId));
pw.println(" possible=" + isUnlockWithFacePossible(userId));
+ pw.println(" listening: actual=" + mFaceRunningState
+ + " expected=(" + (shouldListenForFace() ? 1 : 0));
pw.println(" strongAuthFlags=" + Integer.toHexString(strongAuthFlags));
pw.println(" trustManaged=" + getUserTrustIsManaged(userId));
+ pw.println(" mFaceLockedOutPermanent=" + mFaceLockedOutPermanent);
pw.println(" enabledByUser=" + mBiometricEnabledForUser.get(userId));
pw.println(" mSecureCameraLaunched=" + mSecureCameraLaunched);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index afea27222fbb..9c8582fa334d 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -28,6 +28,9 @@ import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.biometrics.BiometricSourceType;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
+import android.media.AudioAttributes;
+import android.os.Process;
+import android.os.Vibrator;
import android.util.DisplayMetrics;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
@@ -44,6 +47,7 @@ import com.android.settingslib.Utils;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.biometrics.AuthController;
+import com.android.systemui.biometrics.UdfpsController;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.FalsingManager;
@@ -68,6 +72,16 @@ import javax.inject.Inject;
*/
@StatusBarComponent.StatusBarScope
public class LockIconViewController extends ViewController<LockIconView> implements Dumpable {
+ private static final float sDefaultDensity =
+ (float) DisplayMetrics.DENSITY_DEVICE_STABLE / (float) DisplayMetrics.DENSITY_DEFAULT;
+ private static final int sLockIconRadiusPx = (int) (sDefaultDensity * 36);
+ private static final float sDistAboveKgBottomAreaPx = sDefaultDensity * 12;
+ private static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES =
+ new AudioAttributes.Builder()
+ .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+ .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+ .build();
+
@NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@NonNull private final KeyguardViewController mKeyguardViewController;
@NonNull private final StatusBarStateController mStatusBarStateController;
@@ -82,8 +96,10 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
@NonNull private final AnimatedVectorDrawable mFpToUnlockIcon;
@NonNull private final AnimatedVectorDrawable mLockToUnlockIcon;
@NonNull private final Drawable mLockIcon;
+ @NonNull private final Drawable mUnlockIcon;
@NonNull private final CharSequence mUnlockedLabel;
@NonNull private final CharSequence mLockedLabel;
+ @Nullable private final Vibrator mVibrator;
private boolean mIsDozing;
private boolean mIsBouncerShowing;
@@ -98,14 +114,13 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
private boolean mHasUdfps;
private float mHeightPixels;
private float mWidthPixels;
- private float mDensity;
- private int mAmbientIndicationHeight; // in pixels
- private int mKgIndicationHeight; // in pixels
+ private int mBottomPadding; // in pixels
private boolean mShowUnlockIcon;
private boolean mShowLockIcon;
private boolean mDownDetected;
+ private boolean mDetectedLongPress;
private final Rect mSensorTouchLocation = new Rect();
@Inject
@@ -120,7 +135,8 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
@NonNull DumpManager dumpManager,
@NonNull AccessibilityManager accessibilityManager,
@NonNull ConfigurationController configurationController,
- @NonNull @Main DelayableExecutor executor
+ @NonNull @Main DelayableExecutor executor,
+ @Nullable Vibrator vibrator
) {
super(view);
mStatusBarStateController = statusBarStateController;
@@ -132,8 +148,13 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
mAccessibilityManager = accessibilityManager;
mConfigurationController = configurationController;
mExecutor = executor;
+ mVibrator = vibrator;
final Context context = view.getContext();
+ mUnlockIcon = mView.getContext().getResources().getDrawable(
+ R.anim.lock_to_unlock,
+ mView.getContext().getTheme());
+ ((AnimatedVectorDrawable) mUnlockIcon).start();
mLockIcon = mView.getContext().getResources().getDrawable(
R.anim.lock_to_unlock,
mView.getContext().getTheme());
@@ -213,8 +234,9 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
return;
}
- boolean wasShowingFpIcon = mHasUdfps && !mShowUnlockIcon && !mShowLockIcon;
+ boolean wasShowingFpIcon = mUdfpsEnrolled && !mShowUnlockIcon && !mShowLockIcon;
boolean wasShowingLockIcon = mShowLockIcon;
+ boolean wasShowingUnlockIcon = mShowUnlockIcon;
mShowLockIcon = !mCanDismissLockScreen && !mUserUnlockedWithBiometric && isLockScreen()
&& (!mUdfpsEnrolled || !mRunningFPS);
mShowUnlockIcon = mCanDismissLockScreen && isLockScreen();
@@ -225,14 +247,18 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
mView.setVisibility(View.VISIBLE);
mView.setContentDescription(mLockedLabel);
} else if (mShowUnlockIcon) {
- if (wasShowingFpIcon) {
- mView.setImageDrawable(mFpToUnlockIcon);
- mFpToUnlockIcon.forceAnimationOnUI();
- mFpToUnlockIcon.start();
- } else if (wasShowingLockIcon) {
- mView.setImageDrawable(mLockToUnlockIcon);
- mLockToUnlockIcon.forceAnimationOnUI();
- mLockToUnlockIcon.start();
+ if (!wasShowingUnlockIcon) {
+ if (wasShowingFpIcon) {
+ mView.setImageDrawable(mFpToUnlockIcon);
+ mFpToUnlockIcon.forceAnimationOnUI();
+ mFpToUnlockIcon.start();
+ } else if (wasShowingLockIcon) {
+ mView.setImageDrawable(mLockToUnlockIcon);
+ mLockToUnlockIcon.forceAnimationOnUI();
+ mLockToUnlockIcon.start();
+ } else {
+ mView.setImageDrawable(mUnlockIcon);
+ }
}
mView.setVisibility(View.VISIBLE);
mView.setContentDescription(mUnlockedLabel);
@@ -286,17 +312,15 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
mFpToUnlockIcon.setTint(color);
mLockToUnlockIcon.setTint(color);
mLockIcon.setTint(color);
+ mUnlockIcon.setTint(color);
}
private void updateConfiguration() {
final DisplayMetrics metrics = mView.getContext().getResources().getDisplayMetrics();
mWidthPixels = metrics.widthPixels;
mHeightPixels = metrics.heightPixels;
- mDensity = metrics.density;
- mKgIndicationHeight = mView.getContext().getResources().getDimensionPixelSize(
- R.dimen.keyguard_indication_margin_bottom)
- + mView.getContext().getResources().getDimensionPixelSize(
- R.dimen.keyguard_indication_bottom_padding);
+ mBottomPadding = mView.getContext().getResources().getDimensionPixelSize(
+ R.dimen.lock_icon_margin_bottom);
updateLockIconLocation();
}
@@ -306,26 +330,15 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
mView.setCenterLocation(new PointF(props.sensorLocationX, props.sensorLocationY),
props.sensorRadius);
} else {
- final float distAboveKgBottomArea = 12 * mDensity;
- final float radius = 36 * mDensity;
- final int kgBottomAreaHeight = Math.max(mKgIndicationHeight, mAmbientIndicationHeight);
mView.setCenterLocation(
new PointF(mWidthPixels / 2,
- mHeightPixels - kgBottomAreaHeight - distAboveKgBottomArea
- - radius / 2), (int) radius);
+ mHeightPixels - mBottomPadding - sDistAboveKgBottomAreaPx
+ - sLockIconRadiusPx), sLockIconRadiusPx);
}
mView.getHitRect(mSensorTouchLocation);
}
- /**
- * Set the location of ambient indication if showing (ie: now playing)
- */
- public void setAmbientIndicationBottomPadding(int ambientIndicationBottomPadding) {
- mAmbientIndicationHeight = ambientIndicationBottomPadding;
- updateLockIconLocation();
- }
-
@Override
public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
pw.println("mUdfpsEnrolled: " + mUdfpsEnrolled);
@@ -413,7 +426,16 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
@Override
public void onKeyguardShowingChanged() {
+ // Reset values in case biometrics were removed (ie: pin/pattern/password => swipe).
+ // If biometrics were removed, local vars mCanDismissLockScreen and
+ // mUserUnlockedWithBiometric may not be updated.
+ mCanDismissLockScreen = mKeyguardStateController.canDismissLockScreen();
updateKeyguardShowing();
+ if (mIsKeyguardShowing) {
+ mUserUnlockedWithBiometric =
+ mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(
+ KeyguardUpdateMonitor.getCurrentUser());
+ }
mUdfpsEnrolled = mKeyguardUpdateMonitor.isUdfpsEnrolled();
updateVisibility();
}
@@ -451,6 +473,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
private final GestureDetector mGestureDetector =
new GestureDetector(new SimpleOnGestureListener() {
public boolean onDown(MotionEvent e) {
+ mDetectedLongPress = false;
if (!isClickable()) {
mDownDetected = false;
return false;
@@ -459,6 +482,14 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
// intercept all following touches until we see MotionEvent.ACTION_CANCEL UP or
// MotionEvent.ACTION_UP (see #onTouchEvent)
mDownDetected = true;
+ if (mVibrator != null) {
+ mVibrator.vibrate(
+ Process.myUid(),
+ getContext().getOpPackageName(),
+ UdfpsController.EFFECT_CLICK,
+ "lockIcon-onDown",
+ VIBRATION_SONIFICATION_ATTRIBUTES);
+ }
return true;
}
@@ -467,6 +498,15 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
return;
}
+ if (mVibrator != null) {
+ mVibrator.vibrate(
+ Process.myUid(),
+ getContext().getOpPackageName(),
+ UdfpsController.EFFECT_CLICK,
+ "lockIcon-onLongPress",
+ VIBRATION_SONIFICATION_ATTRIBUTES);
+ }
+ mDetectedLongPress = true;
onAffordanceClick();
}
@@ -509,7 +549,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
// we continue to intercept all following touches until we see MotionEvent.ACTION_CANCEL UP
// or MotionEvent.ACTION_UP. this is to avoid passing the touch to NPV
// after the lock icon disappears on device entry
- if (mDownDetected) {
+ if (mDownDetected && mDetectedLongPress) {
if (event.getAction() == MotionEvent.ACTION_CANCEL
|| event.getAction() == MotionEvent.ACTION_UP) {
mDownDetected = false;
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java
index 099e6f4b5341..57407f1f34c0 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java
@@ -88,13 +88,10 @@ public class NumPadButton extends AlphaOptimizedImageButton {
* Reload colors from resources.
**/
public void reloadColors() {
- if (mAnimator != null) {
- mAnimator.reloadColors(getContext());
- } else {
- // Needed for old style pin
- int textColor = Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary)
- .getDefaultColor();
- ((VectorDrawable) getDrawable()).setTintList(ColorStateList.valueOf(textColor));
- }
+ if (mAnimator != null) mAnimator.reloadColors(getContext());
+
+ int textColor = Utils.getColorAttrDefaultColor(getContext(),
+ android.R.attr.colorBackground);
+ ((VectorDrawable) getDrawable()).setTintList(ColorStateList.valueOf(textColor));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 104d711f46fb..76f30a80114a 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -100,6 +100,7 @@ import com.android.systemui.statusbar.phone.ManagedProfileController;
import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
import com.android.systemui.statusbar.policy.AccessibilityController;
@@ -359,9 +360,10 @@ public class Dependency {
@Inject Lazy<TelephonyListenerManager> mTelephonyListenerManager;
@Inject Lazy<SystemStatusAnimationScheduler> mSystemStatusAnimationSchedulerLazy;
@Inject Lazy<PrivacyDotViewController> mPrivacyDotViewControllerLazy;
- @Inject Lazy<EdgeBackGestureHandler> mEdgeBackGestureHandler;
+ @Inject Lazy<EdgeBackGestureHandler.Factory> mEdgeBackGestureHandlerFactoryLazy;
@Inject Lazy<UiEventLogger> mUiEventLogger;
@Inject Lazy<FeatureFlags> mFeatureFlagsLazy;
+ @Inject Lazy<StatusBarContentInsetsProvider> mContentInsetsProviderLazy;
@Inject
public Dependency() {
@@ -574,9 +576,11 @@ public class Dependency {
mProviders.put(SystemStatusAnimationScheduler.class,
mSystemStatusAnimationSchedulerLazy::get);
mProviders.put(PrivacyDotViewController.class, mPrivacyDotViewControllerLazy::get);
- mProviders.put(EdgeBackGestureHandler.class, mEdgeBackGestureHandler::get);
+ mProviders.put(EdgeBackGestureHandler.Factory.class,
+ mEdgeBackGestureHandlerFactoryLazy::get);
mProviders.put(UiEventLogger.class, mUiEventLogger::get);
mProviders.put(FeatureFlags.class, mFeatureFlagsLazy::get);
+ mProviders.put(StatusBarContentInsetsProvider.class, mContentInsetsProviderLazy::get);
Dependency.setInstance(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java
index 782cd29b0179..6a60afa8eadf 100644
--- a/packages/SystemUI/src/com/android/systemui/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/Prefs.java
@@ -64,10 +64,6 @@ public final class Prefs {
Key.QS_NIGHTDISPLAY_ADDED,
Key.QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT,
Key.SEEN_MULTI_USER,
- Key.HAS_SEEN_RECENTS_SWIPE_UP_ONBOARDING,
- Key.HAS_SEEN_RECENTS_QUICK_SCRUB_ONBOARDING,
- Key.OVERVIEW_OPENED_COUNT,
- Key.OVERVIEW_OPENED_FROM_HOME_COUNT,
Key.SEEN_RINGER_GUIDANCE_COUNT,
Key.QS_HAS_TURNED_OFF_MOBILE_DATA,
Key.TOUCHED_RINGER_TOGGLE,
@@ -109,14 +105,6 @@ public final class Prefs {
*/
String QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT = "QsLongPressTooltipShownCount";
String SEEN_MULTI_USER = "HasSeenMultiUser";
- String OVERVIEW_OPENED_COUNT = "OverviewOpenedCount";
- String OVERVIEW_OPENED_FROM_HOME_COUNT = "OverviewOpenedFromHomeCount";
- String HAS_SEEN_RECENTS_SWIPE_UP_ONBOARDING = "HasSeenRecentsSwipeUpOnboarding";
- String HAS_SEEN_RECENTS_QUICK_SCRUB_ONBOARDING = "HasSeenRecentsQuickScrubOnboarding";
- String DISMISSED_RECENTS_SWIPE_UP_ONBOARDING_COUNT =
- "DismissedRecentsSwipeUpOnboardingCount";
- String HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE =
- "HasDismissedRecentsQuickScrubOnboardingOnce";
String SEEN_RINGER_GUIDANCE_COUNT = "RingerGuidanceCount";
String QS_TILE_SPECS_REVEALED = "QsTileSpecsRevealed";
String QS_HAS_TURNED_OFF_MOBILE_DATA = "QsHasTurnedOffMobileData";
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 71e2bb657de4..0ce1846e7745 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -37,6 +37,7 @@ import android.hardware.biometrics.BiometricManager.BiometricMultiSensorMode;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.IBiometricSysuiReceiver;
import android.hardware.biometrics.PromptInfo;
+import android.hardware.display.DisplayManager;
import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.fingerprint.FingerprintManager;
@@ -57,6 +58,7 @@ import com.android.internal.os.SomeArgs;
import com.android.systemui.SystemUI;
import com.android.systemui.assist.ui.DisplayUtils;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.DozeReceiver;
import com.android.systemui.statusbar.CommandQueue;
@@ -423,7 +425,9 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
@Nullable FingerprintManager fingerprintManager,
@Nullable FaceManager faceManager,
Provider<UdfpsController> udfpsControllerFactory,
- Provider<SidefpsController> sidefpsControllerFactory) {
+ Provider<SidefpsController> sidefpsControllerFactory,
+ @NonNull DisplayManager displayManager,
+ @Main Handler handler) {
super(context);
mCommandQueue = commandQueue;
mActivityTaskManager = activityTaskManager;
@@ -432,10 +436,13 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
mUdfpsControllerFactory = udfpsControllerFactory;
mSidefpsControllerFactory = sidefpsControllerFactory;
mWindowManager = windowManager;
- mOrientationListener = new BiometricOrientationEventListener(context, () -> {
- onOrientationChanged();
- return Unit.INSTANCE;
- });
+ mOrientationListener = new BiometricOrientationEventListener(context,
+ () -> {
+ onOrientationChanged();
+ return Unit.INSTANCE;
+ },
+ displayManager,
+ handler);
mFaceProps = mFaceManager != null ? mFaceManager.getSensorPropertiesInternal() : null;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricOrientationEventListener.kt b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricOrientationEventListener.kt
index 08ea857eb208..98a03a1c444b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricOrientationEventListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricOrientationEventListener.kt
@@ -17,7 +17,10 @@
package com.android.systemui.biometrics
import android.content.Context
+import android.hardware.display.DisplayManager
+import android.os.Handler
import android.view.OrientationEventListener
+import android.view.Surface
/**
* An [OrientationEventListener] that invokes the [onOrientationChanged] callback whenever
@@ -26,20 +29,16 @@ import android.view.OrientationEventListener
*/
class BiometricOrientationEventListener(
private val context: Context,
- private val onOrientationChanged: () -> Unit
-) : OrientationEventListener(context) {
+ private val onOrientationChanged: () -> Unit,
+ private val displayManager: DisplayManager,
+ private val handler: Handler
+) : DisplayManager.DisplayListener {
- /** If actively listening (not available in base class). */
- var enabled: Boolean = false
- private set
-
- private var lastRotation = context.display?.rotation ?: ORIENTATION_UNKNOWN
-
- override fun onOrientationChanged(orientation: Int) {
- if (orientation == ORIENTATION_UNKNOWN) {
- return
- }
+ private var lastRotation = context.display?.rotation ?: Surface.ROTATION_0
+ override fun onDisplayAdded(displayId: Int) {}
+ override fun onDisplayRemoved(displayId: Int) {}
+ override fun onDisplayChanged(displayId: Int) {
val rotation = context.display?.rotation ?: return
if (lastRotation != rotation) {
lastRotation = rotation
@@ -48,13 +47,11 @@ class BiometricOrientationEventListener(
}
}
- override fun enable() {
- enabled = true
- super.enable()
+ fun enable() {
+ displayManager.registerDisplayListener(this, handler)
}
- override fun disable() {
- enabled = false
- super.disable()
+ fun disable() {
+ displayManager.unregisterDisplayListener(this)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java
index a51c2b802b91..8f6e2498a00b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java
@@ -23,9 +23,11 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.PixelFormat;
+import android.hardware.display.DisplayManager;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.ISidefpsController;
+import android.os.Handler;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
@@ -93,16 +95,22 @@ public class SidefpsController {
@NonNull LayoutInflater inflater,
@Nullable FingerprintManager fingerprintManager,
@NonNull WindowManager windowManager,
- @Main DelayableExecutor fgExecutor) {
+ @Main DelayableExecutor fgExecutor,
+ @NonNull DisplayManager displayManager,
+ @Main Handler handler) {
mContext = context;
mInflater = inflater;
mFingerprintManager = checkNotNull(fingerprintManager);
mWindowManager = windowManager;
mFgExecutor = fgExecutor;
- mOrientationListener = new BiometricOrientationEventListener(context, () -> {
- onOrientationChanged();
- return Unit.INSTANCE;
- });
+ mOrientationListener = new BiometricOrientationEventListener(
+ context,
+ () -> {
+ onOrientationChanged();
+ return Unit.INSTANCE;
+ },
+ displayManager,
+ handler);
mSensorProps = findFirstSidefps();
checkArgument(mSensorProps != null);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index ab3e042e9da7..950bd8319755 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -32,6 +32,7 @@ import android.content.IntentFilter;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.RectF;
+import android.hardware.display.DisplayManager;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IUdfpsOverlayController;
@@ -40,6 +41,7 @@ import android.media.AudioAttributes;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
@@ -67,8 +69,10 @@ import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.concurrency.Execution;
@@ -106,6 +110,7 @@ public class UdfpsController implements DozeReceiver {
private final DelayableExecutor mFgExecutor;
@NonNull private final StatusBar mStatusBar;
@NonNull private final StatusBarStateController mStatusBarStateController;
+ @NonNull private final KeyguardStateController mKeyguardStateController;
@NonNull private final StatusBarKeyguardViewManager mKeyguardViewManager;
@NonNull private final DumpManager mDumpManager;
@NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@@ -117,6 +122,7 @@ public class UdfpsController implements DozeReceiver {
@NonNull private final AccessibilityManager mAccessibilityManager;
@NonNull private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
@Nullable private final UdfpsHbmProvider mHbmProvider;
+ @NonNull private final KeyguardBypassController mKeyguardBypassController;
@VisibleForTesting @NonNull final BiometricOrientationEventListener mOrientationListener;
// Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
// sensors, this, in addition to a lot of the code here, will be updated.
@@ -148,6 +154,7 @@ public class UdfpsController implements DozeReceiver {
private boolean mScreenOn;
private Runnable mAodInterruptRunnable;
private boolean mOnFingerDown;
+ private boolean mAttemptedToDismissKeyguard;
@VisibleForTesting
public static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES =
@@ -379,8 +386,12 @@ public class UdfpsController implements DozeReceiver {
// ACTION_DOWN, in that case we should just reuse the old instance.
mVelocityTracker.clear();
}
- if (isWithinSensorArea(udfpsView, event.getX(), event.getY(), fromUdfpsView)) {
+
+ boolean withinSensorArea =
+ isWithinSensorArea(udfpsView, event.getX(), event.getY(), fromUdfpsView);
+ if (withinSensorArea) {
Trace.beginAsyncSection("UdfpsController.e2e.onPointerDown", 0);
+ Log.v(TAG, "onTouch | action down");
// The pointer that causes ACTION_DOWN is always at index 0.
// We need to persist its ID to track it during ACTION_MOVE that could include
// data for many other pointers because of multi-touch support.
@@ -388,6 +399,14 @@ public class UdfpsController implements DozeReceiver {
mVelocityTracker.addMovement(event);
handled = true;
}
+ if ((withinSensorArea || fromUdfpsView) && shouldTryToDismissKeyguard()) {
+ Log.v(TAG, "onTouch | dismiss keyguard ACTION_DOWN");
+ if (!mOnFingerDown) {
+ playStartHaptic();
+ }
+ mKeyguardViewManager.notifyKeyguardAuthenticated(false /* strongAuth */);
+ mAttemptedToDismissKeyguard = true;
+ }
Trace.endSection();
break;
@@ -398,8 +417,20 @@ public class UdfpsController implements DozeReceiver {
? event.getPointerId(0)
: event.findPointerIndex(mActivePointerId);
if (idx == event.getActionIndex()) {
- if (isWithinSensorArea(udfpsView, event.getX(idx), event.getY(idx),
- fromUdfpsView)) {
+ boolean actionMoveWithinSensorArea =
+ isWithinSensorArea(udfpsView, event.getX(idx), event.getY(idx),
+ fromUdfpsView);
+ if ((fromUdfpsView || actionMoveWithinSensorArea)
+ && shouldTryToDismissKeyguard()) {
+ Log.v(TAG, "onTouch | dismiss keyguard ACTION_MOVE");
+ if (!mOnFingerDown) {
+ playStartHaptic();
+ }
+ mKeyguardViewManager.notifyKeyguardAuthenticated(false /* strongAuth */);
+ mAttemptedToDismissKeyguard = true;
+ break;
+ }
+ if (actionMoveWithinSensorArea) {
if (mVelocityTracker == null) {
// touches could be injected, so the velocity tracker may not have
// been initialized (via ACTION_DOWN).
@@ -448,6 +479,7 @@ public class UdfpsController implements DozeReceiver {
mVelocityTracker = null;
}
Log.v(TAG, "onTouch | finger up");
+ mAttemptedToDismissKeyguard = false;
onFingerUp();
mFalsingManager.isFalseTouch(UDFPS_AUTHENTICATION);
Trace.endSection();
@@ -459,6 +491,13 @@ public class UdfpsController implements DozeReceiver {
return handled;
}
+ private boolean shouldTryToDismissKeyguard() {
+ return mView.getAnimationViewController() != null
+ && mView.getAnimationViewController() instanceof UdfpsKeyguardViewController
+ && mKeyguardStateController.canDismissLockScreen()
+ && !mAttemptedToDismissKeyguard;
+ }
+
@Inject
public UdfpsController(@NonNull Context context,
@NonNull Execution execution,
@@ -479,7 +518,11 @@ public class UdfpsController implements DozeReceiver {
@NonNull ScreenLifecycle screenLifecycle,
@Nullable Vibrator vibrator,
@NonNull UdfpsHapticsSimulator udfpsHapticsSimulator,
- @NonNull Optional<UdfpsHbmProvider> hbmProvider) {
+ @NonNull Optional<UdfpsHbmProvider> hbmProvider,
+ @NonNull KeyguardStateController keyguardStateController,
+ @NonNull KeyguardBypassController keyguardBypassController,
+ @NonNull DisplayManager displayManager,
+ @Main Handler mainHandler) {
mContext = context;
mExecution = execution;
// TODO (b/185124905): inject main handler and vibrator once done prototyping
@@ -493,6 +536,7 @@ public class UdfpsController implements DozeReceiver {
mFgExecutor = fgExecutor;
mStatusBar = statusBar;
mStatusBarStateController = statusBarStateController;
+ mKeyguardStateController = keyguardStateController;
mKeyguardViewManager = statusBarKeyguardViewManager;
mDumpManager = dumpManager;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
@@ -504,10 +548,15 @@ public class UdfpsController implements DozeReceiver {
mHbmProvider = hbmProvider.orElse(null);
screenLifecycle.addObserver(mScreenObserver);
mScreenOn = screenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_ON;
- mOrientationListener = new BiometricOrientationEventListener(context, () -> {
- onOrientationChanged();
- return Unit.INSTANCE;
- });
+ mOrientationListener = new BiometricOrientationEventListener(
+ context,
+ () -> {
+ onOrientationChanged();
+ return Unit.INSTANCE;
+ },
+ displayManager,
+ mainHandler);
+ mKeyguardBypassController = keyguardBypassController;
mSensorProps = findFirstUdfps();
// At least one UDFPS sensor exists
@@ -539,7 +588,12 @@ public class UdfpsController implements DozeReceiver {
@VisibleForTesting
public void playStartHaptic() {
if (mVibrator != null) {
- mVibrator.vibrate(EFFECT_CLICK, VIBRATION_SONIFICATION_ATTRIBUTES);
+ mVibrator.vibrate(
+ Process.myUid(),
+ mContext.getOpPackageName(),
+ EFFECT_CLICK,
+ "udfps-onStart",
+ VIBRATION_SONIFICATION_ATTRIBUTES);
}
}
@@ -615,7 +669,8 @@ public class UdfpsController implements DozeReceiver {
// Transform dimensions if the device is in landscape mode
switch (mContext.getDisplay().getRotation()) {
case Surface.ROTATION_90:
- if (animation instanceof UdfpsKeyguardViewController) {
+ if (animation instanceof UdfpsKeyguardViewController
+ && mKeyguardUpdateMonitor.isGoingToSleep()) {
break;
}
mCoreLayoutParams.x = mSensorProps.sensorLocationY - mSensorProps.sensorRadius
@@ -625,7 +680,8 @@ public class UdfpsController implements DozeReceiver {
break;
case Surface.ROTATION_270:
- if (animation instanceof UdfpsKeyguardViewController) {
+ if (animation instanceof UdfpsKeyguardViewController
+ && mKeyguardUpdateMonitor.isGoingToSleep()) {
break;
}
mCoreLayoutParams.x = p.x - mSensorProps.sensorLocationY - mSensorProps.sensorRadius
@@ -667,6 +723,7 @@ public class UdfpsController implements DozeReceiver {
mView.setSensorProperties(mSensorProps);
mView.setHbmProvider(mHbmProvider);
UdfpsAnimationViewController animation = inflateUdfpsAnimation(reason);
+ mAttemptedToDismissKeyguard = false;
animation.init();
mView.setAnimationViewController(animation);
mOrientationListener.enable();
@@ -826,12 +883,17 @@ public class UdfpsController implements DozeReceiver {
private void onFingerDown(int x, int y, float minor, float major) {
mExecution.assertIsMainThread();
+ mKeyguardBypassController.setUserHasDeviceEntryIntent(true);
if (mView == null) {
Log.w(TAG, "Null view in onFingerDown");
return;
}
if (!mOnFingerDown) {
playStartHaptic();
+
+ if (!mKeyguardUpdateMonitor.isFaceDetectionRunning()) {
+ mKeyguardUpdateMonitor.requestFaceAuth(/* userInitiatedRequest */ false);
+ }
}
mOnFingerDown = true;
mFingerprintManager.onPointerDown(mSensorProps.sensorId, x, y, minor, major);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java
index 412b77698159..6a918a6c8d39 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java
@@ -21,11 +21,8 @@ import android.annotation.Nullable;
import android.content.Context;
import android.graphics.PointF;
import android.hardware.fingerprint.IUdfpsOverlayController;
-import android.media.AudioAttributes;
import android.os.Build;
import android.os.UserHandle;
-import android.os.VibrationEffect;
-import android.os.Vibrator;
import android.provider.Settings;
import android.util.Log;
import android.util.TypedValue;
@@ -50,12 +47,6 @@ public class UdfpsEnrollHelper {
// Enroll with two center touches before going to guided enrollment
private static final int NUM_CENTER_TOUCHES = 2;
- private static final AudioAttributes VIBRATION_SONFICATION_ATTRIBUTES =
- new AudioAttributes.Builder()
- .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
- .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
- .build();
-
interface Listener {
void onEnrollmentProgress(int remaining, int totalSteps);
void onLastStepAcquired();
@@ -66,9 +57,6 @@ public class UdfpsEnrollHelper {
private final int mEnrollReason;
private final boolean mAccessibilityEnabled;
@NonNull private final List<PointF> mGuidedEnrollmentPoints;
- @NonNull private final Vibrator mVibrator;
- @NonNull private final VibrationEffect mEffectClick =
- VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
private int mTotalSteps = -1;
private int mRemainingSteps = -1;
@@ -82,7 +70,6 @@ public class UdfpsEnrollHelper {
public UdfpsEnrollHelper(@NonNull Context context, int reason) {
mContext = context;
mEnrollReason = reason;
- mVibrator = context.getSystemService(Vibrator.class);
final AccessibilityManager am = context.getSystemService(AccessibilityManager.class);
mAccessibilityEnabled = am.isEnabled();
@@ -141,7 +128,6 @@ public class UdfpsEnrollHelper {
if (remaining != mRemainingSteps) {
mLocationsEnrolled++;
- vibrateSuccess();
}
mRemainingSteps = remaining;
@@ -202,11 +188,6 @@ public class UdfpsEnrollHelper {
if (mRemainingSteps <= 2 && mRemainingSteps >= 0) {
mListener.onLastStepAcquired();
- vibrateSuccess();
}
}
-
- private void vibrateSuccess() {
- mVibrator.vibrate(mEffectClick, VIBRATION_SONFICATION_ATTRIBUTES);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
index 131618442c22..eb02aa0d9cdf 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
@@ -162,7 +162,12 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
}
void updateColor() {
+ mWallpaperTextColor = Utils.getColorAttrDefaultColor(mContext,
+ R.attr.wallpaperTextColorAccent);
+ mTextColorPrimary = Utils.getColorAttrDefaultColor(mContext,
+ android.R.attr.textColorPrimary);
mLockScreenFp.invalidate();
+ mBgProtection.setBackground(getContext().getDrawable(R.drawable.fingerprint_bg));
}
private boolean showingUdfpsBouncer() {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index 51124fb28ad1..6435bdd69872 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -377,6 +377,9 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
@Override
public boolean onTouch(MotionEvent event) {
+ if (mTransitionToFullShadeProgress != 0) {
+ return false;
+ }
return mUdfpsController.onTouch(event);
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
index c241c083a0a3..4104e3184efd 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
@@ -64,16 +64,12 @@ class ControlsActivity @Inject constructor(
}
}
- override fun onStart() {
- super.onStart()
+ override fun onResume() {
+ super.onResume()
parent = requireViewById<ViewGroup>(R.id.global_actions_controls)
parent.alpha = 0f
uiController.show(parent, { finish() }, this)
- }
-
- override fun onResume() {
- super.onResume()
ControlsAnimations.enterAnimation(parent).start()
}
@@ -82,8 +78,8 @@ class ControlsActivity @Inject constructor(
finish()
}
- override fun onStop() {
- super.onStop()
+ override fun onPause() {
+ super.onPause()
uiController.hide()
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
index 5acb3038b91b..06e74821869e 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
@@ -669,11 +669,6 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene
int userId = user.id;
- // No lockdown option if it's not turned on in Settings
- if (mSecureSettings.getIntForUser(Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0, userId) == 0) {
- return false;
- }
-
// Lockdown is meaningless without a place to go.
if (!mKeyguardStateController.isMethodSecure()) {
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 26f38ddd5919..cb11454e44ee 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -1047,10 +1047,6 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
// Returns true if the bar mode is changed.
private boolean updateBarMode(int barMode) {
if (mNavigationBarMode != barMode) {
- if (mNavigationBarMode == MODE_TRANSPARENT
- || mNavigationBarMode == MODE_LIGHTS_OUT_TRANSPARENT) {
- mNavigationBarView.hideRecentsOnboarding();
- }
mNavigationBarMode = barMode;
checkNavBarModes();
if (mAutoHideController != null) {
@@ -1620,6 +1616,11 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
+ // TODO(193941146): Currently unregistering a receiver through BroadcastDispatcher is
+ // async, but we've already cleared the fields. Just return early in this case.
+ if (mNavigationBarView == null) {
+ return;
+ }
String action = intent.getAction();
if (Intent.ACTION_SCREEN_OFF.equals(action)
|| Intent.ACTION_SCREEN_ON.equals(action)) {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index 4816f1cf8d6a..61e803312b55 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -81,7 +81,6 @@ import com.android.systemui.navigationbar.gestural.FloatingRotationButton;
import com.android.systemui.navigationbar.gestural.RegionSamplingHelper;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.RecentsOnboarding;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.SysUiStatsLog;
@@ -163,7 +162,6 @@ public class NavigationBarView extends FrameLayout implements
private Configuration mTmpLastConfiguration;
private NavigationBarInflaterView mNavigationInflaterView;
- private RecentsOnboarding mRecentsOnboarding;
private NotificationPanelViewController mPanelView;
private RotationContextButton mRotationContextButton;
private FloatingRotationButton mFloatingRotationButton;
@@ -322,7 +320,6 @@ public class NavigationBarView extends FrameLayout implements
updateRotationButton();
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
- mRecentsOnboarding = new RecentsOnboarding(context, mOverviewProxyService);
mConfiguration = new Configuration();
mTmpLastConfiguration = new Configuration();
@@ -342,7 +339,8 @@ public class NavigationBarView extends FrameLayout implements
mNavColorSampleMargin = getResources()
.getDimensionPixelSize(R.dimen.navigation_handle_sample_horizontal_margin);
- mEdgeBackGestureHandler = Dependency.get(EdgeBackGestureHandler.class);
+ mEdgeBackGestureHandler = Dependency.get(EdgeBackGestureHandler.Factory.class)
+ .create(mContext);
mEdgeBackGestureHandler.setStateChangeCallback(this::updateStates);
mRegionSamplingHelper = new RegionSamplingHelper(this,
new RegionSamplingHelper.SamplingCallback() {
@@ -696,7 +694,6 @@ public class NavigationBarView extends FrameLayout implements
updateNavButtonIcons();
updateSlippery();
- setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
updateDisabledSystemUiStateFlags();
}
@@ -872,7 +869,6 @@ public class NavigationBarView extends FrameLayout implements
updateSlippery();
reloadNavIcons();
updateNavButtonIcons();
- setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
WindowManagerWrapper.getInstance().setNavBarVirtualKeyHapticFeedbackEnabled(!showSwipeUpUI);
getHomeButton().setAccessibilityDelegate(
showSwipeUpUI ? mQuickStepAccessibilityDelegate : null);
@@ -916,7 +912,6 @@ public class NavigationBarView extends FrameLayout implements
mNavBarMode = mode;
mBarTransitions.onNavigationModeChanged(mNavBarMode);
mEdgeBackGestureHandler.onNavigationModeChanged(mNavBarMode);
- mRecentsOnboarding.onNavigationModeChanged(mNavBarMode);
updateRotationButton();
if (isGesturalMode(mNavBarMode)) {
@@ -932,10 +927,6 @@ public class NavigationBarView extends FrameLayout implements
mContextualButtonGroup.setButtonVisibility(R.id.accessibility_button, visible);
}
- void hideRecentsOnboarding() {
- mRecentsOnboarding.hide(true);
- }
-
@Override
public void onFinishInflate() {
super.onFinishInflate();
@@ -980,7 +971,6 @@ public class NavigationBarView extends FrameLayout implements
super.onLayout(changed, left, top, right, bottom);
notifyActiveTouchRegions();
- mRecentsOnboarding.setNavBarHeight(getMeasuredHeight());
}
/**
@@ -1196,7 +1186,6 @@ public class NavigationBarView extends FrameLayout implements
updateIcons(mTmpLastConfiguration);
updateRecentsIcon();
mEdgeBackGestureHandler.onConfigurationChanged(mConfiguration);
- mRecentsOnboarding.onConfigurationChanged(mConfiguration);
if (uiCarModeChanged || mTmpLastConfiguration.densityDpi != mConfiguration.densityDpi
|| mTmpLastConfiguration.getLayoutDirection() != mConfiguration.getLayoutDirection()) {
// If car mode or density changes, we need to reset the icons.
@@ -1260,7 +1249,6 @@ public class NavigationBarView extends FrameLayout implements
requestApplyInsets();
reorient();
onNavigationModeChanged(mNavBarMode);
- setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
if (mRotationButtonController != null) {
mRotationButtonController.registerListeners();
}
@@ -1276,7 +1264,6 @@ public class NavigationBarView extends FrameLayout implements
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
Dependency.get(NavigationModeController.class).removeListener(this);
- setUpSwipeUpOnboarding(false);
for (int i = 0; i < mButtonDispatchers.size(); ++i) {
mButtonDispatchers.valueAt(i).onDestroy();
}
@@ -1293,14 +1280,6 @@ public class NavigationBarView extends FrameLayout implements
mOnComputeInternalInsetsListener);
}
- private void setUpSwipeUpOnboarding(boolean connectedToOverviewProxy) {
- if (connectedToOverviewProxy) {
- mRecentsOnboarding.onConnectedToLauncher();
- } else {
- mRecentsOnboarding.onDisconnectedFromLauncher();
- }
- }
-
public void dump(PrintWriter pw) {
final Rect r = new Rect();
final Point size = new Point();
@@ -1344,7 +1323,6 @@ public class NavigationBarView extends FrameLayout implements
}
mBarTransitions.dump(pw);
mContextualButtonGroup.dump(pw);
- mRecentsOnboarding.dump(pw);
mRegionSamplingHelper.dump(pw);
mEdgeBackGestureHandler.dump(pw);
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index ff5d0b157c80..aaa3bf0f40ee 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -58,7 +58,6 @@ import com.android.internal.policy.GestureNavigationSettingsObserver;
import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.NavigationBarView;
@@ -92,7 +91,6 @@ import javax.inject.Inject;
/**
* Utility class to handle edge swipes for back gesture
*/
-@SysUISingleton
public class EdgeBackGestureHandler extends CurrentUserTracker
implements PluginListener<NavigationEdgeBackPlugin>, ProtoTraceable<SystemUiTraceProto> {
@@ -294,8 +292,8 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
}
};
- @Inject
- public EdgeBackGestureHandler(Context context, OverviewProxyService overviewProxyService,
+
+ EdgeBackGestureHandler(Context context, OverviewProxyService overviewProxyService,
SysUiState sysUiState, PluginManager pluginManager, @Main Executor executor,
BroadcastDispatcher broadcastDispatcher, ProtoTracer protoTracer,
NavigationModeController navigationModeController, ViewConfiguration viewConfiguration,
@@ -919,6 +917,9 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
pw.println(" mGestureLogInsideInsets=" + String.join("\n", mGestureLogInsideInsets));
pw.println(" mGestureLogOutsideInsets=" + String.join("\n", mGestureLogOutsideInsets));
pw.println(" mEdgeBackPlugin=" + mEdgeBackPlugin);
+ if (mEdgeBackPlugin != null) {
+ mEdgeBackPlugin.dump(pw);
+ }
}
private boolean isGestureBlockingActivityRunning() {
@@ -941,6 +942,53 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
proto.edgeBackGestureHandler.allowGesture = mAllowGesture;
}
+ /**
+ * Injectable instance to create a new EdgeBackGestureHandler.
+ *
+ * Necessary because we don't have good handling of per-display contexts at the moment. With
+ * this, you can pass in a specific context that knows what display it is in.
+ */
+ public static class Factory {
+ private final OverviewProxyService mOverviewProxyService;
+ private final SysUiState mSysUiState;
+ private final PluginManager mPluginManager;
+ private final Executor mExecutor;
+ private final BroadcastDispatcher mBroadcastDispatcher;
+ private final ProtoTracer mProtoTracer;
+ private final NavigationModeController mNavigationModeController;
+ private final ViewConfiguration mViewConfiguration;
+ private final WindowManager mWindowManager;
+ private final IWindowManager mWindowManagerService;
+ private final FalsingManager mFalsingManager;
+
+ @Inject
+ public Factory(OverviewProxyService overviewProxyService,
+ SysUiState sysUiState, PluginManager pluginManager, @Main Executor executor,
+ BroadcastDispatcher broadcastDispatcher, ProtoTracer protoTracer,
+ NavigationModeController navigationModeController,
+ ViewConfiguration viewConfiguration, WindowManager windowManager,
+ IWindowManager windowManagerService, FalsingManager falsingManager) {
+ mOverviewProxyService = overviewProxyService;
+ mSysUiState = sysUiState;
+ mPluginManager = pluginManager;
+ mExecutor = executor;
+ mBroadcastDispatcher = broadcastDispatcher;
+ mProtoTracer = protoTracer;
+ mNavigationModeController = navigationModeController;
+ mViewConfiguration = viewConfiguration;
+ mWindowManager = windowManager;
+ mWindowManagerService = windowManagerService;
+ mFalsingManager = falsingManager;
+ }
+
+ /** Construct a {@link EdgeBackGestureHandler}. */
+ public EdgeBackGestureHandler create(Context context) {
+ return new EdgeBackGestureHandler(context, mOverviewProxyService, mSysUiState,
+ mPluginManager, mExecutor, mBroadcastDispatcher, mProtoTracer,
+ mNavigationModeController, mViewConfiguration, mWindowManager,
+ mWindowManagerService, mFalsingManager);
+ }
+ }
private static class LogArray extends ArrayDeque<String> {
private final int mLength;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
index 9c82989531aa..7fdb79eae2a9 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
@@ -30,6 +30,7 @@ import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
+import android.os.Handler;
import android.os.SystemClock;
import android.os.VibrationEffect;
import android.util.Log;
@@ -56,13 +57,18 @@ import com.android.systemui.animation.Interpolators;
import com.android.systemui.plugins.NavigationEdgeBackPlugin;
import com.android.systemui.statusbar.VibratorHelper;
+import java.io.PrintWriter;
+
public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPlugin {
private static final String TAG = "NavigationBarEdgePanel";
+ private static final boolean ENABLE_FAILSAFE = true;
+
private static final long COLOR_ANIMATION_DURATION_MS = 120;
private static final long DISAPPEAR_FADE_ANIMATION_DURATION_MS = 80;
private static final long DISAPPEAR_ARROW_ANIMATION_DURATION_MS = 100;
+ private static final long FAILSAFE_DELAY_MS = 200;
/**
* The time required since the first vibration effect to automatically trigger a click
@@ -215,6 +221,9 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl
private long mVibrationTime;
private int mScreenSize;
+ private final Handler mHandler = new Handler();
+ private final Runnable mFailsafeRunnable = this::onFailsafe;
+
private DynamicAnimation.OnAnimationEndListener mSetGoneEndListener
= new DynamicAnimation.OnAnimationEndListener() {
@Override
@@ -364,6 +373,7 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl
@Override
public void onDestroy() {
+ cancelFailsafe();
mWindowManager.removeView(this);
mRegionSamplingHelper.stop();
mRegionSamplingHelper = null;
@@ -635,6 +645,8 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl
animate().alpha(0f).setDuration(DISAPPEAR_FADE_ANIMATION_DURATION_MS)
.withEndAction(() -> setVisibility(GONE));
mArrowDisappearAnimation.start();
+ // Schedule failsafe in case alpha end callback is not called
+ scheduleFailsafe();
};
if (mTranslationAnimation.isRunning()) {
mTranslationAnimation.addEndListener(new DynamicAnimation.OnAnimationEndListener() {
@@ -648,6 +660,8 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl
}
}
});
+ // Schedule failsafe in case mTranslationAnimation end callback is not called
+ scheduleFailsafe();
} else {
translationEnd.run();
}
@@ -658,6 +672,8 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl
if (mTranslationAnimation.isRunning()) {
mTranslationAnimation.addEndListener(mSetGoneEndListener);
+ // Schedule failsafe in case mTranslationAnimation end callback is not called
+ scheduleFailsafe();
} else {
setVisibility(GONE);
}
@@ -683,6 +699,7 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl
mTotalTouchDelta = 0;
mVibrationTime = 0;
setDesiredVerticalTransition(0, false /* animated */);
+ cancelFailsafe();
}
private void handleMoveEvent(MotionEvent event) {
@@ -867,7 +884,37 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl
invalidate();
}
+ private void scheduleFailsafe() {
+ if (!ENABLE_FAILSAFE) {
+ return;
+ }
+ cancelFailsafe();
+ mHandler.postDelayed(mFailsafeRunnable, FAILSAFE_DELAY_MS);
+ }
+
+ private void cancelFailsafe() {
+ mHandler.removeCallbacks(mFailsafeRunnable);
+ }
+
+ private void onFailsafe() {
+ setVisibility(GONE);
+ }
+
private float dp(float dp) {
return mDensity * dp;
}
+
+ @Override
+ public void dump(PrintWriter pw) {
+ pw.println("NavigationBarEdgePanel:");
+ pw.println(" mIsLeftPanel=" + mIsLeftPanel);
+ pw.println(" mTriggerBack=" + mTriggerBack);
+ pw.println(" mDragSlopPassed=" + mDragSlopPassed);
+ pw.println(" mCurrentAngle=" + mCurrentAngle);
+ pw.println(" mDesiredAngle=" + mDesiredAngle);
+ pw.println(" mCurrentTranslation=" + mCurrentTranslation);
+ pw.println(" mDesiredTranslation=" + mDesiredTranslation);
+ pw.println(" mTranslationAnimation running=" + mTranslationAnimation.isRunning());
+ mRegionSamplingHelper.dump(pw);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java b/packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java
index e4f5cde37f1d..d94cd28c3bc6 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java
+++ b/packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java
@@ -53,6 +53,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.LinkedList;
import java.util.List;
import javax.inject.Inject;
@@ -88,6 +89,9 @@ public class TvOngoingPrivacyChip extends SystemUI implements PrivacyItemControl
private static final int STATE_COLLAPSED = 3;
private static final int STATE_DISAPPEARING = 4;
+ // Avoid multiple messages after rapid changes such as starting/stopping both camera and mic.
+ private static final int ACCESSIBILITY_ANNOUNCEMENT_DELAY_MS = 500;
+
private static final int EXPANDED_DURATION_MS = 4000;
public final int mAnimationDurationMs;
@@ -113,6 +117,9 @@ public class TvOngoingPrivacyChip extends SystemUI implements PrivacyItemControl
private final Handler mUiThreadHandler = new Handler(Looper.getMainLooper());
private final Runnable mCollapseRunnable = this::collapseChip;
+ private final Runnable mAccessibilityRunnable = this::makeAccessibilityAnnouncement;
+ private final List<PrivacyItem> mItemsBeforeLastAnnouncement = new LinkedList<>();
+
@State
private int mState = STATE_NOT_SHOWN;
@@ -169,6 +176,8 @@ public class TvOngoingPrivacyChip extends SystemUI implements PrivacyItemControl
}
mPrivacyItems = updatedPrivacyItems;
+
+ postAccessibilityAnnouncement();
updateChip();
}
@@ -301,6 +310,7 @@ public class TvOngoingPrivacyChip extends SystemUI implements PrivacyItemControl
mIndicatorView.getViewTreeObserver().removeOnGlobalLayoutListener(
this);
+ postAccessibilityAnnouncement();
animateIconAppearance();
mChipDrawable.startInitialFadeIn();
}
@@ -460,6 +470,83 @@ public class TvOngoingPrivacyChip extends SystemUI implements PrivacyItemControl
}
/**
+ * Schedules the accessibility announcement to be made after {@code
+ * ACCESSIBILITY_ANNOUNCEMENT_DELAY_MS} (if possible). This is so that only one announcement is
+ * made instead of two separate ones if both the camera and the mic are started/stopped.
+ */
+ private void postAccessibilityAnnouncement() {
+ mUiThreadHandler.removeCallbacks(mAccessibilityRunnable);
+
+ if (mPrivacyItems.size() == 0) {
+ // Announce immediately since announcement cannot be made once the chip is gone.
+ makeAccessibilityAnnouncement();
+ } else {
+ mUiThreadHandler.postDelayed(mAccessibilityRunnable,
+ ACCESSIBILITY_ANNOUNCEMENT_DELAY_MS);
+ }
+ }
+
+ private void makeAccessibilityAnnouncement() {
+ if (mIndicatorView == null) {
+ return;
+ }
+
+ boolean cameraWasRecording = listContainsPrivacyType(mItemsBeforeLastAnnouncement,
+ PrivacyType.TYPE_CAMERA);
+ boolean cameraIsRecording = listContainsPrivacyType(mPrivacyItems,
+ PrivacyType.TYPE_CAMERA);
+ boolean micWasRecording = listContainsPrivacyType(mItemsBeforeLastAnnouncement,
+ PrivacyType.TYPE_MICROPHONE);
+ boolean micIsRecording = listContainsPrivacyType(mPrivacyItems,
+ PrivacyType.TYPE_MICROPHONE);
+
+ int announcement = 0;
+ if (!cameraWasRecording && cameraIsRecording && !micWasRecording && micIsRecording) {
+ // Both started
+ announcement = R.string.mic_and_camera_recording_announcement;
+ } else if (cameraWasRecording && !cameraIsRecording && micWasRecording && !micIsRecording) {
+ // Both stopped
+ announcement = R.string.mic_camera_stopped_recording_announcement;
+ } else {
+ // Did the camera start or stop?
+ if (cameraWasRecording && !cameraIsRecording) {
+ announcement = R.string.camera_stopped_recording_announcement;
+ } else if (!cameraWasRecording && cameraIsRecording) {
+ announcement = R.string.camera_recording_announcement;
+ }
+
+ // Announce camera changes now since we might need a second announcement about the mic.
+ if (announcement != 0) {
+ mIndicatorView.announceForAccessibility(mContext.getString(announcement));
+ announcement = 0;
+ }
+
+ // Did the mic start or stop?
+ if (micWasRecording && !micIsRecording) {
+ announcement = R.string.mic_stopped_recording_announcement;
+ } else if (!micWasRecording && micIsRecording) {
+ announcement = R.string.mic_recording_announcement;
+ }
+ }
+
+ if (announcement != 0) {
+ mIndicatorView.announceForAccessibility(mContext.getString(announcement));
+ }
+
+ mItemsBeforeLastAnnouncement.clear();
+ mItemsBeforeLastAnnouncement.addAll(mPrivacyItems);
+ }
+
+ private boolean listContainsPrivacyType(List<PrivacyItem> list, PrivacyType privacyType) {
+ for (PrivacyItem item : list) {
+ if (item.getPrivacyType() == privacyType) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Used in debug logs.
*/
private String stateToString(@State int state) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 03a2c843a15e..cd9db614e477 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -32,6 +32,8 @@ import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.Space;
+import androidx.annotation.NonNull;
+
import com.android.settingslib.Utils;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.R;
@@ -41,6 +43,8 @@ import com.android.systemui.statusbar.phone.StatusBarWindowView;
import com.android.systemui.statusbar.phone.StatusIconContainer;
import com.android.systemui.statusbar.policy.Clock;
+import java.util.List;
+
/**
* View that contains the top-most bits of the QS panel (primarily the status bar with date, time,
* battery, carrier info and privacy icons) and also contains the {@link QuickQSPanel}.
@@ -86,18 +90,13 @@ public class QuickStatusBarHeader extends FrameLayout {
private float mKeyguardExpansionFraction;
private int mTextColorPrimary = Color.TRANSPARENT;
private int mTopViewMeasureHeight;
- private boolean mProviderModel;
- private final String mMobileSlotName;
- private final String mNoCallingSlotName;
- private final String mCallStrengthSlotName;
+ @NonNull
+ private List<String> mRssiIgnoredSlots;
+ private boolean mIsSingleCarrier;
public QuickStatusBarHeader(Context context, AttributeSet attrs) {
super(context, attrs);
- mMobileSlotName = context.getString(com.android.internal.R.string.status_bar_mobile);
- mNoCallingSlotName = context.getString(com.android.internal.R.string.status_bar_no_calling);
- mCallStrengthSlotName =
- context.getString(com.android.internal.R.string.status_bar_call_strength);
}
/**
@@ -148,9 +147,9 @@ public class QuickStatusBarHeader extends FrameLayout {
void onAttach(TintedIconManager iconManager,
QSExpansionPathInterpolator qsExpansionPathInterpolator,
- boolean providerModel) {
- mProviderModel = providerModel;
+ List<String> rssiIgnoredSlots) {
mTintedIconManager = iconManager;
+ mRssiIgnoredSlots = rssiIgnoredSlots;
int fillColor = Utils.getColorAttrDefaultColor(getContext(),
android.R.attr.textColorPrimary);
@@ -161,6 +160,11 @@ public class QuickStatusBarHeader extends FrameLayout {
updateAnimators();
}
+ void setIsSingleCarrier(boolean isSingleCarrier) {
+ mIsSingleCarrier = isSingleCarrier;
+ updateAlphaAnimator();
+ }
+
public QuickQSPanel getHeaderQsPanel() {
return mHeaderQsPanel;
}
@@ -267,39 +271,26 @@ public class QuickStatusBarHeader extends FrameLayout {
.setListener(new TouchAnimator.ListenerAdapter() {
@Override
public void onAnimationAtEnd() {
- // TODO(b/185580157): Remove the mProviderModel if the mobile slot can be
- // hidden in Provider model.
- if (mProviderModel) {
- mIconContainer.addIgnoredSlot(mNoCallingSlotName);
- mIconContainer.addIgnoredSlot(mCallStrengthSlotName);
- } else {
- mIconContainer.addIgnoredSlot(mMobileSlotName);
+ super.onAnimationAtEnd();
+ if (!mIsSingleCarrier) {
+ mIconContainer.addIgnoredSlots(mRssiIgnoredSlots);
}
}
@Override
public void onAnimationStarted() {
- if (mProviderModel) {
- mIconContainer.addIgnoredSlot(mNoCallingSlotName);
- mIconContainer.addIgnoredSlot(mCallStrengthSlotName);
- } else {
- mIconContainer.addIgnoredSlot(mMobileSlotName);
- }
-
setSeparatorVisibility(false);
+ if (!mIsSingleCarrier) {
+ mIconContainer.addIgnoredSlots(mRssiIgnoredSlots);
+ }
}
@Override
public void onAnimationAtStart() {
super.onAnimationAtStart();
- if (mProviderModel) {
- mIconContainer.removeIgnoredSlot(mNoCallingSlotName);
- mIconContainer.removeIgnoredSlot(mCallStrengthSlotName);
- } else {
- mIconContainer.removeIgnoredSlot(mMobileSlotName);
- }
-
setSeparatorVisibility(mShowClockIconsSeparator);
+ // In QQS we never ignore RSSI.
+ mIconContainer.removeIgnoredSlots(mRssiIgnoredSlots);
}
});
mAlphaAnimator = builder.build();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
index fcf1302b8fb4..b8b7f42455bb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
@@ -43,7 +43,6 @@ import com.android.systemui.statusbar.phone.StatusIconContainer;
import com.android.systemui.statusbar.policy.Clock;
import com.android.systemui.util.ViewController;
-import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
@@ -76,6 +75,9 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
private boolean mMicCameraIndicatorsEnabled;
private boolean mLocationIndicatorsEnabled;
private boolean mPrivacyChipLogged;
+ private final String mCameraSlot;
+ private final String mMicSlot;
+ private final String mLocationSlot;
private SysuiColorExtractor mColorExtractor;
private ColorExtractor.OnColorsChangedListener mOnColorsChangedListener;
@@ -104,8 +106,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
}
private void update() {
- StatusIconContainer iconContainer = mView.requireViewById(R.id.statusIcons);
- iconContainer.setIgnoredSlots(getIgnoredIconSlots());
+ updatePrivacyIconSlots();
setChipVisibility(!mPrivacyChip.getPrivacyList().isEmpty());
}
};
@@ -154,7 +155,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
mClockView = mView.findViewById(R.id.clock);
mIconContainer = mView.findViewById(R.id.statusIcons);
- mIconManager = new StatusBarIconController.TintedIconManager(mIconContainer, mFeatureFlags);
+ mIconManager = new StatusBarIconController.TintedIconManager(mIconContainer, featureFlags);
mDemoModeReceiver = new ClockDemoModeReceiver(mClockView);
mColorExtractor = colorExtractor;
mOnColorsChangedListener = (extractor, which) -> {
@@ -162,6 +163,10 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
mClockView.onColorsChanged(lightTheme);
};
mColorExtractor.addOnColorsChangedListener(mOnColorsChangedListener);
+
+ mCameraSlot = getResources().getString(com.android.internal.R.string.status_bar_camera);
+ mMicSlot = getResources().getString(com.android.internal.R.string.status_bar_microphone);
+ mLocationSlot = getResources().getString(com.android.internal.R.string.status_bar_location);
}
@Override
@@ -172,14 +177,30 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
mLocationIndicatorsEnabled = mPrivacyItemController.getLocationAvailable();
// Ignore privacy icons because they show in the space above QQS
- mIconContainer.setIgnoredSlots(getIgnoredIconSlots());
+ updatePrivacyIconSlots();
mIconContainer.setShouldRestrictIcons(false);
mStatusBarIconController.addIconGroup(mIconManager);
setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE);
- mView.onAttach(mIconManager, mQSExpansionPathInterpolator,
- mFeatureFlags.isCombinedStatusBarSignalIconsEnabled());
+ mView.setIsSingleCarrier(mQSCarrierGroupController.isSingleCarrier());
+ mQSCarrierGroupController
+ .setOnSingleCarrierChangedListener(mView::setIsSingleCarrier);
+
+ List<String> rssiIgnoredSlots;
+
+ if (mFeatureFlags.isCombinedStatusBarSignalIconsEnabled()) {
+ rssiIgnoredSlots = List.of(
+ getResources().getString(com.android.internal.R.string.status_bar_no_calling),
+ getResources().getString(com.android.internal.R.string.status_bar_call_strength)
+ );
+ } else {
+ rssiIgnoredSlots = List.of(
+ getResources().getString(com.android.internal.R.string.status_bar_mobile)
+ );
+ }
+
+ mView.onAttach(mIconManager, mQSExpansionPathInterpolator, rssiIgnoredSlots);
mDemoModeController.addCallback(mDemoModeReceiver);
}
@@ -189,6 +210,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
mColorExtractor.removeOnColorsChangedListener(mOnColorsChangedListener);
mPrivacyChip.setOnClickListener(null);
mStatusBarIconController.removeIconGroup(mIconManager);
+ mQSCarrierGroupController.setOnSingleCarrierChangedListener(null);
mDemoModeController.removeCallback(mDemoModeReceiver);
setListening(false);
}
@@ -236,21 +258,25 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
mView.setChipVisibility(chipVisible);
}
- private List<String> getIgnoredIconSlots() {
- ArrayList<String> ignored = new ArrayList<>();
+ private void updatePrivacyIconSlots() {
if (getChipEnabled()) {
if (mMicCameraIndicatorsEnabled) {
- ignored.add(mView.getResources().getString(
- com.android.internal.R.string.status_bar_camera));
- ignored.add(mView.getResources().getString(
- com.android.internal.R.string.status_bar_microphone));
+ mIconContainer.addIgnoredSlot(mCameraSlot);
+ mIconContainer.addIgnoredSlot(mMicSlot);
+ } else {
+ mIconContainer.removeIgnoredSlot(mCameraSlot);
+ mIconContainer.removeIgnoredSlot(mMicSlot);
}
if (mLocationIndicatorsEnabled) {
- ignored.add(mView.getResources().getString(
- com.android.internal.R.string.status_bar_location));
+ mIconContainer.addIgnoredSlot(mLocationSlot);
+ } else {
+ mIconContainer.removeIgnoredSlot(mLocationSlot);
}
+ } else {
+ mIconContainer.removeIgnoredSlot(mCameraSlot);
+ mIconContainer.removeIgnoredSlot(mMicSlot);
+ mIconContainer.removeIgnoredSlot(mLocationSlot);
}
- return ignored;
}
private boolean getChipEnabled() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java
index d6fa21646402..32ac73375f1d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java
@@ -25,6 +25,8 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
+import androidx.annotation.VisibleForTesting;
+
import com.android.settingslib.Utils;
import com.android.settingslib.graph.SignalDrawable;
import com.android.systemui.R;
@@ -37,8 +39,10 @@ public class QSCarrier extends LinearLayout {
private TextView mCarrierText;
private ImageView mMobileSignal;
private ImageView mMobileRoaming;
+ private View mSpacer;
private CellSignalState mLastSignalState;
private boolean mProviderModelInitialized = false;
+ private boolean mIsSingleCarrier;
public QSCarrier(Context context) {
super(context);
@@ -63,18 +67,25 @@ public class QSCarrier extends LinearLayout {
mMobileRoaming = findViewById(R.id.mobile_roaming);
mMobileSignal = findViewById(R.id.mobile_signal);
mCarrierText = findViewById(R.id.qs_carrier_text);
+ mSpacer = findViewById(R.id.spacer);
}
/**
* Update the state of this view
* @param state the current state of the signal for this view
+ * @param isSingleCarrier whether there is a single carrier being shown in the container
* @return true if the state was actually changed
*/
- public boolean updateState(CellSignalState state) {
- if (Objects.equals(state, mLastSignalState)) return false;
+ public boolean updateState(CellSignalState state, boolean isSingleCarrier) {
+ if (Objects.equals(state, mLastSignalState) && isSingleCarrier == mIsSingleCarrier) {
+ return false;
+ }
mLastSignalState = state;
- mMobileGroup.setVisibility(state.visible ? View.VISIBLE : View.GONE);
- if (state.visible) {
+ mIsSingleCarrier = isSingleCarrier;
+ final boolean visible = state.visible && !isSingleCarrier;
+ mMobileGroup.setVisibility(visible ? View.VISIBLE : View.GONE);
+ mSpacer.setVisibility(isSingleCarrier ? View.VISIBLE : View.GONE);
+ if (visible) {
mMobileRoaming.setVisibility(state.roaming ? View.VISIBLE : View.GONE);
ColorStateList colorStateList = Utils.getColorAttr(mContext,
android.R.attr.textColorPrimary);
@@ -125,6 +136,11 @@ public class QSCarrier extends LinearLayout {
com.android.settingslib.R.string.not_default_data_content_description));
}
+ @VisibleForTesting
+ View getRSSIView() {
+ return mMobileGroup;
+ }
+
public void setCarrierText(CharSequence text) {
mCarrierText.setText(text);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java
index f23c0580c409..67c4d33d53d3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java
@@ -37,6 +37,7 @@ import com.android.keyguard.CarrierTextManager;
import com.android.settingslib.AccessibilityContentDescriptions;
import com.android.settingslib.mobile.TelephonyIcons;
import com.android.systemui.R;
+import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -62,7 +63,8 @@ public class QSCarrierGroupController {
private final NetworkController mNetworkController;
private final CarrierTextManager mCarrierTextManager;
private final TextView mNoSimTextView;
- private final H mMainHandler;
+ // Non final for testing
+ private H mMainHandler;
private final Callback mCallback;
private boolean mListening;
private final CellSignalState[] mInfos =
@@ -74,6 +76,11 @@ public class QSCarrierGroupController {
private final boolean mProviderModel;
private final CarrierConfigTracker mCarrierConfigTracker;
+ private boolean mIsSingleCarrier;
+ private OnSingleCarrierChangedListener mOnSingleCarrierChangedListener;
+
+ private final SlotIndexResolver mSlotIndexResolver;
+
private final NetworkController.SignalCallback mSignalCallback =
new NetworkController.SignalCallback() {
@Override
@@ -207,7 +214,8 @@ public class QSCarrierGroupController {
@Background Handler bgHandler, @Main Looper mainLooper,
NetworkController networkController,
CarrierTextManager.Builder carrierTextManagerBuilder, Context context,
- CarrierConfigTracker carrierConfigTracker, FeatureFlags featureFlags) {
+ CarrierConfigTracker carrierConfigTracker, FeatureFlags featureFlags,
+ SlotIndexResolver slotIndexResolver) {
if (featureFlags.isCombinedStatusBarSignalIconsEnabled()) {
mProviderModel = true;
@@ -222,6 +230,7 @@ public class QSCarrierGroupController {
.setShowMissingSim(false)
.build();
mCarrierConfigTracker = carrierConfigTracker;
+ mSlotIndexResolver = slotIndexResolver;
View.OnClickListener onClickListener = v -> {
if (!v.isVisibleToUser()) {
return;
@@ -256,6 +265,7 @@ public class QSCarrierGroupController {
.toString();
mCarrierGroups[i].setOnClickListener(onClickListener);
}
+ mIsSingleCarrier = computeIsSingleCarrier();
view.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@@ -272,10 +282,24 @@ public class QSCarrierGroupController {
@VisibleForTesting
protected int getSlotIndex(int subscriptionId) {
- return SubscriptionManager.getSlotIndex(subscriptionId);
+ return mSlotIndexResolver.getSlotIndex(subscriptionId);
+ }
+
+ /**
+ * Sets a {@link OnSingleCarrierChangedListener}.
+ *
+ * This will get notified when the number of carriers changes between 1 and "not one".
+ * @param listener
+ */
+ public void setOnSingleCarrierChangedListener(OnSingleCarrierChangedListener listener) {
+ mOnSingleCarrierChangedListener = listener;
+ }
+
+ public boolean isSingleCarrier() {
+ return mIsSingleCarrier;
}
- private boolean isSingleCarrier() {
+ private boolean computeIsSingleCarrier() {
int carrierCount = 0;
for (int i = 0; i < SIM_SLOTS; i++) {
@@ -315,7 +339,9 @@ public class QSCarrierGroupController {
return;
}
- if (isSingleCarrier()) {
+ boolean singleCarrier = computeIsSingleCarrier();
+
+ if (singleCarrier) {
for (int i = 0; i < SIM_SLOTS; i++) {
if (mInfos[i].visible
&& mInfos[i].mobileSignalIconId == R.drawable.ic_qs_sim_card) {
@@ -326,7 +352,7 @@ public class QSCarrierGroupController {
}
for (int i = 0; i < SIM_SLOTS; i++) {
- mCarrierGroups[i].updateState(mInfos[i]);
+ mCarrierGroups[i].updateState(mInfos[i], singleCarrier);
}
mCarrierDividers[0].setVisibility(
@@ -337,6 +363,12 @@ public class QSCarrierGroupController {
mCarrierDividers[1].setVisibility(
(mInfos[1].visible && mInfos[2].visible)
|| (mInfos[0].visible && mInfos[2].visible) ? View.VISIBLE : View.GONE);
+ if (mIsSingleCarrier != singleCarrier) {
+ mIsSingleCarrier = singleCarrier;
+ if (mOnSingleCarrierChangedListener != null) {
+ mOnSingleCarrierChangedListener.onSingleCarrierChanged(singleCarrier);
+ }
+ }
}
@MainThread
@@ -433,12 +465,14 @@ public class QSCarrierGroupController {
private final Context mContext;
private final CarrierConfigTracker mCarrierConfigTracker;
private final FeatureFlags mFeatureFlags;
+ private final SlotIndexResolver mSlotIndexResolver;
@Inject
public Builder(ActivityStarter activityStarter, @Background Handler handler,
@Main Looper looper, NetworkController networkController,
CarrierTextManager.Builder carrierTextControllerBuilder, Context context,
- CarrierConfigTracker carrierConfigTracker, FeatureFlags featureFlags) {
+ CarrierConfigTracker carrierConfigTracker, FeatureFlags featureFlags,
+ SlotIndexResolver slotIndexResolver) {
mActivityStarter = activityStarter;
mHandler = handler;
mLooper = looper;
@@ -447,6 +481,7 @@ public class QSCarrierGroupController {
mContext = context;
mCarrierConfigTracker = carrierConfigTracker;
mFeatureFlags = featureFlags;
+ mSlotIndexResolver = slotIndexResolver;
}
public Builder setQSCarrierGroup(QSCarrierGroup view) {
@@ -457,7 +492,43 @@ public class QSCarrierGroupController {
public QSCarrierGroupController build() {
return new QSCarrierGroupController(mView, mActivityStarter, mHandler, mLooper,
mNetworkController, mCarrierTextControllerBuilder, mContext,
- mCarrierConfigTracker, mFeatureFlags);
+ mCarrierConfigTracker, mFeatureFlags, mSlotIndexResolver);
+ }
+ }
+
+ /**
+ * Notify when the state changes from 1 carrier to "not one" and viceversa
+ */
+ @FunctionalInterface
+ public interface OnSingleCarrierChangedListener {
+ void onSingleCarrierChanged(boolean isSingleCarrier);
+ }
+
+ /**
+ * Interface for resolving slot index from subscription ID.
+ */
+ @FunctionalInterface
+ public interface SlotIndexResolver {
+ /**
+ * Get slot index for given sub id.
+ */
+ int getSlotIndex(int subscriptionId);
+ }
+
+ /**
+ * Default implementation for {@link SlotIndexResolver}.
+ *
+ * It retrieves the slot index using {@link SubscriptionManager#getSlotIndex}.
+ */
+ @SysUISingleton
+ public static class SubscriptionManagerSlotIndexResolver implements SlotIndexResolver {
+
+ @Inject
+ public SubscriptionManagerSlotIndexResolver() {}
+
+ @Override
+ public int getSlotIndex(int subscriptionId) {
+ return SubscriptionManager.getSlotIndex(subscriptionId);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
index 34aac492dc30..4d633492ed76 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
@@ -33,6 +33,7 @@ import com.android.systemui.qs.QSFragment;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QuickQSPanel;
import com.android.systemui.qs.QuickStatusBarHeader;
+import com.android.systemui.qs.carrier.QSCarrierGroupController;
import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.statusbar.phone.MultiUserSwitch;
@@ -146,4 +147,8 @@ public interface QSFragmentModule {
return useQsMediaPlayer(context);
}
+ /** */
+ @Binds
+ QSCarrierGroupController.SlotIndexResolver provideSlotIndexResolver(
+ QSCarrierGroupController.SubscriptionManagerSlotIndexResolver impl);
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
index de3be78e5463..6d1bbeed5372 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
@@ -89,5 +89,4 @@ public interface QSModule {
/** */
@Binds
QSHost provideQsHost(QSTileHost controllerImpl);
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 1d791f5d632c..d262412d5182 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -40,6 +40,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.systemui.broadcast.BroadcastDispatcher;
+import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -204,9 +205,14 @@ public class TileLifecycleManager extends BroadcastReceiver implements
if (DEBUG) Log.d(TAG, "Unbinding service " + mIntent + " " + mUser);
// Give it another chance next time it needs to be bound, out of kindness.
mBindTryCount = 0;
- mWrapper = null;
+ freeWrapper();
if (mIsBound) {
- mContext.unbindService(this);
+ try {
+ mContext.unbindService(this);
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to unbind service "
+ + mIntent.getComponent().flattenToShortString(), e);
+ }
mIsBound = false;
}
}
@@ -290,7 +296,9 @@ public class TileLifecycleManager extends BroadcastReceiver implements
private void handleDeath() {
if (mWrapper == null) return;
- mWrapper = null;
+ freeWrapper();
+ // Clearly not bound anymore
+ mIsBound = false;
if (!mBound) return;
if (DEBUG) Log.d(TAG, "handleDeath");
if (checkComponentState()) {
@@ -472,6 +480,18 @@ public class TileLifecycleManager extends BroadcastReceiver implements
return mToken;
}
+ private void freeWrapper() {
+ if (mWrapper != null) {
+ try {
+ mWrapper.asBinder().unlinkToDeath(this, 0);
+ } catch (NoSuchElementException e) {
+ Log.w(TAG, "Trying to unlink not linked recipient for component"
+ + mIntent.getComponent().flattenToShortString());
+ }
+ mWrapper = null;
+ }
+ }
+
public interface TileChangeListener {
void onTileChanged(ComponentName tile);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
index 45c71744e0ec..fa2d4447f26d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
@@ -17,6 +17,7 @@
package com.android.systemui.qs.tiles;
import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
+import static android.os.UserManager.DISALLOW_CAMERA_TOGGLE;
import static com.android.systemui.DejankUtils.whitelistIpcs;
@@ -86,4 +87,9 @@ public class CameraToggleTile extends SensorPrivacyToggleTile {
public @Sensor int getSensorId() {
return CAMERA;
}
+
+ @Override
+ public String getRestriction() {
+ return DISALLOW_CAMERA_TOGGLE;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java
index 48a1ad673d76..f4f0b2cdc432 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java
@@ -17,6 +17,7 @@
package com.android.systemui.qs.tiles;
import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
+import static android.os.UserManager.DISALLOW_MICROPHONE_TOGGLE;
import static com.android.systemui.DejankUtils.whitelistIpcs;
@@ -86,4 +87,9 @@ public class MicrophoneToggleTile extends SensorPrivacyToggleTile {
public @Sensor int getSensorId() {
return MICROPHONE;
}
+
+ @Override
+ public String getRestriction() {
+ return DISALLOW_MICROPHONE_TOGGLE;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
index ab81ac1fd577..82b6c0c1805d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
@@ -153,25 +153,9 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> {
});
}
- @Nullable
- private CharSequence getServiceLabelSafe() {
- try {
- return mController.getWalletClient().getServiceLabel();
- } catch (RuntimeException e) {
- Log.e(TAG, "Failed to get the service label safely, recreating wallet client", e);
- mController.reCreateWalletClient();
- try {
- return mController.getWalletClient().getServiceLabel();
- } catch (RuntimeException e2) {
- Log.e(TAG, "The QAW service label is broken.", e2);
- return null;
- }
- }
- }
-
@Override
protected void handleUpdateState(State state, Object arg) {
- CharSequence label = getServiceLabelSafe();
+ CharSequence label = mController.getWalletClient().getServiceLabel();
state.label = label == null ? mLabel : label;
state.contentDescription = state.label;
Drawable tileIcon = mController.getWalletClient().getTileIcon();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java
index bf72b7728232..b0a1b18a8cd5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java
@@ -22,6 +22,7 @@ import android.content.Intent;
import android.hardware.SensorPrivacyManager.Sensors.Sensor;
import android.os.Handler;
import android.os.Looper;
+import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.view.View;
import android.widget.Switch;
@@ -63,6 +64,11 @@ public abstract class SensorPrivacyToggleTile extends QSTileImpl<QSTile.BooleanS
*/
public abstract @DrawableRes int getIconRes(boolean isBlocked);
+ /**
+ * @return the user restriction name
+ */
+ public abstract String getRestriction();
+
protected SensorPrivacyToggleTile(QSHost host,
@Background Looper backgroundLooper,
@Main Handler mainHandler,
@@ -103,6 +109,8 @@ public abstract class SensorPrivacyToggleTile extends QSTileImpl<QSTile.BooleanS
boolean isBlocked = arg == null ? mSensorPrivacyController.isSensorBlocked(getSensorId())
: (boolean) arg;
+ checkIfRestrictionEnforcedByAdminOnly(state, getRestriction());
+
state.icon = ResourceIcon.get(getIconRes(isBlocked));
state.state = isBlocked ? Tile.STATE_INACTIVE : Tile.STATE_ACTIVE;
state.value = !isBlocked;
@@ -112,7 +120,6 @@ public abstract class SensorPrivacyToggleTile extends QSTileImpl<QSTile.BooleanS
} else {
state.secondaryLabel = mContext.getString(R.string.quick_settings_camera_mic_available);
}
- state.handlesLongClick = false;
state.contentDescription = state.label;
state.expandedAccessibilityClassName = Switch.class.getName();
}
@@ -124,7 +131,7 @@ public abstract class SensorPrivacyToggleTile extends QSTileImpl<QSTile.BooleanS
@Override
public Intent getLongClickIntent() {
- return null;
+ return new Intent(Settings.ACTION_PRIVACY_SETTINGS);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
deleted file mode 100644
index 310ecbc01bf0..000000000000
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ /dev/null
@@ -1,586 +0,0 @@
-/*
- * Copyright (C) 2018 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.systemui.recents;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
-
-import static com.android.systemui.Prefs.Key.DISMISSED_RECENTS_SWIPE_UP_ONBOARDING_COUNT;
-import static com.android.systemui.Prefs.Key.HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE;
-import static com.android.systemui.Prefs.Key.HAS_SEEN_RECENTS_QUICK_SCRUB_ONBOARDING;
-import static com.android.systemui.Prefs.Key.HAS_SEEN_RECENTS_SWIPE_UP_ONBOARDING;
-import static com.android.systemui.Prefs.Key.OVERVIEW_OPENED_COUNT;
-import static com.android.systemui.Prefs.Key.OVERVIEW_OPENED_FROM_HOME_COUNT;
-import static com.android.systemui.shared.system.LauncherEventUtil.DISMISS;
-import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_QUICK_SCRUB_ONBOARDING_TIP;
-import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_SWIPE_UP_ONBOARDING_TIP;
-import static com.android.systemui.shared.system.LauncherEventUtil.VISIBLE;
-
-import android.annotation.StringRes;
-import android.annotation.TargetApi;
-import android.app.ActivityManager;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.CornerPathEffect;
-import android.graphics.Paint;
-import android.graphics.PixelFormat;
-import android.graphics.drawable.ShapeDrawable;
-import android.os.Build;
-import android.os.RemoteException;
-import android.os.SystemProperties;
-import android.os.UserManager;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.view.animation.AccelerateInterpolator;
-import android.view.animation.DecelerateInterpolator;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.Prefs;
-import com.android.systemui.R;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.shared.recents.IOverviewProxy;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.QuickStepContract;
-import com.android.systemui.shared.system.TaskStackChangeListener;
-import com.android.systemui.shared.system.TaskStackChangeListeners;
-
-import java.io.PrintWriter;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Shows onboarding for the new recents interaction in P (codenamed quickstep).
- */
-@TargetApi(Build.VERSION_CODES.P)
-public class RecentsOnboarding {
-
- private static final String TAG = "RecentsOnboarding";
- private static final boolean RESET_PREFS_FOR_DEBUG = false;
- private static final boolean ONBOARDING_ENABLED = true;
- private static final long SHOW_DELAY_MS = 500;
- private static final long SHOW_DURATION_MS = 300;
- private static final long HIDE_DURATION_MS = 100;
- // Show swipe-up tips after opening overview from home this number of times.
- private static final int SWIPE_UP_SHOW_ON_OVERVIEW_OPENED_FROM_HOME_COUNT = 3;
- // Show quick scrub tips after opening overview this number of times.
- private static final int QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT = 10;
- // Maximum number of dismissals while still showing swipe-up tips.
- private static final int MAX_DISMISSAL_ON_SWIPE_UP_SHOW = 2;
- // Number of dismissals for swipe-up tips when exponential backoff starts.
- private static final int BACKOFF_DISMISSAL_COUNT_ON_SWIPE_UP_SHOW = 1;
- // After explicitly dismissing for <= BACKOFF_DISMISSAL_COUNT_ON_SWIPE_UP_SHOW times, show again
- // after launching this number of apps for swipe-up tips.
- private static final int SWIPE_UP_SHOW_ON_APP_LAUNCH_AFTER_DISMISS = 5;
- // After explicitly dismissing for > BACKOFF_DISMISSAL_COUNT_ON_SWIPE_UP_SHOW but
- // <= MAX_DISMISSAL_ON_SWIPE_UP_SHOW times, show again after launching this number of apps for
- // swipe-up tips.
- private static final int SWIPE_UP_SHOW_ON_APP_LAUNCH_AFTER_DISMISS_BACK_OFF = 40;
-
- private final Context mContext;
- private final WindowManager mWindowManager;
- private final OverviewProxyService mOverviewProxyService;
- private Set<String> mBlacklistedPackages;
- private final View mLayout;
- private final TextView mTextView;
- private final ImageView mDismissView;
- private final View mArrowView;
- private final int mOnboardingToastColor;
- private final int mOnboardingToastArrowRadius;
- private int mNavBarHeight;
- private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
-
- private boolean mOverviewProxyListenerRegistered;
- private boolean mTaskListenerRegistered;
- private boolean mLayoutAttachedToWindow;
- private boolean mHasDismissedSwipeUpTip;
- private boolean mHasDismissedQuickScrubTip;
- private int mNumAppsLaunchedSinceSwipeUpTipDismiss;
- private int mOverviewOpenedCountSinceQuickScrubTipDismiss;
-
- private final TaskStackChangeListener mTaskListener = new TaskStackChangeListener() {
- private String mLastPackageName;
-
- @Override
- public void onTaskCreated(int taskId, ComponentName componentName) {
- onAppLaunch();
- }
-
- @Override
- public void onTaskMovedToFront(int taskId) {
- onAppLaunch();
- }
-
- private void onAppLaunch() {
- ActivityManager.RunningTaskInfo info = ActivityManagerWrapper.getInstance()
- .getRunningTask();
- if (info == null || info.baseActivity == null) {
- return;
- }
- if (mBlacklistedPackages.contains(info.baseActivity.getPackageName())) {
- hide(true);
- return;
- }
- if (info.baseActivity.getPackageName().equals(mLastPackageName)) {
- return;
- }
- mLastPackageName = info.baseActivity.getPackageName();
- int activityType = info.configuration.windowConfiguration.getActivityType();
- if (activityType == ACTIVITY_TYPE_STANDARD) {
- boolean alreadySeenSwipeUpOnboarding = hasSeenSwipeUpOnboarding();
- boolean alreadySeenQuickScrubsOnboarding = hasSeenQuickScrubOnboarding();
- if (alreadySeenSwipeUpOnboarding && alreadySeenQuickScrubsOnboarding) {
- onDisconnectedFromLauncher();
- return;
- }
-
- boolean shouldLog = false;
- if (!alreadySeenSwipeUpOnboarding) {
- if (getOpenedOverviewFromHomeCount()
- >= SWIPE_UP_SHOW_ON_OVERVIEW_OPENED_FROM_HOME_COUNT) {
- if (mHasDismissedSwipeUpTip) {
- int hasDimissedSwipeUpOnboardingCount =
- getDismissedSwipeUpOnboardingCount();
- if (hasDimissedSwipeUpOnboardingCount
- > MAX_DISMISSAL_ON_SWIPE_UP_SHOW) {
- return;
- }
- final int swipeUpShowOnAppLauncherAfterDismiss =
- hasDimissedSwipeUpOnboardingCount
- <= BACKOFF_DISMISSAL_COUNT_ON_SWIPE_UP_SHOW
- ? SWIPE_UP_SHOW_ON_APP_LAUNCH_AFTER_DISMISS
- : SWIPE_UP_SHOW_ON_APP_LAUNCH_AFTER_DISMISS_BACK_OFF;
- mNumAppsLaunchedSinceSwipeUpTipDismiss++;
- if (mNumAppsLaunchedSinceSwipeUpTipDismiss
- >= swipeUpShowOnAppLauncherAfterDismiss) {
- mNumAppsLaunchedSinceSwipeUpTipDismiss = 0;
- shouldLog = show(R.string.recents_swipe_up_onboarding);
- }
- } else {
- shouldLog = show(R.string.recents_swipe_up_onboarding);
- }
- if (shouldLog) {
- notifyOnTip(VISIBLE, RECENTS_SWIPE_UP_ONBOARDING_TIP);
- }
- }
- } else {
- if (getOpenedOverviewCount() >= QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT) {
- if (mHasDismissedQuickScrubTip) {
- if (mOverviewOpenedCountSinceQuickScrubTipDismiss
- >= QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT) {
- mOverviewOpenedCountSinceQuickScrubTipDismiss = 0;
- shouldLog = show(R.string.recents_quick_scrub_onboarding);
- }
- } else {
- shouldLog = show(R.string.recents_quick_scrub_onboarding);
- }
- if (shouldLog) {
- notifyOnTip(VISIBLE, RECENTS_QUICK_SCRUB_ONBOARDING_TIP);
- }
- }
-
- }
- } else {
- hide(false);
- }
- }
- };
-
- private OverviewProxyService.OverviewProxyListener mOverviewProxyListener =
- new OverviewProxyService.OverviewProxyListener() {
- @Override
- public void onOverviewShown(boolean fromHome) {
- if (!hasSeenSwipeUpOnboarding() && !fromHome) {
- setHasSeenSwipeUpOnboarding(true);
- }
- if (fromHome) {
- incrementOpenedOverviewFromHomeCount();
- }
- incrementOpenedOverviewCount();
-
- if (getOpenedOverviewCount() >= QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT) {
- if (mHasDismissedQuickScrubTip) {
- mOverviewOpenedCountSinceQuickScrubTipDismiss++;
- }
- }
- }
-
- @Override
- public void onQuickStepStarted() {
- hide(true);
- }
-
- @Override
- public void onQuickScrubStarted() {
- boolean alreadySeenQuickScrubsOnboarding = hasSeenQuickScrubOnboarding();
- if (!alreadySeenQuickScrubsOnboarding) {
- setHasSeenQuickScrubOnboarding(true);
- }
- }
- };
-
- private final View.OnAttachStateChangeListener mOnAttachStateChangeListener
- = new View.OnAttachStateChangeListener() {
-
- private final BroadcastDispatcher mBroadcastDispatcher = Dependency.get(
- BroadcastDispatcher.class);
-
- @Override
- public void onViewAttachedToWindow(View view) {
- if (view == mLayout) {
- mBroadcastDispatcher.registerReceiver(mReceiver,
- new IntentFilter(Intent.ACTION_SCREEN_OFF));
- mLayoutAttachedToWindow = true;
- if (view.getTag().equals(R.string.recents_swipe_up_onboarding)) {
- mHasDismissedSwipeUpTip = false;
- } else {
- mHasDismissedQuickScrubTip = false;
- }
- }
- }
-
- @Override
- public void onViewDetachedFromWindow(View view) {
- if (view == mLayout) {
- mLayoutAttachedToWindow = false;
- if (view.getTag().equals(R.string.recents_quick_scrub_onboarding)) {
- mHasDismissedQuickScrubTip = true;
- if (hasDismissedQuickScrubOnboardingOnce()) {
- // If user dismisses the quick scrub tip twice, we consider user has seen it
- // and do not show it again.
- setHasSeenQuickScrubOnboarding(true);
- } else {
- setHasDismissedQuickScrubOnboardingOnce(true);
- }
- mOverviewOpenedCountSinceQuickScrubTipDismiss = 0;
- }
- mBroadcastDispatcher.unregisterReceiver(mReceiver);
- }
- }
- };
-
- public RecentsOnboarding(Context context, OverviewProxyService overviewProxyService) {
- mContext = context;
- mOverviewProxyService = overviewProxyService;
- final Resources res = context.getResources();
- mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
- mBlacklistedPackages = new HashSet<>();
- Collections.addAll(mBlacklistedPackages, res.getStringArray(
- R.array.recents_onboarding_blacklisted_packages));
- mLayout = LayoutInflater.from(mContext).inflate(R.layout.recents_onboarding, null);
- mTextView = mLayout.findViewById(R.id.onboarding_text);
- mDismissView = mLayout.findViewById(R.id.dismiss);
- mArrowView = mLayout.findViewById(R.id.arrow);
-
- TypedValue typedValue = new TypedValue();
- context.getTheme().resolveAttribute(android.R.attr.colorAccent, typedValue, true);
- mOnboardingToastColor = res.getColor(typedValue.resourceId);
- mOnboardingToastArrowRadius = res.getDimensionPixelSize(
- R.dimen.recents_onboarding_toast_arrow_corner_radius);
-
- mLayout.addOnAttachStateChangeListener(mOnAttachStateChangeListener);
- mDismissView.setOnClickListener(v -> {
- hide(true);
- if (v.getTag().equals(R.string.recents_swipe_up_onboarding)) {
- mHasDismissedSwipeUpTip = true;
- mNumAppsLaunchedSinceSwipeUpTipDismiss = 0;
- setDismissedSwipeUpOnboardingCount(getDismissedSwipeUpOnboardingCount() + 1);
- if (getDismissedSwipeUpOnboardingCount() > MAX_DISMISSAL_ON_SWIPE_UP_SHOW) {
- setHasSeenSwipeUpOnboarding(true);
- }
- notifyOnTip(DISMISS, RECENTS_SWIPE_UP_ONBOARDING_TIP);
- } else {
- notifyOnTip(DISMISS, RECENTS_QUICK_SCRUB_ONBOARDING_TIP);
- }
- });
-
- ViewGroup.LayoutParams arrowLp = mArrowView.getLayoutParams();
- ShapeDrawable arrowDrawable = new ShapeDrawable(TriangleShape.create(
- arrowLp.width, arrowLp.height, false));
- Paint arrowPaint = arrowDrawable.getPaint();
- arrowPaint.setColor(mOnboardingToastColor);
- // The corner path effect won't be reflected in the shadow, but shouldn't be noticeable.
- arrowPaint.setPathEffect(new CornerPathEffect(mOnboardingToastArrowRadius));
- mArrowView.setBackground(arrowDrawable);
-
- if (RESET_PREFS_FOR_DEBUG) {
- setHasSeenSwipeUpOnboarding(false);
- setHasSeenQuickScrubOnboarding(false);
- setDismissedSwipeUpOnboardingCount(0);
- setHasDismissedQuickScrubOnboardingOnce(false);
- setOpenedOverviewCount(0);
- setOpenedOverviewFromHomeCount(0);
- }
- }
-
- private void notifyOnTip(int action, int target) {
- try {
- IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
- if (overviewProxy != null) {
- overviewProxy.onTip(action, target);
- }
- } catch (RemoteException e) {
- }
- }
-
- public void onNavigationModeChanged(int mode) {
- mNavBarMode = mode;
- }
-
- public void onConnectedToLauncher() {
- if (!ONBOARDING_ENABLED || QuickStepContract.isGesturalMode(mNavBarMode)) {
- return;
- }
-
- if (hasSeenSwipeUpOnboarding() && hasSeenQuickScrubOnboarding()) {
- return;
- }
-
- if (!mOverviewProxyListenerRegistered) {
- mOverviewProxyService.addCallback(mOverviewProxyListener);
- mOverviewProxyListenerRegistered = true;
- }
- if (!mTaskListenerRegistered) {
- TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskListener);
- mTaskListenerRegistered = true;
- }
- }
-
- public void onDisconnectedFromLauncher() {
-
- if (mOverviewProxyListenerRegistered) {
- mOverviewProxyService.removeCallback(mOverviewProxyListener);
- mOverviewProxyListenerRegistered = false;
- }
- if (mTaskListenerRegistered) {
- TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskListener);
- mTaskListenerRegistered = false;
- }
-
- mHasDismissedSwipeUpTip = false;
- mHasDismissedQuickScrubTip = false;
- mNumAppsLaunchedSinceSwipeUpTipDismiss = 0;
- mOverviewOpenedCountSinceQuickScrubTipDismiss = 0;
- hide(true);
- }
-
- public void onConfigurationChanged(Configuration newConfiguration) {
- if (newConfiguration.orientation != Configuration.ORIENTATION_PORTRAIT) {
- hide(false);
- }
- }
-
- public boolean show(@StringRes int stringRes) {
- if (!shouldShow()) {
- return false;
- }
- mDismissView.setTag(stringRes);
- mLayout.setTag(stringRes);
- mTextView.setText(stringRes);
- // Only show in portrait.
- int orientation = mContext.getResources().getConfiguration().orientation;
- if (!mLayoutAttachedToWindow && orientation == Configuration.ORIENTATION_PORTRAIT) {
- mLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
-
- final int gravity;
- final int x;
- if (stringRes == R.string.recents_swipe_up_onboarding) {
- gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
- x = 0;
- } else {
- int layoutDirection =
- mContext.getResources().getConfiguration().getLayoutDirection();
- gravity = Gravity.BOTTOM | (layoutDirection == View.LAYOUT_DIRECTION_LTR
- ? Gravity.LEFT : Gravity.RIGHT);
- x = mContext.getResources().getDimensionPixelSize(
- R.dimen.recents_quick_scrub_onboarding_margin_start);
- }
- mWindowManager.addView(mLayout, getWindowLayoutParams(gravity, x));
- mLayout.setAlpha(0);
- mLayout.animate()
- .alpha(1f)
- .withLayer()
- .setStartDelay(SHOW_DELAY_MS)
- .setDuration(SHOW_DURATION_MS)
- .setInterpolator(new DecelerateInterpolator())
- .start();
- return true;
- }
- return false;
- }
-
- /**
- * @return True unless setprop has been set to false, we're in demo mode, or running tests in
- * automation.
- */
- private boolean shouldShow() {
- return SystemProperties.getBoolean("persist.quickstep.onboarding.enabled",
- !(mContext.getSystemService(UserManager.class)).isDemoUser() &&
- !ActivityManager.isRunningInTestHarness());
- }
-
- public void hide(boolean animate) {
- if (mLayoutAttachedToWindow) {
- if (animate) {
- mLayout.animate()
- .alpha(0f)
- .withLayer()
- .setStartDelay(0)
- .setDuration(HIDE_DURATION_MS)
- .setInterpolator(new AccelerateInterpolator())
- .withEndAction(() -> mWindowManager.removeViewImmediate(mLayout))
- .start();
- } else {
- mLayout.animate().cancel();
- mWindowManager.removeViewImmediate(mLayout);
- }
- }
- }
-
- public void setNavBarHeight(int navBarHeight) {
- mNavBarHeight = navBarHeight;
- }
-
- public void dump(PrintWriter pw) {
- pw.println("RecentsOnboarding");
- pw.println(" mTaskListenerRegistered: " + mTaskListenerRegistered);
- pw.println(" mOverviewProxyListenerRegistered: " + mOverviewProxyListenerRegistered);
- pw.println(" mLayoutAttachedToWindow: " + mLayoutAttachedToWindow);
- pw.println(" mHasDismissedSwipeUpTip: " + mHasDismissedSwipeUpTip);
- pw.println(" mHasDismissedQuickScrubTip: " + mHasDismissedQuickScrubTip);
- pw.println(" mNumAppsLaunchedSinceSwipeUpTipDismiss: "
- + mNumAppsLaunchedSinceSwipeUpTipDismiss);
- pw.println(" hasSeenSwipeUpOnboarding: " + hasSeenSwipeUpOnboarding());
- pw.println(" hasSeenQuickScrubOnboarding: " + hasSeenQuickScrubOnboarding());
- pw.println(" getDismissedSwipeUpOnboardingCount: "
- + getDismissedSwipeUpOnboardingCount());
- pw.println(" hasDismissedQuickScrubOnboardingOnce: "
- + hasDismissedQuickScrubOnboardingOnce());
- pw.println(" getOpenedOverviewCount: " + getOpenedOverviewCount());
- pw.println(" getOpenedOverviewFromHomeCount: " + getOpenedOverviewFromHomeCount());
- }
-
- private WindowManager.LayoutParams getWindowLayoutParams(int gravity, int x) {
- int flags = WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT,
- ViewGroup.LayoutParams.WRAP_CONTENT,
- x, -mNavBarHeight / 2,
- WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
- flags,
- PixelFormat.TRANSLUCENT);
- lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
- lp.setTitle("RecentsOnboarding");
- lp.gravity = gravity;
- return lp;
- }
-
- private boolean hasSeenSwipeUpOnboarding() {
- return Prefs.getBoolean(mContext, HAS_SEEN_RECENTS_SWIPE_UP_ONBOARDING, false);
- }
-
- private void setHasSeenSwipeUpOnboarding(boolean hasSeenSwipeUpOnboarding) {
- Prefs.putBoolean(mContext, HAS_SEEN_RECENTS_SWIPE_UP_ONBOARDING, hasSeenSwipeUpOnboarding);
- if (hasSeenSwipeUpOnboarding && hasSeenQuickScrubOnboarding()) {
- onDisconnectedFromLauncher();
- }
- }
-
- private boolean hasSeenQuickScrubOnboarding() {
- return Prefs.getBoolean(mContext, HAS_SEEN_RECENTS_QUICK_SCRUB_ONBOARDING, false);
- }
-
- private void setHasSeenQuickScrubOnboarding(boolean hasSeenQuickScrubOnboarding) {
- Prefs.putBoolean(mContext, HAS_SEEN_RECENTS_QUICK_SCRUB_ONBOARDING,
- hasSeenQuickScrubOnboarding);
- if (hasSeenQuickScrubOnboarding && hasSeenSwipeUpOnboarding()) {
- onDisconnectedFromLauncher();
- }
- }
-
- private int getDismissedSwipeUpOnboardingCount() {
- return Prefs.getInt(mContext, DISMISSED_RECENTS_SWIPE_UP_ONBOARDING_COUNT, 0);
- }
-
- private void setDismissedSwipeUpOnboardingCount(int dismissedSwipeUpOnboardingCount) {
- Prefs.putInt(mContext, DISMISSED_RECENTS_SWIPE_UP_ONBOARDING_COUNT,
- dismissedSwipeUpOnboardingCount);
- }
-
- private boolean hasDismissedQuickScrubOnboardingOnce() {
- return Prefs.getBoolean(mContext, HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE, false);
- }
-
- private void setHasDismissedQuickScrubOnboardingOnce(
- boolean hasDismissedQuickScrubOnboardingOnce) {
- Prefs.putBoolean(mContext, HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE,
- hasDismissedQuickScrubOnboardingOnce);
- }
-
- private int getOpenedOverviewFromHomeCount() {
- return Prefs.getInt(mContext, OVERVIEW_OPENED_FROM_HOME_COUNT, 0);
- }
-
- private void incrementOpenedOverviewFromHomeCount() {
- int openedOverviewFromHomeCount = getOpenedOverviewFromHomeCount();
- if (openedOverviewFromHomeCount >= SWIPE_UP_SHOW_ON_OVERVIEW_OPENED_FROM_HOME_COUNT) {
- return;
- }
- setOpenedOverviewFromHomeCount(openedOverviewFromHomeCount + 1);
- }
-
- private void setOpenedOverviewFromHomeCount(int openedOverviewFromHomeCount) {
- Prefs.putInt(mContext, OVERVIEW_OPENED_FROM_HOME_COUNT, openedOverviewFromHomeCount);
- }
-
- private int getOpenedOverviewCount() {
- return Prefs.getInt(mContext, OVERVIEW_OPENED_COUNT, 0);
- }
-
- private void incrementOpenedOverviewCount() {
- int openedOverviewCount = getOpenedOverviewCount();
- if (openedOverviewCount >= QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT) {
- return;
- }
- setOpenedOverviewCount(openedOverviewCount + 1);
- }
-
- private void setOpenedOverviewCount(int openedOverviewCount) {
- Prefs.putInt(mContext, OVERVIEW_OPENED_COUNT, openedOverviewCount);
- }
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
- hide(false);
- }
- }
- };
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
index aafeabc7c1a2..dce19cf86b35 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
@@ -45,6 +45,8 @@ open class BlurUtils @Inject constructor(
val minBlurRadius = resources.getDimensionPixelSize(R.dimen.min_window_blur_radius)
val maxBlurRadius = resources.getDimensionPixelSize(R.dimen.max_window_blur_radius)
+ private var lastAppliedBlur = 0
+
init {
dumpManager.registerDumpable(javaClass.name, this)
}
@@ -75,17 +77,25 @@ open class BlurUtils @Inject constructor(
*
* @param viewRootImpl The window root.
* @param radius blur radius in pixels.
+ * @param opaque if surface is opaque, regardless or having blurs or no.
*/
- fun applyBlur(viewRootImpl: ViewRootImpl?, radius: Int, opaqueBackground: Boolean) {
+ fun applyBlur(viewRootImpl: ViewRootImpl?, radius: Int, opaque: Boolean) {
if (viewRootImpl == null || !viewRootImpl.surfaceControl.isValid ||
!supportsBlursOnWindows()) {
return
}
createTransaction().use {
it.setBackgroundBlurRadius(viewRootImpl.surfaceControl, radius)
- it.setOpaque(viewRootImpl.surfaceControl, opaqueBackground)
+ it.setOpaque(viewRootImpl.surfaceControl, opaque)
+ if (lastAppliedBlur == 0 && radius != 0) {
+ it.setEarlyWakeupStart()
+ }
+ if (lastAppliedBlur != 0 && radius == 0) {
+ it.setEarlyWakeupEnd()
+ }
it.apply()
}
+ lastAppliedBlur = radius
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 44399a126624..120121ce7f0e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -94,7 +94,7 @@ import javax.inject.Inject;
* Controls the indications and error messages shown on the Keyguard
*/
@SysUISingleton
-public class KeyguardIndicationController implements KeyguardStateController.Callback {
+public class KeyguardIndicationController {
private static final String TAG = "KeyguardIndication";
private static final boolean DEBUG_CHARGING_SPEED = false;
@@ -206,7 +206,7 @@ public class KeyguardIndicationController implements KeyguardStateController.Cal
mKeyguardUpdateMonitor.registerCallback(getKeyguardCallback());
mKeyguardUpdateMonitor.registerCallback(mTickReceiver);
mStatusBarStateController.addCallback(mStatusBarStateListener);
- mKeyguardStateController.addCallback(this);
+ mKeyguardStateController.addCallback(mKeyguardStateCallback);
mStatusBarStateListener.onDozingChanged(mStatusBarStateController.isDozing());
}
@@ -827,11 +827,6 @@ public class KeyguardIndicationController implements KeyguardStateController.Cal
mRotateTextViewController.dump(fd, pw, args);
}
- @Override
- public void onUnlockedChanged() {
- updateIndication(false);
- }
-
protected class BaseKeyguardCallback extends KeyguardUpdateMonitorCallback {
public static final int HIDE_DELAY_MS = 5000;
@@ -967,10 +962,8 @@ public class KeyguardIndicationController implements KeyguardStateController.Cal
}
private boolean shouldSuppressFaceMsgAndShowTryFingerprintMsg() {
- // For dual biometric, don't show face auth messages unless face auth was explicitly
- // requested by the user.
+ // For dual biometric, don't show face auth messages
return mKeyguardUpdateMonitor.isFingerprintDetectionRunning()
- && !mKeyguardUpdateMonitor.isFaceAuthUserRequested()
&& mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
true /* isStrongBiometric */);
}
@@ -1068,4 +1061,20 @@ public class KeyguardIndicationController implements KeyguardStateController.Cal
updateIndication(false);
}
};
+
+ private KeyguardStateController.Callback mKeyguardStateCallback =
+ new KeyguardStateController.Callback() {
+ @Override
+ public void onUnlockedChanged() {
+ updateIndication(false);
+ }
+
+ @Override
+ public void onKeyguardShowingChanged() {
+ if (!mKeyguardStateController.isShowing()) {
+ mTopIndicationView.clearMessages();
+ mLockScreenIndicationView.clearMessages();
+ }
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index 28bdd5fbeb8b..db553e4b093b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -89,6 +89,9 @@ class NotificationShadeDepthController @Inject constructor(
private var prevShadeDirection = 0
private var prevShadeVelocity = 0f
+ // Only for dumpsys
+ private var lastAppliedBlur = 0
+
@VisibleForTesting
var shadeSpring = DepthAnimation()
var shadeAnimation = DepthAnimation()
@@ -201,6 +204,7 @@ class NotificationShadeDepthController @Inject constructor(
val opaque = scrimsVisible && !blursDisabledForAppLaunch
Trace.traceCounter(Trace.TRACE_TAG_APP, "shade_blur_radius", blur)
blurUtils.applyBlur(blurRoot?.viewRootImpl ?: root.viewRootImpl, blur, opaque)
+ lastAppliedBlur = blur
try {
if (root.isAttachedToWindow && root.windowToken != null) {
wallpaperManager.setWallpaperZoomOut(root.windowToken, zoomOut)
@@ -271,6 +275,11 @@ class NotificationShadeDepthController @Inject constructor(
brightnessMirrorSpring.finishIfRunning()
}
}
+
+ override fun onDozeAmountChanged(linear: Float, eased: Float) {
+ wakeAndUnlockBlurRadius = blurUtils.blurRadiusOfRatio(eased)
+ scheduleUpdate()
+ }
}
init {
@@ -428,6 +437,9 @@ class NotificationShadeDepthController @Inject constructor(
it.println("brightnessMirrorRadius: ${brightnessMirrorSpring.radius}")
it.println("wakeAndUnlockBlur: $wakeAndUnlockBlurRadius")
it.println("blursDisabledForAppLaunch: $blursDisabledForAppLaunch")
+ it.println("qsPanelExpansion: $qsPanelExpansion")
+ it.println("transitionToFullShadeProgress: $transitionToFullShadeProgress")
+ it.println("lastAppliedBlur: $lastAppliedBlur")
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
index b6aed23e64ee..180f81c22a9d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
@@ -131,7 +131,7 @@ public class RemoteInputController {
*/
public void removeRemoteInput(NotificationEntry entry, Object token) {
Objects.requireNonNull(entry);
- if (entry.mRemoteEditImeVisible) return;
+ if (entry.mRemoteEditImeVisible && entry.mRemoteEditImeAnimatingAway) return;
// If the view is being removed, this may be called even though we're not active
if (!isRemoteInputActive(entry)) return;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
index 5f10e557faed..29cfb07a14f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
@@ -18,6 +18,8 @@ package com.android.systemui.statusbar.events
import android.animation.Animator
import android.annotation.UiThread
+import android.graphics.Point
+import android.graphics.Rect
import android.util.Log
import android.view.Gravity
import android.view.View
@@ -31,9 +33,16 @@ import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.StatusBarState.SHADE
import com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED
-import com.android.systemui.statusbar.phone.StatusBarLocationPublisher
-import com.android.systemui.statusbar.phone.StatusBarMarginUpdatedListener
+import com.android.systemui.statusbar.phone.StatusBarContentInsetsChangedListener
+import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
+import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.leak.RotationUtils
+import com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE
+import com.android.systemui.util.leak.RotationUtils.ROTATION_NONE
+import com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE
+import com.android.systemui.util.leak.RotationUtils.ROTATION_UPSIDE_DOWN
+import com.android.systemui.util.leak.RotationUtils.Rotation
import java.lang.IllegalStateException
import java.util.concurrent.Executor
@@ -58,7 +67,8 @@ import javax.inject.Inject
class PrivacyDotViewController @Inject constructor(
@Main private val mainExecutor: Executor,
private val stateController: StatusBarStateController,
- private val locationPublisher: StatusBarLocationPublisher,
+ private val configurationController: ConfigurationController,
+ private val contentInsetsProvider: StatusBarContentInsetsProvider,
private val animationScheduler: SystemStatusAnimationScheduler
) {
private var sbHeightPortrait = 0
@@ -84,18 +94,27 @@ class PrivacyDotViewController @Inject constructor(
// Privacy dots are created in ScreenDecoration's UiThread, which is not the main thread
private var uiExecutor: DelayableExecutor? = null
- private val marginListener: StatusBarMarginUpdatedListener =
- object : StatusBarMarginUpdatedListener {
- override fun onStatusBarMarginUpdated(marginLeft: Int, marginRight: Int) {
- setStatusBarMargins(marginLeft, marginRight)
- }
- }
-
private val views: Sequence<View>
get() = if (!this::tl.isInitialized) sequenceOf() else sequenceOf(tl, tr, br, bl)
init {
- locationPublisher.addCallback(marginListener)
+ contentInsetsProvider.addCallback(object : StatusBarContentInsetsChangedListener {
+ override fun onStatusBarContentInsetsChanged() {
+ dlog("onStatusBarContentInsetsChanged: ")
+ setNewLayoutRects()
+ }
+ })
+ configurationController.addCallback(object : ConfigurationController.ConfigurationListener {
+ override fun onLayoutDirectionChanged(isRtl: Boolean) {
+ synchronized(this) {
+ val corner = selectDesignatedCorner(nextViewState.rotation, isRtl)
+ nextViewState = nextViewState.copy(
+ layoutRtl = isRtl,
+ designatedCorner = corner
+ )
+ }
+ }
+ })
stateController.addCallback(object : StatusBarStateController.StateListener {
override fun onExpandedChanged(isExpanded: Boolean) {
@@ -123,16 +142,19 @@ class PrivacyDotViewController @Inject constructor(
fun setNewRotation(rot: Int) {
dlog("updateRotation: $rot")
+ val isRtl: Boolean
synchronized(lock) {
if (rot == nextViewState.rotation) {
return
}
+
+ isRtl = nextViewState.layoutRtl
}
// If we rotated, hide all dotes until the next state resolves
setCornerVisibilities(View.INVISIBLE)
- val newCorner = selectDesignatedCorner(rot)
+ val newCorner = selectDesignatedCorner(rot, isRtl)
val index = newCorner.cornerIndex()
val h = when (rot) {
@@ -222,15 +244,77 @@ class PrivacyDotViewController @Inject constructor(
}
}
+ @UiThread
+ private fun setCornerSizes(state: ViewState) {
+ // StatusBarContentInsetsProvider can tell us the location of the privacy indicator dot
+ // in every rotation. The only thing we need to check is rtl
+ val rtl = state.layoutRtl
+ val size = Point()
+ tl.context.display.getRealSize(size)
+ val currentRotation = RotationUtils.getExactRotation(tl.context)
+
+ val displayWidth: Int
+ val displayHeight: Int
+ if (currentRotation == ROTATION_LANDSCAPE || currentRotation == ROTATION_SEASCAPE) {
+ displayWidth = size.y
+ displayHeight = size.x
+ } else {
+ displayWidth = size.x
+ displayHeight = size.y
+ }
+
+ var rot = activeRotationForCorner(tl, rtl)
+ var contentInsets = state.contentRectForRotation(rot)
+ (tl.layoutParams as FrameLayout.LayoutParams).apply {
+ height = contentInsets.height()
+ if (rtl) {
+ width = contentInsets.left
+ } else {
+ width = displayHeight - contentInsets.right
+ }
+ }
+
+ rot = activeRotationForCorner(tr, rtl)
+ contentInsets = state.contentRectForRotation(rot)
+ (tr.layoutParams as FrameLayout.LayoutParams).apply {
+ height = contentInsets.height()
+ if (rtl) {
+ width = contentInsets.left
+ } else {
+ width = displayWidth - contentInsets.right
+ }
+ }
+
+ rot = activeRotationForCorner(br, rtl)
+ contentInsets = state.contentRectForRotation(rot)
+ (br.layoutParams as FrameLayout.LayoutParams).apply {
+ height = contentInsets.height()
+ if (rtl) {
+ width = contentInsets.left
+ } else {
+ width = displayHeight - contentInsets.right
+ }
+ }
+
+ rot = activeRotationForCorner(bl, rtl)
+ contentInsets = state.contentRectForRotation(rot)
+ (bl.layoutParams as FrameLayout.LayoutParams).apply {
+ height = contentInsets.height()
+ if (rtl) {
+ width = contentInsets.left
+ } else {
+ width = displayWidth - contentInsets.right
+ }
+ }
+ }
+
// Designated view will be the one at statusbar's view.END
@UiThread
- private fun selectDesignatedCorner(r: Int): View? {
+ private fun selectDesignatedCorner(r: Int, isRtl: Boolean): View? {
if (!this::tl.isInitialized) {
return null
}
- val isRtl = tl.isLayoutRtl
-
return when (r) {
0 -> if (isRtl) tl else tr
1 -> if (isRtl) tr else br
@@ -282,6 +366,17 @@ class PrivacyDotViewController @Inject constructor(
return modded
}
+ @Rotation
+ private fun activeRotationForCorner(corner: View, rtl: Boolean): Int {
+ // Each corner will only be visible in a single rotation, based on rtl
+ return when (corner) {
+ tr -> if (rtl) ROTATION_LANDSCAPE else ROTATION_NONE
+ tl -> if (rtl) ROTATION_NONE else ROTATION_SEASCAPE
+ br -> if (rtl) ROTATION_UPSIDE_DOWN else ROTATION_LANDSCAPE
+ else /* bl */ -> if (rtl) ROTATION_SEASCAPE else ROTATION_UPSIDE_DOWN
+ }
+ }
+
private fun widthForCorner(corner: Int, left: Int, right: Int): Int {
return when (corner) {
TOP_LEFT, BOTTOM_LEFT -> left
@@ -303,15 +398,32 @@ class PrivacyDotViewController @Inject constructor(
bl = bottomLeft
br = bottomRight
- val dc = selectDesignatedCorner(0)
+ val rtl = configurationController.isLayoutRtl
+ val dc = selectDesignatedCorner(0, rtl)
+
val index = dc.cornerIndex()
mainExecutor.execute {
animationScheduler.addCallback(systemStatusAnimationCallback)
}
+ val left = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_SEASCAPE)
+ val top = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_NONE)
+ val right = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_LANDSCAPE)
+ val bottom = contentInsetsProvider
+ .getStatusBarContentInsetsForRotation(ROTATION_UPSIDE_DOWN)
+
synchronized(lock) {
- nextViewState = nextViewState.copy(designatedCorner = dc, cornerIndex = index)
+ nextViewState = nextViewState.copy(
+ viewInitialized = true,
+ designatedCorner = dc,
+ cornerIndex = index,
+ seascapeRect = left,
+ portraitRect = top,
+ landscapeRect = right,
+ upsideDownRect = bottom,
+ layoutRtl = rtl
+ )
}
}
@@ -324,19 +436,6 @@ class PrivacyDotViewController @Inject constructor(
sbHeightLandscape = landscape
}
- /**
- * The dot view containers will fill the margin in order to position the dots correctly
- *
- * @param left the space between the status bar contents and the left side of the screen
- * @param right space between the status bar contents and the right side of the screen
- */
- private fun setStatusBarMargins(left: Int, right: Int) {
- dlog("setStatusBarMargins l=$left r=$right")
- synchronized(lock) {
- nextViewState = nextViewState.copy(marginLeft = left, marginRight = right)
- }
- }
-
private fun updateStatusBarState() {
synchronized(lock) {
nextViewState = nextViewState.copy(shadeExpanded = isShadeInQs())
@@ -377,6 +476,11 @@ class PrivacyDotViewController @Inject constructor(
@UiThread
private fun resolveState(state: ViewState) {
dlog("resolveState $state")
+ if (!state.viewInitialized) {
+ dlog("resolveState: view is not initialized. skipping.")
+ return
+ }
+
if (state == currentViewState) {
dlog("resolveState: skipping")
return
@@ -387,23 +491,15 @@ class PrivacyDotViewController @Inject constructor(
updateRotations(state.rotation)
}
- if (state.height != currentViewState.height) {
- updateHeights(state.rotation)
- }
-
- if (state.marginLeft != currentViewState.marginLeft ||
- state.marginRight != currentViewState.marginRight) {
- updateCornerSizes(state.marginLeft, state.marginRight, state.rotation)
+ if (state.needsLayout(currentViewState)) {
+ setCornerSizes(state)
+ views.forEach { it.requestLayout() }
}
if (state.designatedCorner != currentViewState.designatedCorner) {
updateDesignatedCorner(state.designatedCorner, state.shouldShowDot())
}
- if (state.needsLayout(currentViewState)) {
- views.forEach { it.requestLayout() }
- }
-
val shouldShow = state.shouldShowDot()
if (shouldShow != currentViewState.shouldShowDot()) {
if (shouldShow && state.designatedCorner != null) {
@@ -441,6 +537,30 @@ class PrivacyDotViewController @Inject constructor(
}
return -1
}
+
+ // Returns [left, top, right, bottom] aka [seascape, none, landscape, upside-down]
+ private fun getLayoutRects(): List<Rect> {
+ val left = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_SEASCAPE)
+ val top = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_NONE)
+ val right = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_LANDSCAPE)
+ val bottom = contentInsetsProvider
+ .getStatusBarContentInsetsForRotation(ROTATION_UPSIDE_DOWN)
+
+ return listOf(left, top, right, bottom)
+ }
+
+ private fun setNewLayoutRects() {
+ val rects = getLayoutRects()
+
+ synchronized(lock) {
+ nextViewState = nextViewState.copy(
+ seascapeRect = rects[0],
+ portraitRect = rects[1],
+ landscapeRect = rects[2],
+ upsideDownRect = rects[3]
+ )
+ }
+ }
}
private fun dlog(s: String) {
@@ -461,7 +581,7 @@ const val BOTTOM_RIGHT = 2
const val BOTTOM_LEFT = 3
private const val DURATION = 160L
private const val TAG = "PrivacyDotViewController"
-private const val DEBUG = true
+private const val DEBUG = false
private const val DEBUG_VERBOSE = false
private fun Int.toGravity(): Int {
@@ -485,14 +605,20 @@ private fun Int.innerGravity(): Int {
}
private data class ViewState(
+ val viewInitialized: Boolean = false,
+
val systemPrivacyEventIsActive: Boolean = false,
val shadeExpanded: Boolean = false,
val qsExpanded: Boolean = false,
+ val portraitRect: Rect? = null,
+ val landscapeRect: Rect? = null,
+ val upsideDownRect: Rect? = null,
+ val seascapeRect: Rect? = null,
+ val layoutRtl: Boolean = false,
+
val rotation: Int = 0,
val height: Int = 0,
- val marginLeft: Int = 0,
- val marginRight: Int = 0,
val cornerIndex: Int = -1,
val designatedCorner: View? = null
) {
@@ -502,7 +628,20 @@ private data class ViewState(
fun needsLayout(other: ViewState): Boolean {
return rotation != other.rotation ||
- marginRight != other.marginRight ||
- height != other.height
+ layoutRtl != other.layoutRtl ||
+ portraitRect != other.portraitRect ||
+ landscapeRect != other.landscapeRect ||
+ upsideDownRect != other.upsideDownRect ||
+ seascapeRect != other.seascapeRect
+ }
+
+ fun contentRectForRotation(@Rotation rot: Int): Rect {
+ return when (rot) {
+ ROTATION_NONE -> portraitRect!!
+ ROTATION_LANDSCAPE -> landscapeRect!!
+ ROTATION_UPSIDE_DOWN -> upsideDownRect!!
+ ROTATION_SEASCAPE -> seascapeRect!!
+ else -> throw IllegalArgumentException("not a rotation ($rot)")
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 96b0e7819c7a..94ee868ceebc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -183,6 +183,7 @@ public final class NotificationEntry extends ListEntry {
private boolean mIsMarkedForUserTriggeredMovement;
private boolean mIsAlerting;
+ public boolean mRemoteEditImeAnimatingAway;
public boolean mRemoteEditImeVisible;
private boolean mExpandAnimationRunning;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 93166f39ad62..73bb6cd9ba1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -287,7 +287,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mGroupExpansionChanging = true;
final boolean wasExpanded = mGroupExpansionManager.isGroupExpanded(mEntry);
boolean nowExpanded = mGroupExpansionManager.toggleGroupExpansion(mEntry);
- mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
+ mOnExpandClickListener.onExpandClicked(mEntry, v, nowExpanded);
MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_GROUP_EXPANDER,
nowExpanded);
onExpansionChanged(true /* userAction */, wasExpanded);
@@ -310,7 +310,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
setUserExpanded(nowExpanded);
}
notifyHeightChanged(true);
- mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
+ mOnExpandClickListener.onExpandClicked(mEntry, v, nowExpanded);
MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_EXPANDER,
nowExpanded);
}
@@ -3064,7 +3064,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
public interface OnExpandClickListener {
- void onExpandClicked(NotificationEntry clickedEntry, boolean nowExpanded);
+ void onExpandClicked(NotificationEntry clickedEntry, View clickedView, boolean nowExpanded);
}
@Override
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 f460a132d65c..d0507e1e136c 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
@@ -154,15 +154,21 @@ public class StackScrollAlgorithm {
shelf.updateState(algorithmState, ambientState);
- // After the shelf has updated its yTranslation,
- // explicitly hide views below the shelf to skip rendering them in the hardware layer.
+ // 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.
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().hidden = true;
+ view.getViewState().alpha = 0;
}
}
}
@@ -388,7 +394,8 @@ public class StackScrollAlgorithm {
ambientState.getExpansionFraction(), true /* notification */);
}
- if (view.mustStayOnScreen() && viewState.yTranslation >= 0) {
+ if (ambientState.isShadeExpanded() && view.mustStayOnScreen()
+ && viewState.yTranslation >= 0) {
// Even if we're not scrolled away we're in view and we're also not in the
// shelf. We can relax the constraints and let us scroll off the top!
float end = viewState.yTranslation + viewState.height + ambientState.getStackY();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 6d5c53609f81..6e201048abdb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -564,8 +564,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
boolean unlockingAllowed =
mUpdateMonitor.isUnlockingWithBiometricAllowed(isStrongBiometric);
boolean deviceDreaming = mUpdateMonitor.isDreaming();
- boolean bypass = mKeyguardBypassController.getBypassEnabled();
-
+ boolean bypass = mKeyguardBypassController.getBypassEnabled()
+ || mKeyguardBypassController.getUserHasDeviceEntryIntent();
if (!mUpdateMonitor.isDeviceInteractive()) {
if (!mKeyguardViewController.isShowing()) {
return bypass ? MODE_WAKE_AND_UNLOCK : MODE_ONLY_WAKE;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index 1361acb1e156..596fce5f7009 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -37,7 +37,6 @@ import android.view.ViewGroup;
import android.view.ViewStub;
import android.widget.LinearLayout;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -76,9 +75,9 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
public static final int FADE_IN_DURATION = 320;
public static final int FADE_IN_DELAY = 50;
private PhoneStatusBarView mStatusBar;
- private StatusBarStateController mStatusBarStateController;
- private KeyguardStateController mKeyguardStateController;
- private NetworkController mNetworkController;
+ private final StatusBarStateController mStatusBarStateController;
+ private final KeyguardStateController mKeyguardStateController;
+ private final NetworkController mNetworkController;
private LinearLayout mSystemIconArea;
private View mClockView;
private View mOngoingCallChip;
@@ -86,15 +85,16 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
private View mCenteredIconArea;
private int mDisabled1;
private int mDisabled2;
- private StatusBar mStatusBarComponent;
+ private final StatusBar mStatusBarComponent;
private DarkIconManager mDarkIconManager;
private View mOperatorNameFrame;
- private CommandQueue mCommandQueue;
- private OngoingCallController mOngoingCallController;
+ private final CommandQueue mCommandQueue;
+ private final OngoingCallController mOngoingCallController;
private final SystemStatusAnimationScheduler mAnimationScheduler;
private final StatusBarLocationPublisher mLocationPublisher;
- private NotificationIconAreaController mNotificationIconAreaController;
private final FeatureFlags mFeatureFlags;
+ private final NotificationIconAreaController mNotificationIconAreaController;
+ private final StatusBarIconController mStatusBarIconController;
private List<String> mBlockedIcons = new ArrayList<>();
@@ -118,23 +118,25 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
SystemStatusAnimationScheduler animationScheduler,
StatusBarLocationPublisher locationPublisher,
NotificationIconAreaController notificationIconAreaController,
- FeatureFlags featureFlags
+ FeatureFlags featureFlags,
+ StatusBarIconController statusBarIconController,
+ KeyguardStateController keyguardStateController,
+ NetworkController networkController,
+ StatusBarStateController statusBarStateController,
+ StatusBar statusBarComponent,
+ CommandQueue commandQueue
) {
mOngoingCallController = ongoingCallController;
mAnimationScheduler = animationScheduler;
mLocationPublisher = locationPublisher;
mNotificationIconAreaController = notificationIconAreaController;
mFeatureFlags = featureFlags;
- }
-
- @Override
- public void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mKeyguardStateController = Dependency.get(KeyguardStateController.class);
- mNetworkController = Dependency.get(NetworkController.class);
- mStatusBarStateController = Dependency.get(StatusBarStateController.class);
- mStatusBarComponent = Dependency.get(StatusBar.class);
- mCommandQueue = Dependency.get(CommandQueue.class);
+ mStatusBarIconController = statusBarIconController;
+ mKeyguardStateController = keyguardStateController;
+ mNetworkController = networkController;
+ mStatusBarStateController = statusBarStateController;
+ mStatusBarComponent = statusBarComponent;
+ mCommandQueue = commandQueue;
}
@Override
@@ -160,7 +162,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_alarm_clock));
mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_call_strength));
mDarkIconManager.setBlockList(mBlockedIcons);
- Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
+ mStatusBarIconController.addIconGroup(mDarkIconManager);
mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
mClockView = mStatusBar.findViewById(R.id.clock);
mOngoingCallChip = mStatusBar.findViewById(R.id.ongoing_call_chip);
@@ -199,7 +201,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
@Override
public void onDestroyView() {
super.onDestroyView();
- Dependency.get(StatusBarIconController.class).removeIconGroup(mDarkIconManager);
+ mStatusBarIconController.removeIconGroup(mDarkIconManager);
if (mNetworkController.hasEmergencyCryptKeeperText()) {
mNetworkController.removeCallback(mSignalCallback);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
index b148eeba2cf5..07618da4451a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
@@ -18,6 +18,7 @@ import android.content.Context
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.os.LocaleList
+import android.view.View.LAYOUT_DIRECTION_RTL
import com.android.systemui.statusbar.policy.ConfigurationController
import java.util.ArrayList
@@ -33,6 +34,7 @@ class ConfigurationControllerImpl(context: Context) : ConfigurationController {
private var uiMode: Int = 0
private var localeList: LocaleList? = null
private val context: Context
+ private var layoutDirection: Int
init {
val currentConfig = context.resources.configuration
@@ -44,6 +46,7 @@ class ConfigurationControllerImpl(context: Context) : ConfigurationController {
Configuration.UI_MODE_TYPE_CAR
uiMode = currentConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK
localeList = currentConfig.locales
+ layoutDirection = currentConfig.layoutDirection
}
override fun notifyThemeChanged() {
@@ -101,6 +104,13 @@ class ConfigurationControllerImpl(context: Context) : ConfigurationController {
}
}
+ if (layoutDirection != newConfig.layoutDirection) {
+ layoutDirection = newConfig.layoutDirection
+ listeners.filterForEach({ this.listeners.contains(it) }) {
+ it.onLayoutDirectionChanged(layoutDirection == LAYOUT_DIRECTION_RTL)
+ }
+ }
+
if (lastConfig.updateFrom(newConfig) and ActivityInfo.CONFIG_ASSETS_PATHS != 0) {
listeners.filterForEach({ this.listeners.contains(it) }) {
it.onOverlayChanged()
@@ -116,6 +126,10 @@ class ConfigurationControllerImpl(context: Context) : ConfigurationController {
override fun removeCallback(listener: ConfigurationController.ConfigurationListener) {
listeners.remove(listener)
}
+
+ override fun isLayoutRtl(): Boolean {
+ return layoutDirection == LAYOUT_DIRECTION_RTL
+ }
}
// This could be done with a Collection.filter and Collection.forEach, but Collection.filter
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
index 2cb0a3a28901..ec669711e2db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
@@ -43,6 +43,7 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr
@BypassOverride private val bypassOverride: Int
private var hasFaceFeature: Boolean
private var pendingUnlock: PendingUnlock? = null
+ var userHasDeviceEntryIntent: Boolean = false // ie: attempted udfps auth
@IntDef(
FACE_UNLOCK_BYPASS_NO_OVERRIDE,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
index 178974327a75..f1cde8a9be7a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
@@ -62,6 +62,14 @@ public class KeyguardIndicationTextView extends TextView {
}
/**
+ * Clears message queue.
+ */
+ public void clearMessages() {
+ mMessages.clear();
+ mKeyguardIndicationInfo.clear();
+ }
+
+ /**
* Changes the text with an animation and makes sure a single indication is shown long enough.
*/
public void switchIndication(int textResId) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index fb3790cf4599..0fb26a2d0470 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -3646,8 +3646,6 @@ public class NotificationPanelViewController extends PanelViewController {
public void setAmbientIndicationBottomPadding(int ambientIndicationBottomPadding) {
if (mAmbientIndicationBottomPadding != ambientIndicationBottomPadding) {
mAmbientIndicationBottomPadding = ambientIndicationBottomPadding;
- mLockIconViewController.setAmbientIndicationBottomPadding(
- mAmbientIndicationBottomPadding);
updateMaxDisplayedNotifications(true);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 31a432e2c451..c300b11b9a34 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -23,6 +23,7 @@ import static java.lang.Float.isNaN;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
+import android.graphics.Point;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.EventLog;
@@ -52,6 +53,7 @@ public class PhoneStatusBarView extends PanelBar {
private static final boolean DEBUG = StatusBar.DEBUG;
private static final boolean DEBUG_GESTURES = false;
private final CommandQueue mCommandQueue;
+ private final StatusBarContentInsetsProvider mContentInsetsProvider;
StatusBar mBar;
@@ -85,11 +87,10 @@ public class PhoneStatusBarView extends PanelBar {
private int mCutoutSideNudge = 0;
private boolean mHeadsUpVisible;
- private int mRoundedCornerPadding = 0;
-
public PhoneStatusBarView(Context context, AttributeSet attrs) {
super(context, attrs);
mCommandQueue = Dependency.get(CommandQueue.class);
+ mContentInsetsProvider = Dependency.get(StatusBarContentInsetsProvider.class);
}
public void setBar(StatusBar bar) {
@@ -305,8 +306,6 @@ public class PhoneStatusBarView extends PanelBar {
public void updateResources() {
mCutoutSideNudge = getResources().getDimensionPixelSize(
R.dimen.display_cutout_margin_consumption);
- mRoundedCornerPadding = getResources().getDimensionPixelSize(
- R.dimen.rounded_corner_content_padding);
updateStatusBarHeight();
}
@@ -341,8 +340,7 @@ public class PhoneStatusBarView extends PanelBar {
private void updateLayoutForCutout() {
updateStatusBarHeight();
updateCutoutLocation(StatusBarWindowView.cornerCutoutMargins(mDisplayCutout, getDisplay()));
- updateSafeInsets(StatusBarWindowView.statusBarCornerCutoutMargins(mDisplayCutout,
- getDisplay(), mRotationOrientation, mStatusBarHeight));
+ updateSafeInsets();
}
private void updateCutoutLocation(Pair<Integer, Integer> cornerCutoutMargins) {
@@ -370,15 +368,18 @@ public class PhoneStatusBarView extends PanelBar {
lp.height = bounds.height();
}
- private void updateSafeInsets(Pair<Integer, Integer> cornerCutoutMargins) {
- // Depending on our rotation, we may have to work around a cutout in the middle of the view,
- // or letterboxing from the right or left sides.
+ private void updateSafeInsets() {
+ Rect contentRect = mContentInsetsProvider
+ .getStatusBarContentInsetsForRotation(RotationUtils.getExactRotation(getContext()));
- Pair<Integer, Integer> padding =
- StatusBarWindowView.paddingNeededForCutoutAndRoundedCorner(
- mDisplayCutout, cornerCutoutMargins, mRoundedCornerPadding);
+ Point size = new Point();
+ getDisplay().getRealSize(size);
- setPadding(padding.first, getPaddingTop(), padding.second, getPaddingBottom());
+ setPadding(
+ contentRect.left,
+ getPaddingTop(),
+ size.x - contentRect.right,
+ getPaddingBottom());
}
public void setHeadsUpVisible(boolean headsUpVisible) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index c68429a56225..173eec18ecc5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -55,6 +55,7 @@ import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.StatusBarManager;
+import android.app.TaskInfo;
import android.app.UiModeManager;
import android.app.WallpaperInfo;
import android.app.WallpaperManager;
@@ -247,6 +248,7 @@ import com.android.systemui.volume.VolumeComponent;
import com.android.systemui.wmshell.BubblesManager;
import com.android.wm.shell.bubbles.Bubbles;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
+import com.android.wm.shell.startingsurface.SplashscreenContentDrawer;
import com.android.wm.shell.startingsurface.StartingSurface;
import java.io.FileDescriptor;
@@ -269,7 +271,7 @@ public class StatusBar extends SystemUI implements DemoMode,
ColorExtractor.OnColorsChangedListener, ConfigurationListener,
StatusBarStateController.StateListener,
LifecycleOwner, BatteryController.BatteryStateChangeCallback,
- ActivityLaunchAnimator.KeyguardHandler {
+ ActivityLaunchAnimator.Callback {
public static final boolean MULTIUSER_DEBUG = false;
protected static final int MSG_HIDE_RECENT_APPS = 1020;
@@ -439,6 +441,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private final OngoingCallController mOngoingCallController;
private final SystemStatusAnimationScheduler mAnimationScheduler;
private final StatusBarLocationPublisher mStatusBarLocationPublisher;
+ private final StatusBarIconController mStatusBarIconController;
// expanded notifications
// the sliding/resizing panel within the notification window
@@ -801,6 +804,7 @@ public class StatusBar extends SystemUI implements DemoMode,
OngoingCallController ongoingCallController,
SystemStatusAnimationScheduler animationScheduler,
StatusBarLocationPublisher locationPublisher,
+ StatusBarIconController statusBarIconController,
LockscreenShadeTransitionController lockscreenShadeTransitionController,
FeatureFlags featureFlags,
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
@@ -887,6 +891,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mOngoingCallController = ongoingCallController;
mAnimationScheduler = animationScheduler;
mStatusBarLocationPublisher = locationPublisher;
+ mStatusBarIconController = statusBarIconController;
mFeatureFlags = featureFlags;
mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
@@ -1188,7 +1193,14 @@ public class StatusBar extends SystemUI implements DemoMode,
mAnimationScheduler,
mStatusBarLocationPublisher,
mNotificationIconAreaController,
- mFeatureFlags),
+ mFeatureFlags,
+ mStatusBarIconController,
+ mKeyguardStateController,
+ mNetworkController,
+ mStatusBarStateController,
+ this,
+ mCommandQueue
+ ),
CollapsedStatusBarFragment.TAG)
.commit();
@@ -1421,9 +1433,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private void setUpPresenter() {
// Set up the initial notification state.
- mActivityLaunchAnimator = new ActivityLaunchAnimator(this,
- mStartingSurfaceOptional.orElse(null),
- mContext);
+ mActivityLaunchAnimator = new ActivityLaunchAnimator(this, mContext);
mNotificationAnimationProvider = new NotificationLaunchAnimatorControllerProvider(
mNotificationShadeWindowViewController,
mStackScrollerController.getNotificationListContainer(),
@@ -2123,6 +2133,16 @@ public class StatusBar extends SystemUI implements DemoMode,
mKeyguardViewMediator.setBlursDisabledForAppLaunch(disabled);
}
+ @Override
+ public int getBackgroundColor(TaskInfo task) {
+ if (!mStartingSurfaceOptional.isPresent()) {
+ Log.w(TAG, "No starting surface, defaulting to SystemBGColor");
+ return SplashscreenContentDrawer.getSystemBGColor();
+ }
+
+ return mStartingSurfaceOptional.get().getBackgroundColor(task);
+ }
+
public boolean isDeviceInVrMode() {
return mPresenter.isDeviceInVrMode();
}
@@ -2727,6 +2747,11 @@ public class StatusBar extends SystemUI implements DemoMode,
mScrimController.dump(fd, pw, args);
}
+ if (mLightRevealScrim != null) {
+ pw.println(
+ "mLightRevealScrim.getRevealAmount(): " + mLightRevealScrim.getRevealAmount());
+ }
+
if (mStatusBarKeyguardViewManager != null) {
mStatusBarKeyguardViewManager.dump(pw);
}
@@ -3925,7 +3950,11 @@ public class StatusBar extends SystemUI implements DemoMode,
|| !wakingUp && mWakefulnessLifecycle.getLastSleepReason()
== PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON) {
mLightRevealScrim.setRevealEffect(mPowerButtonReveal);
- } else if (!(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) {
+ } else if (!wakingUp || !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) {
+ // If we're going to sleep, but it's not from the power button, use the default reveal.
+ // If we're waking up, only use the default reveal if the biometric controller didn't
+ // already set it to the circular reveal because we're waking up from a fingerprint/face
+ // auth.
mLightRevealScrim.setRevealEffect(LiftReveal.INSTANCE);
}
}
@@ -4169,7 +4198,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private void vibrateForCameraGesture() {
// Make sure to pass -1 for repeat so VibratorService doesn't stop us when going to sleep.
- mVibrator.vibrate(mCameraLaunchGestureVibrationEffect);
+ mVibrator.vibrate(mCameraLaunchGestureVibrationEffect, VIBRATION_ATTRIBUTES);
}
private static VibrationEffect getCameraGestureVibrationEffect(Vibrator vibrator,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
index edcf261115d2..fe1f63a34acd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.phone
import android.content.Context
import android.content.res.Resources
import android.graphics.Rect
+import android.util.Log
import android.util.Pair
import android.view.DisplayCutout
import android.view.View.LAYOUT_DIRECTION_RTL
@@ -155,13 +156,30 @@ class StatusBarContentInsetsProvider @Inject constructor(
val dc = context.display.cutout
val currentRotation = RotationUtils.getExactRotation(context)
+ val isRtl = rotatedResources.configuration.layoutDirection == LAYOUT_DIRECTION_RTL
+ val roundedCornerPadding = rotatedResources
+ .getDimensionPixelSize(R.dimen.rounded_corner_content_padding)
+ val minDotWidth = rotatedResources
+ .getDimensionPixelSize(R.dimen.ongoing_appops_dot_min_padding)
+
+ val minLeft: Int
+ val minRight: Int
+ if (isRtl) {
+ minLeft = max(minDotWidth, roundedCornerPadding)
+ minRight = roundedCornerPadding
+ } else {
+ minLeft = roundedCornerPadding
+ minRight = max(minDotWidth, roundedCornerPadding)
+ }
+
return calculateInsetsForRotationWithRotatedResources(
currentRotation,
targetRotation,
dc,
windowManager.maximumWindowMetrics,
rotatedResources.getDimensionPixelSize(R.dimen.status_bar_height),
- rotatedResources.getDimensionPixelSize(R.dimen.rounded_corner_content_padding))
+ minLeft,
+ minRight)
}
override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
@@ -212,9 +230,12 @@ fun getPrivacyChipBoundingRectForInsets(
* Calculates the exact left and right positions for the status bar contents for the given
* rotation
*
- * @param rot rotation for which to query the margins
- * @param context systemui context
- * @param rotatedResources resources constructed with the proper orientation set
+ * @param currentRotation current device rotation
+ * @param targetRotation rotation for which to calculate the status bar content rect
+ * @param displayCutout [DisplayCutout] for the curren display. possibly null
+ * @param windowMetrics [WindowMetrics] for the current window
+ * @param statusBarHeight height of the status bar for the target rotation
+ * @param roundedCornerPadding from rounded_corner_content_padding
*
* @see [RotationUtils#getResourcesForRotation]
*/
@@ -224,7 +245,8 @@ fun calculateInsetsForRotationWithRotatedResources(
displayCutout: DisplayCutout?,
windowMetrics: WindowMetrics,
statusBarHeight: Int,
- roundedCornerPadding: Int
+ minLeft: Int,
+ minRight: Int
): Rect {
/*
TODO: Check if this is ever used for devices with no rounded corners
@@ -242,7 +264,8 @@ fun calculateInsetsForRotationWithRotatedResources(
rotZeroBounds.bottom,
currentBounds.width(),
currentBounds.height(),
- roundedCornerPadding,
+ minLeft,
+ minRight,
targetRotation,
currentRotation)
@@ -256,7 +279,10 @@ fun calculateInsetsForRotationWithRotatedResources(
* @param sbHeight appropriate status bar height for this rotation
* @param width display width calculated for ROTATION_NONE
* @param height display height calculated for ROTATION_NONE
- * @param roundedCornerPadding rounded_corner_content_padding dimension
+ * @param cWidth display width in our current rotation
+ * @param cHeight display height in our current rotation
+ * @param minLeft the minimum padding to enforce on the left
+ * @param minRight the minimum padding to enforce on the right
* @param targetRotation the rotation for which to calculate margins
* @param currentRotation the rotation from which the display cutout was generated
*
@@ -270,7 +296,8 @@ private fun getStatusBarLeftRight(
height: Int,
cWidth: Int,
cHeight: Int,
- roundedCornerPadding: Int,
+ minLeft: Int,
+ minRight: Int,
@Rotation targetRotation: Int,
@Rotation currentRotation: Int
): Rect {
@@ -279,9 +306,9 @@ private fun getStatusBarLeftRight(
val cutoutRects = dc?.boundingRects
if (cutoutRects == null || cutoutRects.isEmpty()) {
- return Rect(roundedCornerPadding,
+ return Rect(minLeft,
0,
- logicalDisplayWidth - roundedCornerPadding,
+ logicalDisplayWidth - minRight,
sbHeight)
}
@@ -294,8 +321,8 @@ private fun getStatusBarLeftRight(
// Size of the status bar window for the given rotation relative to our exact rotation
val sbRect = sbRect(relativeRotation, sbHeight, Pair(cWidth, cHeight))
- var leftMargin = roundedCornerPadding
- var rightMargin = roundedCornerPadding
+ var leftMargin = minLeft
+ var rightMargin = minRight
for (cutoutRect in cutoutRects) {
// There is at most one non-functional area per short edge of the device. So if the status
// bar doesn't share a short edge with the cutout, we can ignore its insets because there
@@ -306,11 +333,11 @@ private fun getStatusBarLeftRight(
if (cutoutRect.touchesLeftEdge(relativeRotation, cWidth, cHeight)) {
- val l = max(roundedCornerPadding, cutoutRect.logicalWidth(relativeRotation))
+ val l = max(minLeft, cutoutRect.logicalWidth(relativeRotation))
leftMargin = max(l, leftMargin)
} else if (cutoutRect.touchesRightEdge(relativeRotation, cWidth, cHeight)) {
val logicalWidth = cutoutRect.logicalWidth(relativeRotation)
- rightMargin = max(roundedCornerPadding, logicalWidth)
+ rightMargin = max(minRight, logicalWidth)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index aa58527cb32e..47deb1f0084b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -24,12 +24,14 @@ import android.app.KeyguardManager;
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
import android.util.Log;
import android.util.Slog;
+import android.view.View;
import android.view.accessibility.AccessibilityManager;
import android.widget.TextView;
@@ -394,8 +396,10 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
}
@Override
- public void onExpandClicked(NotificationEntry clickedEntry, boolean nowExpanded) {
+ public void onExpandClicked(NotificationEntry clickedEntry, View clickedView,
+ boolean nowExpanded) {
mHeadsUpManager.setExpanded(clickedEntry, nowExpanded);
+ mStatusBar.wakeUpIfDozing(SystemClock.uptimeMillis(), clickedView, "NOTIFICATION_CLICK");
if (nowExpanded) {
if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
mShadeTransitionController.goToLockedShade(clickedEntry.getRow());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
index 95712cd303f5..262dc837f22c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
@@ -132,7 +132,7 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks,
if (!row.isPinned()) {
mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
}
- mStatusBarKeyguardViewManager.showBouncer(true /* scrimmed */);
+ mStatusBarKeyguardViewManager.showGenericBouncer(true /* scrimmed */);
mPendingRemoteInputView = clicked;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
index 64a497ddd317..329293409dc2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
@@ -245,8 +245,19 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
* @param slotName name of the icon slot to remove from the ignored list
*/
public void removeIgnoredSlot(String slotName) {
- if (mIgnoredSlots.contains(slotName)) {
- mIgnoredSlots.remove(slotName);
+ mIgnoredSlots.remove(slotName);
+
+ requestLayout();
+ }
+
+ /**
+ * Remove a list of slots from the list of ignored icon slots.
+ * It will then be shown when set to visible by the {@link StatusBarIconController}.
+ * @param slots name of the icon slots to remove from the ignored list
+ */
+ public void removeIgnoredSlots(List<String> slots) {
+ for (String slot : slots) {
+ mIgnoredSlots.remove(slot);
}
requestLayout();
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 4167287a504e..a5b868b6f8a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
@@ -199,10 +199,9 @@ class UnlockedScreenOffAnimationController @Inject constructor(
// We currently draw both the light reveal scrim, and the AOD UI, in the shade. If it's
// already expanded and showing notifications/QS, the animation looks really messy. For now,
- // disable it if the notification panel is expanded.
+ // disable it if the notification panel is not fully collapsed.
if (!this::statusBar.isInitialized ||
- statusBar.notificationPanelViewController.isFullyExpanded ||
- statusBar.notificationPanelViewController.isExpanding) {
+ !statusBar.notificationPanelViewController.isFullyCollapsed) {
return false
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index 716d1dbc6462..b6e8bd8bf7c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -89,6 +89,7 @@ import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarLocationPublisher;
import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
@@ -216,6 +217,7 @@ public interface StatusBarPhoneModule {
OngoingCallController ongoingCallController,
SystemStatusAnimationScheduler animationScheduler,
StatusBarLocationPublisher locationPublisher,
+ StatusBarIconController statusBarIconController,
LockscreenShadeTransitionController transitionController,
FeatureFlags featureFlags,
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
@@ -305,6 +307,7 @@ public interface StatusBarPhoneModule {
ongoingCallController,
animationScheduler,
locationPublisher,
+ statusBarIconController,
transitionController,
featureFlags,
keyguardUnlockAnimationController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
index c2bd87c6276f..3a05ec78a8b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
@@ -30,6 +30,9 @@ public interface ConfigurationController extends CallbackController<Configuratio
/** Alert controller of a change in between light and dark themes. */
void notifyThemeChanged();
+ /** Query the current configuration's layout direction */
+ boolean isLayoutRtl();
+
interface ConfigurationListener {
default void onConfigChanged(Configuration newConfig) {}
default void onDensityOrFontScaleChanged() {}
@@ -38,5 +41,6 @@ public interface ConfigurationController extends CallbackController<Configuratio
default void onUiModeChanged() {}
default void onThemeChanged() {}
default void onLocaleListChanged() {}
+ default void onLayoutDirectionChanged(boolean isLayoutRtl) {}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index bbaf65a399a9..84d7c05ddc14 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -272,6 +272,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
public void onEnd(@NonNull WindowInsetsAnimation animation) {
super.onEnd(animation);
if (animation.getTypeMask() == WindowInsets.Type.ime()) {
+ mEntry.mRemoteEditImeAnimatingAway = false;
mEntry.mRemoteEditImeVisible =
mEditText.getRootWindowInsets().isVisible(WindowInsets.Type.ime());
if (!mEntry.mRemoteEditImeVisible && !mEditText.mShowImeOnInputConnection) {
@@ -392,6 +393,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
mSendButton.setVisibility(INVISIBLE);
mProgressBar.setVisibility(VISIBLE);
mEntry.lastRemoteInputSent = SystemClock.elapsedRealtime();
+ mEntry.mRemoteEditImeAnimatingAway = true;
mController.addSpinning(mEntry.getKey(), mToken);
mController.removeRemoteInput(mEntry, mToken);
mEditText.mShowImeOnInputConnection = false;
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 4e921a036b36..c94eaeda3906 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -539,6 +539,13 @@ public class UserSwitcherController implements Dumpable {
mSecondaryUser = userInfo.id;
}
unpauseRefreshUsers = true;
+ if (mGuestUserAutoCreated) {
+ // Guest user must be scheduled for creation AFTER switching to the target user.
+ // This avoids lock contention which will produce UX bugs on the keyguard
+ // (b/193933686).
+ // TODO(b/191067027): Move guest user recreation to system_server
+ guaranteeGuestPresent();
+ }
} else if (Intent.ACTION_USER_INFO_CHANGED.equals(intent.getAction())) {
forcePictureLoadForId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
UserHandle.USER_NULL);
@@ -670,10 +677,6 @@ public class UserSwitcherController implements Dumpable {
switchToUserId(newGuestId);
mUserManager.removeUser(currentUser.id);
} else {
- if (mGuestUserAutoCreated) {
- // TODO(b/191067027): Move guest recreation to system_server
- scheduleGuestCreation();
- }
switchToUserId(targetUserId);
mUserManager.removeUser(currentUser.id);
}
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
index 843630b35e17..c3b4fbe9a13d 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
@@ -197,8 +197,10 @@ public class ThemeOverlayApplier implements Dumpable {
.collect(Collectors.toList());
OverlayManagerTransaction.Builder transaction = getTransactionBuilder();
+ HashSet<OverlayIdentifier> identifiersPending = new HashSet<>();
if (pendingCreation != null) {
for (FabricatedOverlay overlay : pendingCreation) {
+ identifiersPending.add(overlay.getIdentifier());
transaction.registerFabricatedOverlay(overlay);
}
}
@@ -206,14 +208,14 @@ public class ThemeOverlayApplier implements Dumpable {
for (Pair<String, String> packageToDisable : overlaysToDisable) {
OverlayIdentifier overlayInfo = new OverlayIdentifier(packageToDisable.second);
setEnabled(transaction, overlayInfo, packageToDisable.first, currentUser,
- managedProfiles, false);
+ managedProfiles, false, identifiersPending.contains(overlayInfo));
}
for (String category : THEME_CATEGORIES) {
if (categoryToPackage.containsKey(category)) {
OverlayIdentifier overlayInfo = categoryToPackage.get(category);
setEnabled(transaction, overlayInfo, category, currentUser, managedProfiles,
- true);
+ true, identifiersPending.contains(overlayInfo));
}
}
@@ -233,7 +235,7 @@ public class ThemeOverlayApplier implements Dumpable {
@AnyThread
private void setEnabled(OverlayManagerTransaction.Builder transaction,
OverlayIdentifier identifier, String category, int currentUser,
- Set<UserHandle> managedProfiles, boolean enabled) {
+ Set<UserHandle> managedProfiles, boolean enabled, boolean pendingCreation) {
if (DEBUG) {
Log.d(TAG, "setEnabled: " + identifier.getPackageName() + " category: "
+ category + ": " + enabled);
@@ -241,7 +243,7 @@ public class ThemeOverlayApplier implements Dumpable {
OverlayInfo overlayInfo = mOverlayManager.getOverlayInfo(identifier,
UserHandle.of(currentUser));
- if (overlayInfo == null) {
+ if (overlayInfo == null && !pendingCreation) {
Log.i(TAG, "Won't enable " + identifier + ", it doesn't exist for user"
+ currentUser);
return;
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
index 0ecc4e25047f..4a4f2e9710dd 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
@@ -31,8 +31,10 @@ import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.util.settings.SecureSettings;
+import com.android.systemui.util.time.SystemClock;
import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
@@ -52,9 +54,11 @@ public class QuickAccessWalletController {
}
private static final String TAG = "QAWController";
+ private static final long RECREATION_TIME_WINDOW = TimeUnit.MINUTES.toMillis(10L);
private final Context mContext;
private final Executor mExecutor;
private final SecureSettings mSecureSettings;
+ private final SystemClock mClock;
private QuickAccessWalletClient mQuickAccessWalletClient;
private ContentObserver mWalletPreferenceObserver;
@@ -62,17 +66,21 @@ public class QuickAccessWalletController {
private int mWalletPreferenceChangeEvents = 0;
private int mDefaultPaymentAppChangeEvents = 0;
private boolean mWalletEnabled = false;
+ private long mQawClientCreatedTimeMillis;
@Inject
public QuickAccessWalletController(
Context context,
@Main Executor executor,
SecureSettings secureSettings,
- QuickAccessWalletClient quickAccessWalletClient) {
+ QuickAccessWalletClient quickAccessWalletClient,
+ SystemClock clock) {
mContext = context;
mExecutor = executor;
mSecureSettings = secureSettings;
mQuickAccessWalletClient = quickAccessWalletClient;
+ mClock = clock;
+ mQawClientCreatedTimeMillis = mClock.elapsedRealtime();
}
/**
@@ -143,6 +151,11 @@ public class QuickAccessWalletController {
*/
public void queryWalletCards(
QuickAccessWalletClient.OnWalletCardsRetrievedCallback cardsRetriever) {
+ if (mClock.elapsedRealtime() - mQawClientCreatedTimeMillis
+ > RECREATION_TIME_WINDOW) {
+ Log.i(TAG, "Re-creating the QAW client to avoid stale.");
+ reCreateWalletClient();
+ }
if (!mQuickAccessWalletClient.isWalletFeatureAvailable()) {
Log.d(TAG, "QuickAccessWallet feature is not available.");
return;
@@ -162,6 +175,7 @@ public class QuickAccessWalletController {
*/
public void reCreateWalletClient() {
mQuickAccessWalletClient = QuickAccessWalletClient.create(mContext);
+ mQawClientCreatedTimeMillis = mClock.elapsedRealtime();
}
private void setupDefaultPaymentAppObserver(