summaryrefslogtreecommitdiff
path: root/packages/SystemUI/src
diff options
context:
space:
mode:
authorScott Lobdell <slobdell@google.com>2021-07-23 16:46:35 +0000
committerScott Lobdell <slobdell@google.com>2021-07-23 17:56:38 +0000
commitdc5ea9d31ab76ba378da9c550813e6b7d8be1e69 (patch)
treee69528a4200094e8616a1303f0f3104ce54b9415 /packages/SystemUI/src
parentfef582047102b73e83831845a694f7409f33294b (diff)
parent0cf0aea05a722e3bec6fb3ea2077066edfd2fe57 (diff)
Merge SP1A.210715.002
Change-Id: I65e2b7db097927b87c9c4023015c754033c62086
Diffstat (limited to 'packages/SystemUI/src')
-rw-r--r--packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java19
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java27
-rwxr-xr-xpackages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java10
-rw-r--r--packages/SystemUI/src/com/android/keyguard/LockIconViewController.java52
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java77
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/BiometricOrientationEventListener.kt60
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java99
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java61
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java86
-rw-r--r--packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSDetail.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFragment.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ImageTileSet.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java45
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java71
-rw-r--r--packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt39
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java58
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java49
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java24
-rwxr-xr-xpackages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java45
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java2
-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.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java2
57 files changed, 782 insertions, 477 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
index fcf4e4703ed3..c89cda98c8a5 100644
--- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
@@ -21,7 +21,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
-import android.hardware.biometrics.BiometricSourceType;
import android.icu.text.NumberFormat;
import com.android.settingslib.Utils;
@@ -94,9 +93,7 @@ public class AnimatableClockController extends ViewController<AnimatableClockVie
@Override
public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
if (mKeyguardShowing && !mIsCharging && charging) {
- mView.animateCharge(() -> {
- return mStatusBarStateController.isDozing();
- });
+ mView.animateCharge(mStatusBarStateController::isDozing);
}
mIsCharging = charging;
}
@@ -127,21 +124,10 @@ public class AnimatableClockController extends ViewController<AnimatableClockVie
private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() {
@Override
- public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType,
- boolean isStrongBiometric) {
- // Strong auth will force the bouncer regardless of a successful face auth
- if (biometricSourceType == BiometricSourceType.FACE
- && mBypassController.canBypass()
- && !mKeyguardUpdateMonitor.userNeedsStrongAuth()) {
- mView.animateDisappear();
- }
- }
-
- @Override
public void onKeyguardVisibilityChanged(boolean showing) {
mKeyguardShowing = showing;
if (!mKeyguardShowing) {
- // reset state (ie: after animateDisappear)
+ // reset state (ie: after weight animations)
reset();
}
}
@@ -156,7 +142,6 @@ public class AnimatableClockController extends ViewController<AnimatableClockVie
mDozeAmount = mStatusBarStateController.getDozeAmount();
mBatteryController.addCallback(mBatteryCallback);
mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
- mKeyguardShowing = true;
mStatusBarStateController.removeCallback(mStatusBarStatePersistentListener);
mStatusBarStateController.addCallback(mStatusBarStatePersistentListener);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index 2096c310744d..72e502816534 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -79,18 +79,6 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
dozeParameters, unlockedScreenOffAnimationController, /* animateYPos= */ true);
mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
mSmartspaceTransitionController = smartspaceTransitionController;
-
- mKeyguardStateController.addCallback(new KeyguardStateController.Callback() {
- @Override
- public void onKeyguardShowingChanged() {
- // If we explicitly re-show the keyguard, make sure that all the child views are
- // visible. They might have been animating out as part of the SmartSpace shared
- // element transition.
- if (keyguardStateController.isShowing()) {
- mView.setChildrenAlphaExcludingClockView(1f);
- }
- }
- });
}
@Override
@@ -102,12 +90,14 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
protected void onViewAttached() {
mKeyguardUpdateMonitor.registerCallback(mInfoCallback);
mConfigurationController.addCallback(mConfigurationListener);
+ mKeyguardStateController.addCallback(mKeyguardStateControllerCallback);
}
@Override
protected void onViewDetached() {
mKeyguardUpdateMonitor.removeCallback(mInfoCallback);
mConfigurationController.removeCallback(mConfigurationListener);
+ mKeyguardStateController.removeCallback(mKeyguardStateControllerCallback);
}
/**
@@ -276,6 +266,19 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
}
};
+ private KeyguardStateController.Callback mKeyguardStateControllerCallback =
+ new KeyguardStateController.Callback() {
+ @Override
+ public void onKeyguardShowingChanged() {
+ // If we explicitly re-show the keyguard, make sure that all the child views are
+ // visible. They might have been animating out as part of the SmartSpace shared
+ // element transition.
+ if (mKeyguardStateController.isShowing()) {
+ mView.setChildrenAlphaExcludingClockView(1f);
+ }
+ }
+ };
+
/**
* Rect that specifies how KSV should be clipped, on its parent's coordinates.
*/
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 0503b2e80d86..5c9afa5cf4c9 100755
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -286,7 +286,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
@VisibleForTesting
protected boolean mTelephonyCapable;
- private final boolean mAcquiredHapticEnabled;
+ private final boolean mAcquiredHapticEnabled = false;
@Nullable private final Vibrator mVibrator;
// Device provisioning state
@@ -1414,11 +1414,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
@VisibleForTesting
public void playAcquiredHaptic() {
if (mAcquiredHapticEnabled && mVibrator != null) {
- String effect = Settings.Global.getString(
- mContext.getContentResolver(),
- "udfps_acquired_type");
- mVibrator.vibrate(UdfpsController.getVibration(effect,
- UdfpsController.EFFECT_TICK),
+ mVibrator.vibrate(UdfpsController.EFFECT_CLICK,
UdfpsController.VIBRATION_SONIFICATION_ATTRIBUTES);
}
}
@@ -1732,8 +1728,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mLockPatternUtils = lockPatternUtils;
mAuthController = authController;
dumpManager.registerDumpable(getClass().getName(), this);
- mAcquiredHapticEnabled = Settings.Global.getInt(mContext.getContentResolver(),
- "udfps_acquired", 0) == 1;
mVibrator = vibrator;
mHandler = new Handler(mainLooper) {
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index 62cb4b9a33f5..afea27222fbb 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -24,8 +24,8 @@ import android.content.Context;
import android.content.res.Configuration;
import android.graphics.PointF;
import android.graphics.Rect;
+import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.InsetDrawable;
import android.hardware.biometrics.BiometricSourceType;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.util.DisplayMetrics;
@@ -79,7 +79,8 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
@NonNull private final DelayableExecutor mExecutor;
private boolean mUdfpsEnrolled;
- @NonNull private final Drawable mUnlockIcon;
+ @NonNull private final AnimatedVectorDrawable mFpToUnlockIcon;
+ @NonNull private final AnimatedVectorDrawable mLockToUnlockIcon;
@NonNull private final Drawable mLockIcon;
@NonNull private final CharSequence mUnlockedLabel;
@NonNull private final CharSequence mLockedLabel;
@@ -98,7 +99,8 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
private float mHeightPixels;
private float mWidthPixels;
private float mDensity;
- private int mKgBottomAreaHeight;
+ private int mAmbientIndicationHeight; // in pixels
+ private int mKgIndicationHeight; // in pixels
private boolean mShowUnlockIcon;
private boolean mShowLockIcon;
@@ -132,14 +134,14 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
mExecutor = executor;
final Context context = view.getContext();
- mUnlockIcon = new InsetDrawable(context.getResources().getDrawable(
- com.android.internal.R.drawable.ic_lock_open, context.getTheme()),
- context.getResources().getDimensionPixelSize(
- com.android.systemui.R.dimen.udfps_unlock_icon_inset));
- mLockIcon = new InsetDrawable(context.getResources().getDrawable(
- com.android.internal.R.drawable.ic_lock, context.getTheme()),
- context.getResources().getDimensionPixelSize(
- com.android.systemui.R.dimen.udfps_unlock_icon_inset));
+ mLockIcon = mView.getContext().getResources().getDrawable(
+ R.anim.lock_to_unlock,
+ mView.getContext().getTheme());
+ mFpToUnlockIcon = (AnimatedVectorDrawable) mView.getContext().getResources().getDrawable(
+ R.anim.fp_to_unlock, mView.getContext().getTheme());
+ mLockToUnlockIcon = (AnimatedVectorDrawable) mView.getContext().getResources().getDrawable(
+ R.anim.lock_to_unlock,
+ mView.getContext().getTheme());
mUnlockedLabel = context.getResources().getString(R.string.accessibility_unlock_button);
mLockedLabel = context.getResources().getString(R.string.accessibility_lock_icon);
dumpManager.registerDumpable("LockIconViewController", this);
@@ -211,6 +213,8 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
return;
}
+ boolean wasShowingFpIcon = mHasUdfps && !mShowUnlockIcon && !mShowLockIcon;
+ boolean wasShowingLockIcon = mShowLockIcon;
mShowLockIcon = !mCanDismissLockScreen && !mUserUnlockedWithBiometric && isLockScreen()
&& (!mUdfpsEnrolled || !mRunningFPS);
mShowUnlockIcon = mCanDismissLockScreen && isLockScreen();
@@ -221,7 +225,15 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
mView.setVisibility(View.VISIBLE);
mView.setContentDescription(mLockedLabel);
} else if (mShowUnlockIcon) {
- mView.setImageDrawable(mUnlockIcon);
+ if (wasShowingFpIcon) {
+ mView.setImageDrawable(mFpToUnlockIcon);
+ mFpToUnlockIcon.forceAnimationOnUI();
+ mFpToUnlockIcon.start();
+ } else if (wasShowingLockIcon) {
+ mView.setImageDrawable(mLockToUnlockIcon);
+ mLockToUnlockIcon.forceAnimationOnUI();
+ mLockToUnlockIcon.start();
+ }
mView.setVisibility(View.VISIBLE);
mView.setContentDescription(mUnlockedLabel);
} else {
@@ -271,7 +283,8 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
private void updateColors() {
final int color = Utils.getColorAttrDefaultColor(mView.getContext(),
R.attr.wallpaperTextColorAccent);
- mUnlockIcon.setTint(color);
+ mFpToUnlockIcon.setTint(color);
+ mLockToUnlockIcon.setTint(color);
mLockIcon.setTint(color);
}
@@ -280,7 +293,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
mWidthPixels = metrics.widthPixels;
mHeightPixels = metrics.heightPixels;
mDensity = metrics.density;
- mKgBottomAreaHeight = mView.getContext().getResources().getDimensionPixelSize(
+ mKgIndicationHeight = mView.getContext().getResources().getDimensionPixelSize(
R.dimen.keyguard_indication_margin_bottom)
+ mView.getContext().getResources().getDimensionPixelSize(
R.dimen.keyguard_indication_bottom_padding);
@@ -295,15 +308,24 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
} 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 - mKgBottomAreaHeight - distAboveKgBottomArea
+ mHeightPixels - kgBottomAreaHeight - distAboveKgBottomArea
- radius / 2), (int) radius);
}
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);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.java
index 45ee4ad9ae50..ee602bc9cb78 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.java
@@ -23,6 +23,8 @@ import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
+import androidx.annotation.Nullable;
+
import com.android.systemui.R;
public class AuthBiometricFingerprintView extends AuthBiometricView {
@@ -94,12 +96,37 @@ public class AuthBiometricFingerprintView extends AuthBiometricView {
mIconView.setImageDrawable(icon);
+ final CharSequence iconContentDescription = getIconContentDescription(newState);
+ if (iconContentDescription != null) {
+ mIconView.setContentDescription(iconContentDescription);
+ }
+
if (animation != null && shouldAnimateForTransition(lastState, newState)) {
animation.forceAnimationOnUI();
animation.start();
}
}
+ @Nullable
+ private CharSequence getIconContentDescription(int newState) {
+ switch (newState) {
+ case STATE_IDLE:
+ case STATE_AUTHENTICATING_ANIMATING_IN:
+ case STATE_AUTHENTICATING:
+ case STATE_PENDING_CONFIRMATION:
+ case STATE_AUTHENTICATED:
+ return mContext.getString(
+ R.string.accessibility_fingerprint_dialog_fingerprint_icon);
+
+ case STATE_ERROR:
+ case STATE_HELP:
+ return mContext.getString(R.string.biometric_dialog_try_again);
+
+ default:
+ return null;
+ }
+ }
+
private boolean shouldAnimateForTransition(int oldState, int newState) {
switch (newState) {
case STATE_HELP:
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
index bebf813e1833..60b06378a61a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
@@ -636,7 +636,6 @@ public abstract class AuthBiometricView extends LinearLayout {
mIndicatorView.setText(message);
mIndicatorView.setTextColor(mTextColorError);
mIndicatorView.setVisibility(View.VISIBLE);
- mIndicatorView.setSelected(true);
mHandler.postDelayed(resetMessageRunnable, mInjector.getDelayAfterError());
Utils.notifyAccessibilityContentChanged(mAccessibilityManager, this);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 2aa89e86d5c8..71e2bb657de4 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -48,10 +48,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;
-import android.view.Display;
import android.view.MotionEvent;
-import android.view.OrientationEventListener;
-import android.view.Surface;
import android.view.WindowManager;
import com.android.internal.R;
@@ -72,6 +69,8 @@ import java.util.Set;
import javax.inject.Inject;
import javax.inject.Provider;
+import kotlin.Unit;
+
/**
* Receives messages sent from {@link com.android.server.biometrics.BiometricService} and shows the
* appropriate biometric UI (e.g. BiometricDialogView).
@@ -107,7 +106,8 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
TaskStackListener mTaskStackListener;
@VisibleForTesting
IBiometricSysuiReceiver mReceiver;
- @NonNull private final BiometricOrientationEventListener mOrientationListener;
+ @VisibleForTesting
+ @NonNull final BiometricOrientationEventListener mOrientationListener;
@Nullable private final List<FaceSensorPropertiesInternal> mFaceProps;
@Nullable private List<FingerprintSensorPropertiesInternal> mFpProps;
@Nullable private List<FingerprintSensorPropertiesInternal> mUdfpsProps;
@@ -120,46 +120,6 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
}
}
- private class BiometricOrientationEventListener extends OrientationEventListener {
- @Surface.Rotation private int mLastRotation = ORIENTATION_UNKNOWN;
-
- BiometricOrientationEventListener(Context context) {
- super(context);
-
- final Display display = context.getDisplay();
- if (display != null) {
- mLastRotation = display.getRotation();
- }
- }
-
- @Override
- public void onOrientationChanged(int orientation) {
- if (orientation == ORIENTATION_UNKNOWN) {
- return;
- }
-
- final Display display = mContext.getDisplay();
- if (display == null) {
- return;
- }
-
- final int rotation = display.getRotation();
- if (mLastRotation != rotation) {
- mLastRotation = rotation;
-
- if (mCurrentDialog != null) {
- mCurrentDialog.onOrientationChanged();
- }
- if (mUdfpsController != null) {
- mUdfpsController.onOrientationChanged();
- }
- if (mSidefpsController != null) {
- mSidefpsController.onOrientationChanged();
- }
- }
- }
- }
-
@NonNull
private final IFingerprintAuthenticatorsRegisteredCallback
mFingerprintAuthenticatorsRegisteredCallback =
@@ -204,6 +164,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
Log.w(TAG, "ACTION_CLOSE_SYSTEM_DIALOGS received");
mCurrentDialog.dismissWithoutCallback(true /* animate */);
mCurrentDialog = null;
+ mOrientationListener.disable();
try {
if (mReceiver != null) {
@@ -232,6 +193,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
Log.w(TAG, "Evicting client due to: " + topPackage);
mCurrentDialog.dismissWithoutCallback(true /* animate */);
mCurrentDialog = null;
+ mOrientationListener.disable();
if (mReceiver != null) {
mReceiver.onDialogDismissed(
@@ -470,8 +432,10 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
mUdfpsControllerFactory = udfpsControllerFactory;
mSidefpsControllerFactory = sidefpsControllerFactory;
mWindowManager = windowManager;
- mOrientationListener = new BiometricOrientationEventListener(context);
- mOrientationListener.enable();
+ mOrientationListener = new BiometricOrientationEventListener(context, () -> {
+ onOrientationChanged();
+ return Unit.INSTANCE;
+ });
mFaceProps = mFaceManager != null ? mFaceManager.getSensorPropertiesInternal() : null;
@@ -666,6 +630,18 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
// BiometricService will have already sent the callback to the client in this case.
// This avoids a round trip to SystemUI. So, just dismiss the dialog and we're done.
mCurrentDialog = null;
+ mOrientationListener.disable();
+ }
+
+ /**
+ * Whether the user's finger is currently on udfps attempting to authenticate.
+ */
+ public boolean isUdfpsFingerDown() {
+ if (mUdfpsController == null) {
+ return false;
+ }
+
+ return mUdfpsController.isFingerDown();
}
/**
@@ -737,6 +713,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
mReceiver = (IBiometricSysuiReceiver) args.arg2;
mCurrentDialog = newDialog;
mCurrentDialog.show(mWindowManager, savedState);
+ mOrientationListener.enable();
}
private void onDialogDismissed(@DismissedReason int reason) {
@@ -746,6 +723,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
}
mReceiver = null;
mCurrentDialog = null;
+ mOrientationListener.disable();
}
@Override
@@ -758,6 +736,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
mCurrentDialog.onSaveState(savedState);
mCurrentDialog.dismissWithoutCallback(false /* animate */);
mCurrentDialog = null;
+ mOrientationListener.disable();
// Only show the dialog if necessary. If it was animating out, the dialog is supposed
// to send its pending callback immediately.
@@ -778,6 +757,12 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
}
}
+ private void onOrientationChanged() {
+ if (mCurrentDialog != null) {
+ mCurrentDialog.onOrientationChanged();
+ }
+ }
+
protected AuthDialog buildDialog(PromptInfo promptInfo, boolean requireConfirmation,
int userId, int[] sensorIds, boolean credentialAllowed, String opPackageName,
boolean skipIntro, long operationId,
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricOrientationEventListener.kt b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricOrientationEventListener.kt
new file mode 100644
index 000000000000..08ea857eb208
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricOrientationEventListener.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics
+
+import android.content.Context
+import android.view.OrientationEventListener
+
+/**
+ * An [OrientationEventListener] that invokes the [onOrientationChanged] callback whenever
+ * the orientation of the device has changed in order to keep overlays for biometric sensors
+ * aligned with the device's screen.
+ */
+class BiometricOrientationEventListener(
+ private val context: Context,
+ private val onOrientationChanged: () -> Unit
+) : OrientationEventListener(context) {
+
+ /** 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
+ }
+
+ val rotation = context.display?.rotation ?: return
+ if (lastRotation != rotation) {
+ lastRotation = rotation
+
+ onOrientationChanged()
+ }
+ }
+
+ override fun enable() {
+ enabled = true
+ super.enable()
+ }
+
+ override fun disable() {
+ enabled = false
+ super.disable()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java
index 436e1e4e3116..a51c2b802b91 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java
@@ -41,6 +41,8 @@ import com.android.systemui.util.concurrency.DelayableExecutor;
import javax.inject.Inject;
+import kotlin.Unit;
+
/**
* Shows and hides the side fingerprint sensor (side-fps) overlay and handles side fps touch events.
*/
@@ -52,6 +54,8 @@ public class SidefpsController {
private final FingerprintManager mFingerprintManager;
private final WindowManager mWindowManager;
private final DelayableExecutor mFgExecutor;
+ @VisibleForTesting @NonNull final BiometricOrientationEventListener mOrientationListener;
+
// TODO: update mDisplayHeight and mDisplayWidth for multi-display devices
private final int mDisplayHeight;
private final int mDisplayWidth;
@@ -95,6 +99,10 @@ public class SidefpsController {
mFingerprintManager = checkNotNull(fingerprintManager);
mWindowManager = windowManager;
mFgExecutor = fgExecutor;
+ mOrientationListener = new BiometricOrientationEventListener(context, () -> {
+ onOrientationChanged();
+ return Unit.INSTANCE;
+ });
mSensorProps = findFirstSidefps();
checkArgument(mSensorProps != null);
@@ -119,14 +127,15 @@ public class SidefpsController {
mFingerprintManager.setSidefpsController(mSidefpsControllerImpl);
}
- void show() {
+ private void show() {
mView = (SidefpsView) mInflater.inflate(R.layout.sidefps_view, null, false);
mView.setSensorProperties(mSensorProps);
mWindowManager.addView(mView, computeLayoutParams());
+ mOrientationListener.enable();
}
- void hide() {
+ private void hide() {
if (mView != null) {
mWindowManager.removeView(mView);
mView.setOnTouchListener(null);
@@ -135,13 +144,16 @@ public class SidefpsController {
} else {
Log.v(TAG, "hideUdfpsOverlay | the overlay is already hidden");
}
+
+ mOrientationListener.disable();
}
- void onOrientationChanged() {
+ private void onOrientationChanged() {
// If mView is null or if view is hidden, then return.
if (mView == null || !mIsVisible) {
return;
}
+
// If the overlay needs to be displayed with a new configuration, destroy the current
// overlay, and re-create and show the overlay with the updated LayoutParams.
hide();
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 81e60f316bbd..ab3e042e9da7 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -16,7 +16,7 @@
package com.android.systemui.biometrics;
-import static android.os.VibrationEffect.Composition.PRIMITIVE_LOW_TICK;
+import static android.hardware.fingerprint.IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD;
import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkNotNull;
@@ -26,7 +26,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -46,8 +45,6 @@ import android.os.SystemClock;
import android.os.Trace;
import android.os.VibrationEffect;
import android.os.Vibrator;
-import android.provider.Settings;
-import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -79,6 +76,8 @@ import java.util.Optional;
import javax.inject.Inject;
+import kotlin.Unit;
+
/**
* Shows and hides the under-display fingerprint sensor (UDFPS) overlay, handles UDFPS touch events,
* and coordinates triggering of the high-brightness mode (HBM).
@@ -118,6 +117,7 @@ public class UdfpsController implements DozeReceiver {
@NonNull private final AccessibilityManager mAccessibilityManager;
@NonNull private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
@Nullable private final UdfpsHbmProvider mHbmProvider;
+ @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.
@VisibleForTesting final FingerprintSensorPropertiesInternal mSensorProps;
@@ -156,16 +156,8 @@ public class UdfpsController implements DozeReceiver {
.setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
.build();
- public static final VibrationEffect EFFECT_TICK =
- VibrationEffect.get(VibrationEffect.EFFECT_TICK);
- private static final VibrationEffect EFFECT_TEXTURE_TICK =
- VibrationEffect.get(VibrationEffect.EFFECT_TEXTURE_TICK);
- @VisibleForTesting
- static final VibrationEffect EFFECT_CLICK = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
- private static final VibrationEffect EFFECT_HEAVY =
- VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK);
- private static final VibrationEffect EFFECT_DOUBLE_CLICK =
- VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
+ public static final VibrationEffect EFFECT_CLICK =
+ VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
private final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
@Override
@@ -314,8 +306,10 @@ public class UdfpsController implements DozeReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (mServerRequest != null
+ && mServerRequest.mRequestReason != REASON_AUTH_FPM_KEYGUARD
&& Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
- Log.d(TAG, "ACTION_CLOSE_SYSTEM_DIALOGS received");
+ Log.d(TAG, "ACTION_CLOSE_SYSTEM_DIALOGS received, mRequestReason: "
+ + mServerRequest.mRequestReason);
mServerRequest.onUserCanceled();
mServerRequest = null;
updateOverlay();
@@ -431,7 +425,6 @@ public class UdfpsController implements DozeReceiver {
mTouchLogTime = SystemClock.elapsedRealtime();
mPowerManager.userActivity(SystemClock.uptimeMillis(),
PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0);
- playStartHaptic();
handled = true;
} else if (sinceLastLog >= MIN_TOUCH_LOG_INTERVAL) {
Log.v(TAG, "onTouch | finger move: " + touchInfo);
@@ -511,6 +504,10 @@ 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;
+ });
mSensorProps = findFirstUdfps();
// At least one UDFPS sensor exists
@@ -542,18 +539,7 @@ public class UdfpsController implements DozeReceiver {
@VisibleForTesting
public void playStartHaptic() {
if (mVibrator != null) {
- final ContentResolver contentResolver =
- mContext.getContentResolver();
- // TODO: these settings checks should eventually be removed after ux testing
- // (b/185124905)
- int startEnabled = Settings.Global.getInt(contentResolver,
- "udfps_start", 1);
- if (startEnabled > 0) {
- String startEffectSetting = Settings.Global.getString(
- contentResolver, "udfps_start_type");
- mVibrator.vibrate(getVibration(startEffectSetting,
- EFFECT_CLICK), VIBRATION_SONIFICATION_ATTRIBUTES);
- }
+ mVibrator.vibrate(EFFECT_CLICK, VIBRATION_SONIFICATION_ATTRIBUTES);
}
}
@@ -626,9 +612,12 @@ public class UdfpsController implements DozeReceiver {
// Gets the size based on the current rotation of the display.
mContext.getDisplay().getRealSize(p);
- // Transform dimensions if the device is in landscape mode.
+ // Transform dimensions if the device is in landscape mode
switch (mContext.getDisplay().getRotation()) {
case Surface.ROTATION_90:
+ if (animation instanceof UdfpsKeyguardViewController) {
+ break;
+ }
mCoreLayoutParams.x = mSensorProps.sensorLocationY - mSensorProps.sensorRadius
- paddingX;
mCoreLayoutParams.y = p.y - mSensorProps.sensorLocationX - mSensorProps.sensorRadius
@@ -636,6 +625,9 @@ public class UdfpsController implements DozeReceiver {
break;
case Surface.ROTATION_270:
+ if (animation instanceof UdfpsKeyguardViewController) {
+ break;
+ }
mCoreLayoutParams.x = p.x - mSensorProps.sensorLocationY - mSensorProps.sensorRadius
- paddingX;
mCoreLayoutParams.y = mSensorProps.sensorLocationX - mSensorProps.sensorRadius
@@ -644,13 +636,14 @@ public class UdfpsController implements DozeReceiver {
default:
// Do nothing to stay in portrait mode.
+ // Keyguard is always in portrait mode.
}
// avoid announcing window title
mCoreLayoutParams.accessibilityTitle = " ";
return mCoreLayoutParams;
}
- void onOrientationChanged() {
+ private void onOrientationChanged() {
// When the configuration changes it's almost always necessary to destroy and re-create
// the overlay's window to pass it the new LayoutParams.
// Hiding the overlay will destroy its window. It's safe to hide the overlay regardless
@@ -668,6 +661,7 @@ public class UdfpsController implements DozeReceiver {
if (mView == null) {
try {
Log.v(TAG, "showUdfpsOverlay | adding window reason=" + reason);
+
mView = (UdfpsView) mInflater.inflate(R.layout.udfps_view, null, false);
mOnFingerDown = false;
mView.setSensorProperties(mSensorProps);
@@ -675,11 +669,13 @@ public class UdfpsController implements DozeReceiver {
UdfpsAnimationViewController animation = inflateUdfpsAnimation(reason);
animation.init();
mView.setAnimationViewController(animation);
+ mOrientationListener.enable();
// This view overlaps the sensor area, so prevent it from being selectable
// during a11y.
if (reason == IUdfpsOverlayController.REASON_ENROLL_FIND_SENSOR
- || reason == IUdfpsOverlayController.REASON_ENROLL_ENROLLING) {
+ || reason == IUdfpsOverlayController.REASON_ENROLL_ENROLLING
+ || reason == IUdfpsOverlayController.REASON_AUTH_BP) {
mView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
}
@@ -768,6 +764,8 @@ public class UdfpsController implements DozeReceiver {
} else {
Log.v(TAG, "hideUdfpsOverlay | the overlay is already hidden");
}
+
+ mOrientationListener.disable();
}
/**
@@ -822,12 +820,19 @@ public class UdfpsController implements DozeReceiver {
mIsAodInterruptActive = false;
}
+ public boolean isFingerDown() {
+ return mOnFingerDown;
+ }
+
private void onFingerDown(int x, int y, float minor, float major) {
mExecution.assertIsMainThread();
if (mView == null) {
Log.w(TAG, "Null view in onFingerDown");
return;
}
+ if (!mOnFingerDown) {
+ playStartHaptic();
+ }
mOnFingerDown = true;
mFingerprintManager.onPointerDown(mSensorProps.sensorId, x, y, minor, major);
Trace.endAsyncSection("UdfpsController.e2e.onPointerDown", 0);
@@ -855,38 +860,6 @@ public class UdfpsController implements DozeReceiver {
}
}
- /**
- * get vibration to play given string
- * used for testing purposes (b/185124905)
- */
- public static VibrationEffect getVibration(String effect, VibrationEffect defaultEffect) {
- if (TextUtils.isEmpty(effect)) {
- return defaultEffect;
- }
-
- switch (effect.toLowerCase()) {
- case "click":
- return EFFECT_CLICK;
- case "heavy":
- return EFFECT_HEAVY;
- case "texture_tick":
- return EFFECT_TEXTURE_TICK;
- case "tick":
- return EFFECT_TICK;
- case "double_tap":
- return EFFECT_DOUBLE_CLICK;
- default:
- try {
- int primitive = Integer.parseInt(effect);
- if (primitive <= PRIMITIVE_LOW_TICK && primitive > -1) {
- return VibrationEffect.startComposition().addPrimitive(primitive).compose();
- }
- } catch (NumberFormatException e) {
- }
- return defaultEffect;
- }
- }
-
private void updateTouchListener() {
if (mView == null) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
index ec96af3ef500..131618442c22 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
@@ -43,6 +43,7 @@ import com.android.systemui.statusbar.StatusBarState;
import com.airbnb.lottie.LottieAnimationView;
import com.airbnb.lottie.LottieProperty;
import com.airbnb.lottie.model.KeyPath;
+
/**
* View corresponding with udfps_keyguard_view.xml
*/
@@ -114,12 +115,10 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
@Override
void onIlluminationStarting() {
- setVisibility(View.INVISIBLE);
}
@Override
void onIlluminationStopped() {
- setVisibility(View.VISIBLE);
}
@Override
@@ -140,9 +139,12 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
mAodFp.setTranslationX(mBurnInOffsetX);
mAodFp.setTranslationY(mBurnInOffsetY);
mAodFp.setProgress(mBurnInProgress);
+ mAodFp.setAlpha(255 * mInterpolatedDarkAmount);
mLockScreenFp.setTranslationX(mBurnInOffsetX);
mLockScreenFp.setTranslationY(mBurnInOffsetY);
+ mLockScreenFp.setProgress(1f - mInterpolatedDarkAmount);
+ mLockScreenFp.setAlpha((1f - mInterpolatedDarkAmount) * 255);
}
void requestUdfps(boolean request, int color) {
@@ -209,14 +211,6 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
mHintAnimator.cancel();
mInterpolatedDarkAmount = eased;
updateBurnInOffsets();
- mLockScreenFp.setProgress(1f - mInterpolatedDarkAmount);
- mAodFp.setAlpha(mInterpolatedDarkAmount);
-
- if (linear == 1f) {
- mLockScreenFp.setVisibility(View.INVISIBLE);
- } else {
- mLockScreenFp.setVisibility(View.VISIBLE);
- }
}
void animateHint() {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index 819de538c840..51124fb28ad1 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -41,6 +41,7 @@ import com.android.systemui.util.concurrency.DelayableExecutor;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+
/**
* Class that coordinates non-HBM animations during keyguard authentication.
*
@@ -66,6 +67,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
private boolean mHintShown;
private int mStatusBarState;
private float mTransitionToFullShadeProgress;
+ private float mLastDozeAmount;
/**
* hidden amount of pin/pattern/password bouncer
@@ -108,6 +110,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
updateFaceDetectRunning(mKeyguardUpdateMonitor.isFaceDetectionRunning());
final float dozeAmount = mStatusBarStateController.getDozeAmount();
+ mLastDozeAmount = dozeAmount;
mStateListener.onDozeAmountChanged(dozeAmount, dozeAmount);
mStatusBarStateController.addCallback(mStateListener);
@@ -205,7 +208,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
return true;
}
- if (mInputBouncerHiddenAmount < .4f || mIsBouncerVisible) {
+ if (mInputBouncerHiddenAmount < .5f || mIsBouncerVisible) {
return true;
}
@@ -277,8 +280,9 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
private void updateAlpha() {
// fade icon on transition to showing bouncer
int alpha = mShowingUdfpsBouncer ? 255
- : Math.abs((int) MathUtils.constrainedMap(0f, 255f, .4f, .7f,
- mInputBouncerHiddenAmount));
+ : (int) MathUtils.constrain(
+ MathUtils.map(.5f, .9f, 0f, 255f, mInputBouncerHiddenAmount),
+ 0f, 255f);
alpha *= (1.0f - mTransitionToFullShadeProgress);
mView.setUnpausedAlpha(alpha);
}
@@ -287,8 +291,11 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
new StatusBarStateController.StateListener() {
@Override
public void onDozeAmountChanged(float linear, float eased) {
- if (linear != 0) showUdfpsBouncer(false);
+ if (mLastDozeAmount < linear) {
+ showUdfpsBouncer(false);
+ }
mView.onDozeAmountChanged(linear, eased);
+ mLastDozeAmount = linear;
updatePauseAuth();
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
index 809e7a70d66c..37a6cfaabb5e 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
@@ -33,7 +33,6 @@ import com.android.internal.logging.MetricsLogger;
import com.android.systemui.classifier.FalsingDataProvider.SessionListener;
import com.android.systemui.classifier.HistoryTracker.BeliefListener;
import com.android.systemui.dagger.qualifiers.TestHarness;
-import com.android.systemui.dock.DockManager;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -66,7 +65,6 @@ public class BrightLineFalsingManager implements FalsingManager {
private static final double FALSE_BELIEF_THRESHOLD = 0.9;
private final FalsingDataProvider mDataProvider;
- private final DockManager mDockManager;
private final SingleTapClassifier mSingleTapClassifier;
private final DoubleTapClassifier mDoubleTapClassifier;
private final HistoryTracker mHistoryTracker;
@@ -173,14 +171,13 @@ public class BrightLineFalsingManager implements FalsingManager {
@Inject
public BrightLineFalsingManager(FalsingDataProvider falsingDataProvider,
- DockManager dockManager, MetricsLogger metricsLogger,
+ MetricsLogger metricsLogger,
@Named(BRIGHT_LINE_GESTURE_CLASSIFERS) Set<FalsingClassifier> classifiers,
SingleTapClassifier singleTapClassifier, DoubleTapClassifier doubleTapClassifier,
HistoryTracker historyTracker, KeyguardStateController keyguardStateController,
AccessibilityManager accessibilityManager,
@TestHarness boolean testHarness) {
mDataProvider = falsingDataProvider;
- mDockManager = dockManager;
mMetricsLogger = metricsLogger;
mClassifiers = classifiers;
mSingleTapClassifier = singleTapClassifier;
@@ -332,7 +329,7 @@ public class BrightLineFalsingManager implements FalsingManager {
|| !mKeyguardStateController.isShowing()
|| mTestHarness
|| mDataProvider.isJustUnlockedWithFace()
- || mDockManager.isDocked()
+ || mDataProvider.isDocked()
|| mAccessibilityManager.isEnabled();
}
@@ -400,7 +397,7 @@ public class BrightLineFalsingManager implements FalsingManager {
ipw.print("mJustUnlockedWithFace=");
ipw.println(mDataProvider.isJustUnlockedWithFace() ? 1 : 0);
ipw.print("isDocked=");
- ipw.println(mDockManager.isDocked() ? 1 : 0);
+ ipw.println(mDataProvider.isDocked() ? 1 : 0);
ipw.print("width=");
ipw.println(mDataProvider.getWidthPixels());
ipw.print("height=");
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
index 969736910b5e..14e5991f35d2 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
@@ -16,6 +16,8 @@
package com.android.systemui.classifier;
+import static com.android.systemui.dock.DockManager.DockEventListener;
+
import android.hardware.SensorManager;
import android.hardware.biometrics.BiometricSourceType;
import android.util.Log;
@@ -25,9 +27,12 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dock.DockManager;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.sensors.ProximitySensor;
@@ -53,6 +58,8 @@ class FalsingCollectorImpl implements FalsingCollector {
private final ProximitySensor mProximitySensor;
private final StatusBarStateController mStatusBarStateController;
private final KeyguardStateController mKeyguardStateController;
+ private final BatteryController mBatteryController;
+ private final DockManager mDockManager;
private final DelayableExecutor mMainExecutor;
private final SystemClock mSystemClock;
@@ -89,12 +96,46 @@ class FalsingCollectorImpl implements FalsingCollector {
}
};
+
+ private final BatteryStateChangeCallback mBatteryListener = new BatteryStateChangeCallback() {
+ @Override
+ public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+ }
+
+ @Override
+ public void onWirelessChargingChanged(boolean isWirelessCharging) {
+ if (isWirelessCharging || mDockManager.isDocked()) {
+ mProximitySensor.pause();
+ } else {
+ mProximitySensor.resume();
+ }
+ }
+ };
+
+ private final DockEventListener mDockEventListener = new DockEventListener() {
+ @Override
+ public void onEvent(int event) {
+ if (event == DockManager.STATE_NONE && !mBatteryController.isWirelessCharging()) {
+ mProximitySensor.resume();
+ } else {
+ mProximitySensor.pause();
+ }
+ }
+ };
+
@Inject
- FalsingCollectorImpl(FalsingDataProvider falsingDataProvider, FalsingManager falsingManager,
- KeyguardUpdateMonitor keyguardUpdateMonitor, HistoryTracker historyTracker,
- ProximitySensor proximitySensor, StatusBarStateController statusBarStateController,
+ FalsingCollectorImpl(
+ FalsingDataProvider falsingDataProvider,
+ FalsingManager falsingManager,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ HistoryTracker historyTracker,
+ ProximitySensor proximitySensor,
+ StatusBarStateController statusBarStateController,
KeyguardStateController keyguardStateController,
- @Main DelayableExecutor mainExecutor, SystemClock systemClock) {
+ BatteryController batteryController,
+ DockManager dockManager,
+ @Main DelayableExecutor mainExecutor,
+ SystemClock systemClock) {
mFalsingDataProvider = falsingDataProvider;
mFalsingManager = falsingManager;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
@@ -102,10 +143,11 @@ class FalsingCollectorImpl implements FalsingCollector {
mProximitySensor = proximitySensor;
mStatusBarStateController = statusBarStateController;
mKeyguardStateController = keyguardStateController;
+ mBatteryController = batteryController;
+ mDockManager = dockManager;
mMainExecutor = mainExecutor;
mSystemClock = systemClock;
-
mProximitySensor.setTag(PROXIMITY_SENSOR_TAG);
mProximitySensor.setDelay(SensorManager.SENSOR_DELAY_GAME);
@@ -113,6 +155,9 @@ class FalsingCollectorImpl implements FalsingCollector {
mState = mStatusBarStateController.getState();
mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateCallback);
+
+ mBatteryController.addCallback(mBatteryListener);
+ mDockManager.addListener(mDockEventListener);
}
@Override
@@ -312,6 +357,8 @@ class FalsingCollectorImpl implements FalsingCollector {
unregisterSensors();
mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateCallback);
mStatusBarStateController.removeCallback(mStatusBarStateListener);
+ mBatteryController.removeCallback(mBatteryListener);
+ mDockManager.removeListener(mDockEventListener);
}
@Override
@@ -351,9 +398,7 @@ class FalsingCollectorImpl implements FalsingCollector {
}
private void registerSensors() {
- if (!mFalsingDataProvider.isWirelessCharging()) {
- mProximitySensor.register(mSensorEventListener);
- }
+ mProximitySensor.register(mSensorEventListener);
}
private void unregisterSensors() {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
index 2f688dd9d247..a3ecb0c0b273 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
@@ -22,6 +22,7 @@ import android.view.MotionEvent.PointerCoords;
import android.view.MotionEvent.PointerProperties;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dock.DockManager;
import com.android.systemui.statusbar.policy.BatteryController;
import java.util.ArrayList;
@@ -40,7 +41,8 @@ public class FalsingDataProvider {
private final int mWidthPixels;
private final int mHeightPixels;
- private final BatteryController mBatteryController;
+ private BatteryController mBatteryController;
+ private final DockManager mDockManager;
private final float mXdpi;
private final float mYdpi;
private final List<SessionListener> mSessionListeners = new ArrayList<>();
@@ -59,12 +61,16 @@ public class FalsingDataProvider {
private boolean mJustUnlockedWithFace;
@Inject
- public FalsingDataProvider(DisplayMetrics displayMetrics, BatteryController batteryController) {
+ public FalsingDataProvider(
+ DisplayMetrics displayMetrics,
+ BatteryController batteryController,
+ DockManager dockManager) {
mXdpi = displayMetrics.xdpi;
mYdpi = displayMetrics.ydpi;
mWidthPixels = displayMetrics.widthPixels;
mHeightPixels = displayMetrics.heightPixels;
mBatteryController = batteryController;
+ mDockManager = dockManager;
FalsingClassifier.logInfo("xdpi, ydpi: " + getXdpi() + ", " + getYdpi());
FalsingClassifier.logInfo("width, height: " + getWidthPixels() + ", " + getHeightPixels());
@@ -219,11 +225,6 @@ public class FalsingDataProvider {
return mLastMotionEvent.getY() < mFirstRecentMotionEvent.getY();
}
- /** Returns true if phone is being charged without a cable. */
- public boolean isWirelessCharging() {
- return mBatteryController.isWirelessCharging();
- }
-
private void recalculateData() {
if (!mDirty) {
return;
@@ -357,6 +358,11 @@ public class FalsingDataProvider {
mJustUnlockedWithFace = justUnlockedWithFace;
}
+ /** Returns true if phone is sitting in a dock or is wirelessly charging. */
+ public boolean isDocked() {
+ return mBatteryController.isWirelessCharging() || mDockManager.isDocked();
+ }
+
/** Implement to be alerted abotu the beginning and ending of falsing tracking. */
public interface SessionListener {
/** Called when the lock screen is shown and falsing-tracking begins. */
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 8a9fc2685a71..277ecdfef52f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1536,8 +1536,10 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable,
return;
}
- // if the keyguard is already showing, don't bother
- if (mKeyguardViewControllerLazy.get().isShowing()) {
+ // if the keyguard is already showing, don't bother. check flags in both files
+ // to account for the hiding animation which results in a delay and discrepancy
+ // between flags
+ if (mShowing && mKeyguardViewControllerLazy.get().isShowing()) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
resetStateLocked();
return;
@@ -2339,7 +2341,6 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable,
// only play "unlock" noises if not on a call (since the incall UI
// disables the keyguard)
if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)) {
- Log.i("TEST", "playSounds: false");
playSounds(false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index 902e8c28a85d..15a70831b2f9 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -475,6 +475,13 @@ public class MediaControlPanel {
@Nullable
private ActivityLaunchAnimator.Controller buildLaunchAnimatorController(
TransitionLayout player) {
+ if (!(player.getParent() instanceof ViewGroup)) {
+ // TODO(b/192194319): Throw instead of just logging.
+ Log.wtf(TAG, "Skipping player animation as it is not attached to a ViewGroup",
+ new Exception());
+ return null;
+ }
+
// TODO(b/174236650): Make sure that the carousel indicator also fades out.
// TODO(b/174236650): Instrument the animation to measure jank.
return new GhostedViewLaunchAnimatorController(player,
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
index 7ab4b6f200ed..a16b92f494a4 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
@@ -47,6 +47,7 @@ import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
+import android.graphics.ImageDecoder;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.graphics.text.LineBreaker;
@@ -59,6 +60,7 @@ import android.text.TextUtils;
import android.util.IconDrawableFactory;
import android.util.Log;
import android.util.Pair;
+import android.util.Size;
import android.util.SizeF;
import android.util.TypedValue;
import android.view.Gravity;
@@ -79,6 +81,7 @@ import com.android.systemui.people.widget.LaunchConversationActivity;
import com.android.systemui.people.widget.PeopleSpaceWidgetProvider;
import com.android.systemui.people.widget.PeopleTileKey;
+import java.io.IOException;
import java.text.NumberFormat;
import java.time.Duration;
import java.util.ArrayList;
@@ -178,6 +181,7 @@ public class PeopleTileViewHelper {
private int mWidth;
private int mHeight;
private int mLayoutSize;
+ private boolean mIsLeftToRight;
private Locale mLocale;
private NumberFormat mIntegerFormat;
@@ -192,6 +196,8 @@ public class PeopleTileViewHelper {
mWidth = width;
mHeight = height;
mLayoutSize = getLayoutSize();
+ mIsLeftToRight = TextUtils.getLayoutDirectionFromLocale(Locale.getDefault())
+ == View.LAYOUT_DIRECTION_LTR;
}
/**
@@ -501,6 +507,8 @@ public class PeopleTileViewHelper {
views.setViewVisibility(R.id.availability, View.VISIBLE);
startPadding = mContext.getResources().getDimensionPixelSize(
R.dimen.availability_dot_shown_padding);
+ views.setContentDescription(R.id.availability,
+ mContext.getString(R.string.person_available));
} else {
views.setViewVisibility(R.id.availability, View.GONE);
startPadding = mContext.getResources().getDimensionPixelSize(
@@ -654,7 +662,7 @@ public class PeopleTileViewHelper {
private RemoteViews createMissedCallRemoteViews() {
RemoteViews views = setViewForContentLayout(new RemoteViews(mContext.getPackageName(),
getLayoutForContent()));
- views.setViewVisibility(R.id.predefined_icon, View.VISIBLE);
+ setPredefinedIconVisible(views);
views.setViewVisibility(R.id.text_content, View.VISIBLE);
views.setViewVisibility(R.id.messages_count, View.GONE);
setMaxLines(views, false);
@@ -673,19 +681,39 @@ public class PeopleTileViewHelper {
return views;
}
+ private void setPredefinedIconVisible(RemoteViews views) {
+ views.setViewVisibility(R.id.predefined_icon, View.VISIBLE);
+ if (mLayoutSize == LAYOUT_MEDIUM) {
+ int endPadding = mContext.getResources().getDimensionPixelSize(
+ R.dimen.before_predefined_icon_padding);
+ views.setViewPadding(R.id.name, mIsLeftToRight ? 0 : endPadding, 0,
+ mIsLeftToRight ? endPadding : 0,
+ 0);
+ }
+ }
+
private RemoteViews createNotificationRemoteViews() {
RemoteViews views = setViewForContentLayout(new RemoteViews(mContext.getPackageName(),
getLayoutForNotificationContent()));
CharSequence sender = mTile.getNotificationSender();
- Uri image = mTile.getNotificationDataUri();
- if (image != null) {
- // TODO: Use NotificationInlineImageCache
- views.setImageViewUri(R.id.image, image);
+ Uri imageUri = mTile.getNotificationDataUri();
+ if (imageUri != null) {
String newImageDescription = mContext.getString(
R.string.new_notification_image_content_description, mTile.getUserName());
views.setContentDescription(R.id.image, newImageDescription);
views.setViewVisibility(R.id.image, View.VISIBLE);
views.setViewVisibility(R.id.text_content, View.GONE);
+ try {
+ Drawable drawable = resolveImage(imageUri, mContext);
+ Bitmap bitmap = convertDrawableToBitmap(drawable);
+ views.setImageViewBitmap(R.id.image, bitmap);
+ } catch (IOException e) {
+ Log.e(TAG, "Could not decode image: " + e);
+ // If we couldn't load the image, show text that we have a new image.
+ views.setTextViewText(R.id.text_content, newImageDescription);
+ views.setViewVisibility(R.id.text_content, View.VISIBLE);
+ views.setViewVisibility(R.id.image, View.GONE);
+ }
} else {
setMaxLines(views, !TextUtils.isEmpty(sender));
CharSequence content = mTile.getNotificationContent();
@@ -703,6 +731,13 @@ public class PeopleTileViewHelper {
views.setImageViewResource(R.id.predefined_icon, R.drawable.ic_message);
}
if (mTile.getMessagesCount() > 1) {
+ if (mLayoutSize == LAYOUT_MEDIUM) {
+ int endPadding = mContext.getResources().getDimensionPixelSize(
+ R.dimen.before_messages_count_padding);
+ views.setViewPadding(R.id.name, mIsLeftToRight ? 0 : endPadding, 0,
+ mIsLeftToRight ? endPadding : 0,
+ 0);
+ }
views.setViewVisibility(R.id.messages_count, View.VISIBLE);
views.setTextViewText(R.id.messages_count,
getMessagesCountText(mTile.getMessagesCount()));
@@ -720,6 +755,40 @@ public class PeopleTileViewHelper {
return views;
}
+ private Drawable resolveImage(Uri uri, Context context) throws IOException {
+ final ImageDecoder.Source source =
+ ImageDecoder.createSource(context.getContentResolver(), uri);
+ final Drawable drawable =
+ ImageDecoder.decodeDrawable(source, (decoder, info, s) -> {
+ onHeaderDecoded(decoder, info, s);
+ });
+ return drawable;
+ }
+
+ private static int getPowerOfTwoForSampleRatio(double ratio) {
+ final int k = Integer.highestOneBit((int) Math.floor(ratio));
+ return Math.max(1, k);
+ }
+
+ private void onHeaderDecoded(ImageDecoder decoder, ImageDecoder.ImageInfo info,
+ ImageDecoder.Source source) {
+ int widthInPx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mWidth,
+ mContext.getResources().getDisplayMetrics());
+ int heightInPx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mHeight,
+ mContext.getResources().getDisplayMetrics());
+ int maxIconSizeInPx = Math.max(widthInPx, heightInPx);
+ int minDimen = (int) (1.5 * Math.min(widthInPx, heightInPx));
+ if (minDimen < maxIconSizeInPx) {
+ maxIconSizeInPx = minDimen;
+ }
+ final Size size = info.getSize();
+ final int originalSize = Math.max(size.getHeight(), size.getWidth());
+ final double ratio = (originalSize > maxIconSizeInPx)
+ ? originalSize * 1f / maxIconSizeInPx
+ : 1.0;
+ decoder.setTargetSampleSize(getPowerOfTwoForSampleRatio(ratio));
+ }
+
private void setContentDescriptionForNotificationTextContent(RemoteViews views,
CharSequence content, CharSequence sender) {
String newTextDescriptionWithNotificationContent = mContext.getString(
@@ -755,7 +824,7 @@ public class PeopleTileViewHelper {
if (TextUtils.isEmpty(statusText)) {
statusText = getStatusTextByType(status.getActivity());
}
- views.setViewVisibility(R.id.predefined_icon, View.VISIBLE);
+ setPredefinedIconVisible(views);
views.setTextViewText(R.id.text_content, statusText);
if (status.getActivity() == ACTIVITY_BIRTHDAY
@@ -865,13 +934,11 @@ public class PeopleTileViewHelper {
* on the status layouts compared to all other layouts.
*/
private void setAvailabilityDotPadding(RemoteViews views, int resId) {
- boolean isLeftToRight = TextUtils.getLayoutDirectionFromLocale(Locale.getDefault())
- == View.LAYOUT_DIRECTION_LTR;
int startPadding = mContext.getResources().getDimensionPixelSize(resId);
int bottomPadding = mContext.getResources().getDimensionPixelSize(
R.dimen.medium_content_padding_above_name);
views.setViewPadding(R.id.medium_content,
- isLeftToRight ? startPadding : 0, 0, isLeftToRight ? 0 : startPadding,
+ mIsLeftToRight ? startPadding : 0, 0, mIsLeftToRight ? 0 : startPadding,
bottomPadding);
}
@@ -1069,6 +1136,7 @@ public class PeopleTileViewHelper {
views.setViewPadding(R.id.content, horizontalPadding, verticalPadding,
horizontalPadding,
verticalPadding);
+ views.setViewPadding(R.id.name, 0, 0, 0, 0);
// Expand the name font on medium if there's space.
int heightRequiredForMaxContentText = (int) (mContext.getResources().getDimension(
R.dimen.medium_height_for_max_name_text_size) / mDensity);
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
index 3320fbda6fe5..985903435b9a 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
@@ -375,7 +375,7 @@ public class PeopleSpaceWidgetManager {
widgetSp.getInt(USER_ID, INVALID_USER_ID),
widgetSp.getString(PACKAGE_NAME, EMPTY_STRING));
- return getTileFromPersistentStorage(key, appWidgetId);
+ return getTileFromPersistentStorage(key, appWidgetId, /* supplementFromStorage= */ true);
}
/**
@@ -383,7 +383,8 @@ public class PeopleSpaceWidgetManager {
* If a {@link PeopleTileKey} is not provided, fetch one from {@link SharedPreferences}.
*/
@Nullable
- public PeopleSpaceTile getTileFromPersistentStorage(PeopleTileKey key, int appWidgetId) throws
+ public PeopleSpaceTile getTileFromPersistentStorage(PeopleTileKey key, int appWidgetId,
+ boolean supplementFromStorage) throws
PackageManager.NameNotFoundException {
if (!PeopleTileKey.isValid(key)) {
Log.e(TAG, "PeopleTileKey invalid: " + key.toString());
@@ -412,7 +413,8 @@ public class PeopleSpaceWidgetManager {
// Supplement with our storage.
String contactUri = mSharedPrefs.getString(String.valueOf(appWidgetId), null);
- if (contactUri != null && storedTile.build().getContactUri() == null) {
+ if (supplementFromStorage && contactUri != null
+ && storedTile.build().getContactUri() == null) {
if (DEBUG) Log.d(TAG, "Restore contact uri from storage: " + contactUri);
storedTile.setContactUri(Uri.parse(contactUri));
}
@@ -811,7 +813,8 @@ public class PeopleSpaceWidgetManager {
if (DEBUG) Log.d(TAG, "addNewWidget called with key for appWidgetId: " + appWidgetId);
PeopleSpaceTile tile = null;
try {
- tile = getTileFromPersistentStorage(key, appWidgetId);
+ tile = getTileFromPersistentStorage(key, appWidgetId, /* supplementFromStorage= */
+ false);
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "Cannot add widget since app was uninstalled");
return;
@@ -850,7 +853,9 @@ public class PeopleSpaceWidgetManager {
} catch (Exception e) {
Log.w(TAG, "Exception caching shortcut:" + e);
}
- updateAppWidgetOptionsAndView(appWidgetId, tile);
+ PeopleSpaceTile finalTile = tile;
+ mBgExecutor.execute(
+ () -> updateAppWidgetOptionsAndView(appWidgetId, finalTile));
}
/** Registers a conversation listener for {@code appWidgetId} if not already registered. */
@@ -1071,7 +1076,7 @@ public class PeopleSpaceWidgetManager {
return;
}
for (int appWidgetId : appWidgetIds) {
- if (DEBUG) Log.d(TAG, "Updating widget from broadcast, widget id: " + appWidgetId);
+ if (DEBUG) Log.d(TAG, "Updating widget from broadcast, widget id: " + appWidgetId);
PeopleSpaceTile existingTile = null;
PeopleSpaceTile updatedTile = null;
try {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index bcce87a51097..929927e5d4e4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -44,6 +44,7 @@ import com.android.systemui.Dependency;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
@@ -57,6 +58,7 @@ public class QSDetail extends LinearLayout {
private final UiEventLogger mUiEventLogger = QSEvents.INSTANCE.getQsUiEventsLogger();
private ViewGroup mDetailContent;
+ private FalsingManager mFalsingManager;
protected TextView mDetailSettingsButton;
protected TextView mDetailDoneButton;
@VisibleForTesting
@@ -124,12 +126,13 @@ public class QSDetail extends LinearLayout {
/** */
public void setQsPanel(QSPanelController panelController, QuickStatusBarHeader header,
- QSFooter footer) {
+ QSFooter footer, FalsingManager falsingManager) {
mQsPanelController = panelController;
mHeader = header;
mFooter = footer;
mHeader.setCallback(mQsPanelCallback);
mQsPanelController.setCallback(mQsPanelCallback);
+ mFalsingManager = falsingManager;
}
public void setHost(QSTileHost host) {
@@ -209,6 +212,11 @@ public class QSDetail extends LinearLayout {
Dependency.get(CommandQueue.class).animateCollapsePanels();
mTriggeredExpand = false;
}
+ // Always animate on close, even if the last opened detail adapter had shouldAnimate()
+ // return false. This is necessary to avoid a race condition which could leave the
+ // keyguard in a bad state where QS remains visible underneath the notifications, clock,
+ // and status area.
+ mShouldAnimate = true;
}
boolean visibleDiff = wasShowingDetail != showingDetail;
@@ -242,10 +250,15 @@ public class QSDetail extends LinearLayout {
mClosingDetail = true;
mDetailAdapter = null;
listener = mTeardownDetailWhenDone;
- mHeader.setVisibility(View.VISIBLE);
- mFooter.setVisibility(View.VISIBLE);
- mQsPanelController.setGridContentVisibility(true);
- mQsPanelCallback.onScanStateChanged(false);
+ // Only update visibility if already expanded. Otherwise, a race condition can cause the
+ // keyguard to enter a bad state where the QS tiles are displayed underneath the
+ // notifications, clock, and status area.
+ if (mQsPanelController.isExpanded()) {
+ mHeader.setVisibility(View.VISIBLE);
+ mFooter.setVisibility(View.VISIBLE);
+ mQsPanelController.setGridContentVisibility(true);
+ mQsPanelCallback.onScanStateChanged(false);
+ }
}
sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
animateDetailVisibleDiff(x, y, visibleDiff, listener);
@@ -273,6 +286,9 @@ public class QSDetail extends LinearLayout {
final Intent settingsIntent = adapter.getSettingsIntent();
mDetailSettingsButton.setVisibility(settingsIntent != null ? VISIBLE : GONE);
mDetailSettingsButton.setOnClickListener(v -> {
+ if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+ return;
+ }
Dependency.get(MetricsLogger.class).action(ACTION_QS_MORE_SETTINGS,
adapter.getMetricsCategory());
mUiEventLogger.log(adapter.moreSettingsEvent());
@@ -280,6 +296,9 @@ public class QSDetail extends LinearLayout {
.postStartActivityDismissingKeyguard(settingsIntent, 0);
});
mDetailDoneButton.setOnClickListener(v -> {
+ if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+ return;
+ }
announceForAccessibility(
mContext.getString(R.string.accessibility_desc_quick_settings));
if (!adapter.onDoneButtonClicked()) {
@@ -301,13 +320,13 @@ public class QSDetail extends LinearLayout {
mQsDetailHeaderSwitch.setVisibility(VISIBLE);
handleToggleStateChanged(toggleState, adapter.getToggleEnabled());
mQsDetailHeader.setClickable(true);
- mQsDetailHeader.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- boolean checked = !mQsDetailHeaderSwitch.isChecked();
- mQsDetailHeaderSwitch.setChecked(checked);
- adapter.setToggleState(checked);
+ mQsDetailHeader.setOnClickListener(v -> {
+ if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+ return;
}
+ boolean checked = !mQsDetailHeaderSwitch.isChecked();
+ mQsDetailHeaderSwitch.setChecked(checked);
+ adapter.setToggleState(checked);
});
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 36b4ee987d99..0a1e9d04fab0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -39,6 +39,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.media.MediaHost;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.customize.QSCustomizerController;
@@ -67,6 +68,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
private final Rect mQsBounds = new Rect();
private final StatusBarStateController mStatusBarStateController;
+ private final FalsingManager mFalsingManager;
private boolean mQsExpanded;
private boolean mHeaderAnimating;
private boolean mStackScrollerOverscrolling;
@@ -133,7 +135,8 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
StatusBarStateController statusBarStateController, CommandQueue commandQueue,
QSDetailDisplayer qsDetailDisplayer, @Named(QS_PANEL) MediaHost qsMediaHost,
@Named(QUICK_QS_PANEL) MediaHost qqsMediaHost,
- QSFragmentComponent.Factory qsComponentFactory, FeatureFlags featureFlags) {
+ QSFragmentComponent.Factory qsComponentFactory, FeatureFlags featureFlags,
+ FalsingManager falsingManager) {
mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler;
mInjectionInflater = injectionInflater;
mCommandQueue = commandQueue;
@@ -144,6 +147,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
commandQueue.observe(getLifecycle(), this);
mHost = qsTileHost;
mFeatureFlags = featureFlags;
+ mFalsingManager = falsingManager;
mStatusBarStateController = statusBarStateController;
}
@@ -190,7 +194,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
mQSContainerImplController.init();
mContainer = mQSContainerImplController.getView();
- mQSDetail.setQsPanel(mQSPanelController, mHeader, mFooter);
+ mQSDetail.setQsPanel(mQSPanelController, mHeader, mFooter, mFalsingManager);
mQSAnimator = qsFragmentComponent.getQSAnimator();
mQSCustomizerController = qsFragmentComponent.getQSCustomizerController();
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 82b6c0c1805d..ab81ac1fd577 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
@@ -153,9 +153,25 @@ 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 = mController.getWalletClient().getServiceLabel();
+ CharSequence label = getServiceLabelSafe();
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/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
index a9723341e787..04437ea14bb3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
@@ -146,7 +146,7 @@ public class UserDetailView extends PseudoGridView {
@Override
public void onClick(View view) {
- if (mFalsingManager.isFalseTap(FalsingManager.MODERATE_PENALTY)) {
+ if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ImageTileSet.java b/packages/SystemUI/src/com/android/systemui/screenshot/ImageTileSet.java
index 51cc32ad39c1..356f67e7ea00 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ImageTileSet.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ImageTileSet.java
@@ -24,7 +24,6 @@ import android.graphics.Region;
import android.graphics.RenderNode;
import android.graphics.drawable.Drawable;
import android.os.Handler;
-import android.util.Log;
import androidx.annotation.UiThread;
@@ -140,7 +139,6 @@ class ImageTileSet {
* getHeight()).
*/
Bitmap toBitmap(Rect bounds) {
- Log.d(TAG, "exporting with bounds: " + bounds);
if (mTiles.isEmpty()) {
return null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
index af0141c81d58..0eaef72ae29b 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
@@ -63,7 +63,7 @@ import javax.inject.Inject;
* and bottom before saving/sharing/editing.
*/
public class LongScreenshotActivity extends Activity {
- private static final String TAG = "LongScreenshotActivity";
+ private static final String TAG = LogConfig.logTag(LongScreenshotActivity.class);
public static final String EXTRA_CAPTURE_RESPONSE = "capture-response";
private static final String KEY_SAVED_IMAGE_PATH = "saved-image-path";
@@ -80,7 +80,6 @@ public class LongScreenshotActivity extends Activity {
private View mSave;
private View mEdit;
private View mShare;
- private View mDelete;
private CropView mCropView;
private MagnifierView mMagnifierView;
private ScrollCaptureResponse mScrollCaptureResponse;
@@ -113,7 +112,6 @@ public class LongScreenshotActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
- Log.d(TAG, "onCreate(savedInstanceState = " + savedInstanceState + ")");
super.onCreate(savedInstanceState);
setContentView(R.layout.long_screenshot);
@@ -121,24 +119,18 @@ public class LongScreenshotActivity extends Activity {
mSave = requireViewById(R.id.save);
mEdit = requireViewById(R.id.edit);
mShare = requireViewById(R.id.share);
- mDelete = requireViewById(R.id.delete);
mCropView = requireViewById(R.id.crop_view);
mMagnifierView = requireViewById(R.id.magnifier);
mCropView.setCropInteractionListener(mMagnifierView);
mTransitionView = requireViewById(R.id.transition);
mEnterTransitionView = requireViewById(R.id.enter_transition);
+ requireViewById(R.id.cancel).setOnClickListener(v -> finishAndRemoveTask());
+
mSave.setOnClickListener(this::onClicked);
mEdit.setOnClickListener(this::onClicked);
mShare.setOnClickListener(this::onClicked);
- // Only show the delete button if we have something to delete (should typically be the case)
- if (getIntent().getData() != null) {
- mDelete.setOnClickListener(this::onClicked);
- } else {
- mDelete.setVisibility(View.GONE);
- }
-
mPreview.addOnLayoutChangeListener(
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
updateImageDimensions());
@@ -161,9 +153,13 @@ public class LongScreenshotActivity extends Activity {
@Override
public void onStart() {
- Log.d(TAG, "onStart");
super.onStart();
+ if (mPreview.getDrawable() != null) {
+ // We already have an image, so no need to try to load again.
+ return;
+ }
+
if (mCacheLoadFuture != null) {
Log.d(TAG, "mCacheLoadFuture != null");
final ListenableFuture<ImageLoader.Result> future = mCacheLoadFuture;
@@ -194,7 +190,7 @@ public class LongScreenshotActivity extends Activity {
}
private void onLongScreenshotReceived(LongScreenshot longScreenshot) {
- Log.d(TAG, "onLongScreenshotReceived(longScreenshot=" + longScreenshot + ")");
+ Log.i(TAG, "Completed: " + longScreenshot);
mLongScreenshot = longScreenshot;
Drawable drawable = mLongScreenshot.getDrawable();
mPreview.setImageDrawable(drawable);
@@ -249,7 +245,6 @@ public class LongScreenshotActivity extends Activity {
}
private void onCachedImageLoaded(ImageLoader.Result imageResult) {
- Log.d(TAG, "onCachedImageLoaded(imageResult=" + imageResult + ")");
BitmapDrawable drawable = new BitmapDrawable(getResources(), imageResult.bitmap);
mPreview.setImageDrawable(drawable);
mPreview.setAlpha(1f);
@@ -274,7 +269,6 @@ public class LongScreenshotActivity extends Activity {
@Override
protected void onSaveInstanceState(Bundle outState) {
- Log.d(TAG, "onSaveInstanceState");
super.onSaveInstanceState(outState);
if (mSavedImagePath != null) {
outState.putString(KEY_SAVED_IMAGE_PATH, mSavedImagePath.getPath());
@@ -282,14 +276,7 @@ public class LongScreenshotActivity extends Activity {
}
@Override
- protected void onPause() {
- Log.d(TAG, "onPause");
- super.onPause();
- }
-
- @Override
protected void onStop() {
- Log.d(TAG, "onStop finishing=" + isFinishing());
super.onStop();
if (mTransitionStarted) {
finish();
@@ -311,24 +298,16 @@ public class LongScreenshotActivity extends Activity {
mCacheSaveFuture.cancel(true);
}
if (mSavedImagePath != null) {
- Log.d(TAG, "Deleting " + mSavedImagePath);
//noinspection ResultOfMethodCallIgnored
mSavedImagePath.delete();
mSavedImagePath = null;
}
}
- @Override
- protected void onDestroy() {
- Log.d(TAG, "onDestroy");
- super.onDestroy();
- }
-
private void setButtonsEnabled(boolean enabled) {
mSave.setEnabled(enabled);
mEdit.setEnabled(enabled);
mShare.setEnabled(enabled);
- mDelete.setEnabled(enabled);
}
private void doEdit(Uri uri) {
@@ -383,16 +362,10 @@ public class LongScreenshotActivity extends Activity {
} else if (id == R.id.share) {
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_SHARE);
startExport(PendingAction.SHARE);
- } else if (id == R.id.delete) {
- mBackgroundExecutor.execute(() -> {
- getContentResolver().delete(getIntent().getData(), null);
- finishAndRemoveTask();
- });
}
}
private void startExport(PendingAction action) {
- Log.d(TAG, "startExport(action = " + action + ")");
Drawable drawable = mPreview.getDrawable();
if (drawable == null) {
Log.e(TAG, "No drawable, skipping export!");
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 52b393f563b6..16872b08b9c8 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -264,7 +264,6 @@ public class ScreenshotController {
private Animator mScreenshotAnimation;
private RequestCallback mCurrentRequestCallback;
- private Uri mLatestUriSaved;
private final Handler mScreenshotHandler = new Handler(Looper.getMainLooper()) {
@Override
@@ -547,6 +546,7 @@ public class ScreenshotController {
mAccessibilityManager.sendAccessibilityEvent(event);
}
+
if (mScreenshotView.isAttachedToWindow()) {
// if we didn't already dismiss for another reason
if (!mScreenshotView.isDismissing()) {
@@ -563,7 +563,6 @@ public class ScreenshotController {
.getWindowInsets().getDisplayCutout());
mScreenBitmap = screenshot;
- mLatestUriSaved = null;
if (!isUserSetupComplete()) {
Log.w(TAG, "User setup not complete, displaying toast only");
@@ -701,7 +700,6 @@ public class ScreenshotController {
longScreenshot));
final Intent intent = new Intent(mContext, LongScreenshotActivity.class);
- intent.setData(mLatestUriSaved);
intent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
@@ -891,8 +889,6 @@ public class ScreenshotController {
resetTimeout();
- mLatestUriSaved = imageData.uri;
-
if (imageData.uri != null) {
mScreenshotHandler.post(() -> {
if (mScreenshotAnimation != null && mScreenshotAnimation.isRunning()) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java
index 4c1f6a19b96c..6dc68746e3ec 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java
@@ -43,7 +43,7 @@ import javax.inject.Inject;
* Interaction controller between the UI and ScrollCaptureClient.
*/
public class ScrollCaptureController {
- private static final String TAG = "ScrollCaptureController";
+ private static final String TAG = LogConfig.logTag(ScrollCaptureController.class);
private static final float MAX_PAGES_DEFAULT = 3f;
private static final String SETTING_KEY_MAX_PAGES = "screenshot.scroll_max_pages";
@@ -90,7 +90,9 @@ public class ScrollCaptureController {
/** Releases image resources from the screenshot. */
public void release() {
- Log.d(TAG, "LongScreenshot :: release()");
+ if (LogConfig.DEBUG_SCROLL) {
+ Log.d(TAG, "LongScreenshot :: release()");
+ }
mImageTileSet.clear();
mSession.release();
}
@@ -153,15 +155,11 @@ public class ScrollCaptureController {
* @return a future ImageTile set containing the result
*/
ListenableFuture<LongScreenshot> run(ScrollCaptureResponse response) {
- Log.d(TAG, "run: " + response);
return CallbackToFutureAdapter.getFuture(completer -> {
- Log.d(TAG, "getFuture(ImageTileSet) ");
mCaptureCompleter = completer;
mBgExecutor.execute(() -> {
- Log.d(TAG, "bgExecutor.execute");
float maxPages = Settings.Secure.getFloat(mContext.getContentResolver(),
SETTING_KEY_MAX_PAGES, MAX_PAGES_DEFAULT);
- Log.d(TAG, "client start, maxPages=" + maxPages);
mSessionFuture = mClient.start(response, maxPages);
mSessionFuture.addListener(this::onStartComplete, mContext.getMainExecutor());
});
@@ -172,21 +170,27 @@ public class ScrollCaptureController {
private void onStartComplete() {
try {
mSession = mSessionFuture.get();
- Log.d(TAG, "got session " + mSession);
+ if (LogConfig.DEBUG_SCROLL) {
+ Log.d(TAG, "got session " + mSession);
+ }
requestNextTile(0);
} catch (InterruptedException | ExecutionException e) {
// Failure to start, propagate to caller
- Log.d(TAG, "session start failed!");
+ Log.e(TAG, "session start failed!");
mCaptureCompleter.setException(e);
}
}
private void requestNextTile(int topPx) {
- Log.d(TAG, "requestNextTile: " + topPx);
+ if (LogConfig.DEBUG_SCROLL) {
+ Log.d(TAG, "requestNextTile: " + topPx);
+ }
mTileFuture = mSession.requestTile(topPx);
mTileFuture.addListener(() -> {
try {
- Log.d(TAG, "onCaptureResult");
+ if (LogConfig.DEBUG_SCROLL) {
+ Log.d(TAG, "onCaptureResult");
+ }
onCaptureResult(mTileFuture.get());
} catch (InterruptedException | ExecutionException e) {
Log.e(TAG, "requestTile failed!", e);
@@ -196,14 +200,18 @@ public class ScrollCaptureController {
}
private void onCaptureResult(CaptureResult result) {
- Log.d(TAG, "onCaptureResult: " + result + " scrolling " + (mScrollingUp ? "UP" : "DOWN")
- + " finish on boundary: " + mFinishOnBoundary);
+ if (LogConfig.DEBUG_SCROLL) {
+ Log.d(TAG, "onCaptureResult: " + result + " scrolling " + (mScrollingUp ? "UP" : "DOWN")
+ + " finish on boundary: " + mFinishOnBoundary);
+ }
boolean emptyResult = result.captured.height() == 0;
if (emptyResult) {
// Potentially reached a vertical boundary. Extend in the other direction.
if (mFinishOnBoundary) {
- Log.d(TAG, "Empty: finished!");
+ if (LogConfig.DEBUG_SCROLL) {
+ Log.d(TAG, "Empty: finished!");
+ }
finishCapture();
return;
} else {
@@ -212,13 +220,17 @@ public class ScrollCaptureController {
mImageTileSet.clear();
mFinishOnBoundary = true;
mScrollingUp = !mScrollingUp;
- Log.d(TAG, "Empty: cleared, switch direction to finish");
+ if (LogConfig.DEBUG_SCROLL) {
+ Log.d(TAG, "Empty: cleared, switch direction to finish");
+ }
}
} else {
// Got a non-empty result, but may already have enough bitmap data now
int expectedTiles = mImageTileSet.size() + 1;
if (expectedTiles >= mSession.getMaxTiles()) {
- Log.d(TAG, "Hit max tiles: finished");
+ if (LogConfig.DEBUG_SCROLL) {
+ Log.d(TAG, "Hit max tiles: finished");
+ }
// If we ever hit the max tiles, we've got enough bitmap data to finish
// (even if we weren't sure we'd finish on this pass).
finishCapture();
@@ -229,7 +241,9 @@ public class ScrollCaptureController {
// by IDEAL_PORTION_ABOVE.
if (mImageTileSet.getHeight() + result.captured.height()
>= mSession.getTargetHeight() * IDEAL_PORTION_ABOVE) {
- Log.d(TAG, "Hit ideal portion above: clear and switch direction");
+ if (LogConfig.DEBUG_SCROLL) {
+ Log.d(TAG, "Hit ideal portion above: clear and switch direction");
+ }
// We got enough above the start point, now see how far down it can go.
mImageTileSet.clear();
mScrollingUp = false;
@@ -241,20 +255,25 @@ public class ScrollCaptureController {
if (!emptyResult) {
mImageTileSet.addTile(new ImageTile(result.image, result.captured));
}
-
- Log.d(TAG, "bounds: " + mImageTileSet.getLeft() + "," + mImageTileSet.getTop()
- + " - " + mImageTileSet.getRight() + "," + mImageTileSet.getBottom()
- + " (" + mImageTileSet.getWidth() + "x" + mImageTileSet.getHeight() + ")");
+ if (LogConfig.DEBUG_SCROLL) {
+ Log.d(TAG, "bounds: " + mImageTileSet.getLeft() + "," + mImageTileSet.getTop()
+ + " - " + mImageTileSet.getRight() + "," + mImageTileSet.getBottom()
+ + " (" + mImageTileSet.getWidth() + "x" + mImageTileSet.getHeight() + ")");
+ }
Rect gapBounds = mImageTileSet.getGaps();
if (!gapBounds.isEmpty()) {
- Log.d(TAG, "Found gaps in tileset: " + gapBounds + ", requesting " + gapBounds.top);
+ if (LogConfig.DEBUG_SCROLL) {
+ Log.d(TAG, "Found gaps in tileset: " + gapBounds + ", requesting " + gapBounds.top);
+ }
requestNextTile(gapBounds.top);
return;
}
if (mImageTileSet.getHeight() >= mSession.getTargetHeight()) {
- Log.d(TAG, "Target height reached.");
+ if (LogConfig.DEBUG_SCROLL) {
+ Log.d(TAG, "Target height reached.");
+ }
finishCapture();
return;
}
@@ -275,10 +294,14 @@ public class ScrollCaptureController {
}
private void finishCapture() {
- Log.d(TAG, "finishCapture()");
+ if (LogConfig.DEBUG_SCROLL) {
+ Log.d(TAG, "finishCapture()");
+ }
mEndFuture = mSession.end();
mEndFuture.addListener(() -> {
- Log.d(TAG, "endCapture completed");
+ if (LogConfig.DEBUG_SCROLL) {
+ Log.d(TAG, "endCapture completed");
+ }
// Provide result to caller and complete the top-level future
// Caller is responsible for releasing this resource (ImageReader/HardwareBuffers)
mCaptureCompleter.set(new LongScreenshot(mSession, mImageTileSet));
diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
index 24775344240a..f0fb5ebf9e1d 100644
--- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
@@ -17,6 +17,7 @@
package com.android.systemui.sensorprivacy
import android.content.DialogInterface
+import android.content.Intent
import android.content.Intent.EXTRA_PACKAGE_NAME
import android.content.pm.PackageManager
import android.content.res.Resources
@@ -38,6 +39,10 @@ import com.android.systemui.statusbar.phone.KeyguardDismissUtil
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController
import com.android.systemui.statusbar.policy.KeyguardStateController
import javax.inject.Inject
+import com.android.internal.util.FrameworkStatsLog.PRIVACY_TOGGLE_DIALOG_INTERACTION
+import com.android.internal.util.FrameworkStatsLog.PRIVACY_TOGGLE_DIALOG_INTERACTION__ACTION__ENABLE
+import com.android.internal.util.FrameworkStatsLog.PRIVACY_TOGGLE_DIALOG_INTERACTION__ACTION__CANCEL
+import com.android.internal.util.FrameworkStatsLog.write
/**
* Dialog to be shown on top of apps that are attempting to use a sensor (e.g. microphone) which is
@@ -174,7 +179,7 @@ class SensorUseStartedActivity @Inject constructor(
override fun onStart() {
super.onStart()
- sensorPrivacyController.suppressSensorPrivacyReminders(sensorUsePackageName, true)
+ setSuppressed(true)
unsuppressImmediately = false
}
@@ -185,16 +190,25 @@ class SensorUseStartedActivity @Inject constructor(
keyguardDismissUtil.executeWhenUnlocked({
bgHandler.postDelayed({
disableSensorPrivacy()
+ write(PRIVACY_TOGGLE_DIALOG_INTERACTION,
+ PRIVACY_TOGGLE_DIALOG_INTERACTION__ACTION__ENABLE,
+ sensorUsePackageName)
}, UNLOCK_DELAY_MILLIS)
false
}, false, true)
} else {
disableSensorPrivacy()
+ write(PRIVACY_TOGGLE_DIALOG_INTERACTION,
+ PRIVACY_TOGGLE_DIALOG_INTERACTION__ACTION__ENABLE,
+ sensorUsePackageName)
}
}
BUTTON_NEGATIVE -> {
unsuppressImmediately = false
+ write(PRIVACY_TOGGLE_DIALOG_INTERACTION,
+ PRIVACY_TOGGLE_DIALOG_INTERACTION__ACTION__CANCEL,
+ sensorUsePackageName)
}
}
@@ -205,12 +219,10 @@ class SensorUseStartedActivity @Inject constructor(
super.onStop()
if (unsuppressImmediately) {
- sensorPrivacyController
- .suppressSensorPrivacyReminders(sensorUsePackageName, false)
+ setSuppressed(false)
} else {
bgHandler.postDelayed({
- sensorPrivacyController
- .suppressSensorPrivacyReminders(sensorUsePackageName, false)
+ setSuppressed(false)
}, SUPPRESS_REMINDERS_REMOVAL_DELAY_MILLIS)
}
}
@@ -224,6 +236,11 @@ class SensorUseStartedActivity @Inject constructor(
// do not allow backing out
}
+ override fun onNewIntent(intent: Intent?) {
+ setIntent(intent)
+ recreate()
+ }
+
private fun disableSensorPrivacy() {
if (sensor == ALL_SENSORS) {
sensorPrivacyController.setSensorBlocked(DIALOG, MICROPHONE, false)
@@ -234,4 +251,16 @@ class SensorUseStartedActivity @Inject constructor(
unsuppressImmediately = true
setResult(RESULT_OK)
}
+
+ private fun setSuppressed(suppressed: Boolean) {
+ if (sensor == ALL_SENSORS) {
+ sensorPrivacyController
+ .suppressSensorPrivacyReminders(MICROPHONE, suppressed)
+ sensorPrivacyController
+ .suppressSensorPrivacyReminders(CAMERA, suppressed)
+ } else {
+ sensorPrivacyController
+ .suppressSensorPrivacyReminders(sensor, suppressed)
+ }
+ }
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index baac2549055f..cd5cce4f3ee7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -367,6 +367,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
&& !mHostLayoutController.isViewAffectedBySwipe(anv)
&& !isUnlockedHeadsUp
&& !isHunGoingToShade
+ && !anv.isAboveShelf()
&& !mAmbientState.isPulsing()
&& !mAmbientState.isDozing();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index a00d01427ebc..5302188ccb31 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -416,10 +416,12 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi
return mIcon.icon;
}
- private Drawable getIcon(StatusBarIcon icon) {
- Context notifContext = mNotification != null ?
- mNotification.getPackageContext(getContext()) : getContext();
- return getIcon(getContext(), notifContext, icon);
+ Drawable getIcon(StatusBarIcon icon) {
+ Context notifContext = getContext();
+ if (mNotification != null) {
+ notifContext = mNotification.getPackageContext(getContext());
+ }
+ return getIcon(getContext(), notifContext != null ? notifContext : getContext(), icon);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index a32b7e3b2836..6964838e7e41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -70,6 +70,7 @@ import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback;
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager;
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -93,6 +94,10 @@ public interface NotificationsModule {
StackScrollAlgorithm.SectionProvider bindSectionProvider(
NotificationSectionsManager impl);
+ @Binds
+ StackScrollAlgorithm.BypassController bindBypassController(
+ KeyguardBypassController impl);
+
/** Provides an instance of {@link NotificationEntryManager} */
@SysUISingleton
@Provides
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
index 222735aeb35a..4c9c2f95b35c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
@@ -47,10 +47,6 @@ public class NotificationCustomViewWrapper extends NotificationViewWrapper {
public void onContentUpdated(ExpandableNotificationRow row) {
super.onContentUpdated(row);
- // Custom views will most likely use just white or black as their text color.
- // We need to scan through and replace these colors by Material NEXT colors.
- ensureThemeOnChildren(mView);
-
// Let's invert the notification colors when we're in night mode and
// the notification background isn't colorized.
if (needsInversion(mBackgroundColor, mView)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java
index d21ae13a1e01..8c6fa023d92b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java
@@ -62,10 +62,6 @@ public class NotificationDecoratedCustomViewWrapper extends NotificationTemplate
public void onContentUpdated(ExpandableNotificationRow row) {
mWrappedView = getWrappedCustomView(mView);
- // Custom views will most likely use just white or black as their text color.
- // We need to scan through and replace these colors by Material NEXT colors.
- ensureThemeOnChildren(mWrappedView);
-
if (needsInversion(resolveBackgroundColor(), mWrappedView)) {
invertViewLuminosity(mWrappedView);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index 74abd38ec398..76301917b458 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -30,7 +30,6 @@ import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.Pair;
-import android.view.ContextThemeWrapper;
import android.view.NotificationHeaderView;
import android.view.View;
import android.view.ViewGroup;
@@ -41,7 +40,6 @@ import com.android.internal.graphics.ColorUtils;
import com.android.internal.util.ContrastColorUtil;
import com.android.internal.widget.CachingIconView;
import com.android.settingslib.Utils;
-import com.android.systemui.R;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.TransformableView;
import com.android.systemui.statusbar.notification.TransformState;
@@ -58,11 +56,6 @@ public abstract class NotificationViewWrapper implements TransformableView {
private final Rect mTmpRect = new Rect();
protected int mBackgroundColor = 0;
- private int mMaterialTextColorPrimary;
- private int mMaterialTextColorSecondary;
- private int mThemedTextColorPrimary;
- private int mThemedTextColorSecondary;
- private boolean mAdjustTheme;
public static NotificationViewWrapper wrap(Context ctx, View v, ExpandableNotificationRow row) {
if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) {
@@ -98,8 +91,6 @@ public abstract class NotificationViewWrapper implements TransformableView {
mView = view;
mRow = row;
onReinflated();
- mAdjustTheme = ctx.getResources().getBoolean(
- R.bool.config_adjustThemeOnNotificationCustomViews);
}
/**
@@ -124,22 +115,6 @@ public abstract class NotificationViewWrapper implements TransformableView {
mBackgroundColor = backgroundColor;
mView.setBackground(new ColorDrawable(Color.TRANSPARENT));
}
-
- Context materialTitleContext = new ContextThemeWrapper(mView.getContext(),
- com.android.internal.R.style.TextAppearance_Material_Notification_Title);
- mMaterialTextColorPrimary = Utils.getColorAttr(materialTitleContext,
- com.android.internal.R.attr.textColor).getDefaultColor();
- Context materialContext = new ContextThemeWrapper(mView.getContext(),
- com.android.internal.R.style.TextAppearance_Material_Notification);
- mMaterialTextColorSecondary = Utils.getColorAttr(materialContext,
- com.android.internal.R.attr.textColor).getDefaultColor();
-
- Context themedContext = new ContextThemeWrapper(mView.getContext(),
- com.android.internal.R.style.Theme_DeviceDefault_DayNight);
- mThemedTextColorPrimary = Utils.getColorAttr(themedContext,
- com.android.internal.R.attr.textColorPrimary).getDefaultColor();
- mThemedTextColorSecondary = Utils.getColorAttr(themedContext,
- com.android.internal.R.attr.textColorSecondary).getDefaultColor();
}
protected boolean needsInversion(int defaultBackgroundColor, View view) {
@@ -217,39 +192,6 @@ public abstract class NotificationViewWrapper implements TransformableView {
return false;
}
- protected void ensureThemeOnChildren(View rootView) {
- if (!mAdjustTheme || mView == null || rootView == null) {
- return;
- }
-
- // Notifications with custom backgrounds should not be adjusted
- if (mBackgroundColor != Color.TRANSPARENT
- || getBackgroundColor(mView) != Color.TRANSPARENT
- || getBackgroundColor(rootView) != Color.TRANSPARENT) {
- return;
- }
-
- // Now let's check if there's unprotected text somewhere, and apply the theme if we find it.
- processTextColorRecursive(rootView);
- }
-
- private void processTextColorRecursive(View view) {
- if (view instanceof TextView) {
- TextView textView = (TextView) view;
- int foreground = textView.getCurrentTextColor();
- if (foreground == mMaterialTextColorPrimary) {
- textView.setTextColor(mThemedTextColorPrimary);
- } else if (foreground == mMaterialTextColorSecondary) {
- textView.setTextColor(mThemedTextColorSecondary);
- }
- } else if (view instanceof ViewGroup) {
- ViewGroup viewGroup = (ViewGroup) view;
- for (int i = 0; i < viewGroup.getChildCount(); i++) {
- processTextColorRecursive(viewGroup.getChildAt(i));
- }
- }
- }
-
protected int getBackgroundColor(View view) {
if (view == null) {
return Color.TRANSPARENT;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
index 197920f7be19..9846b28ba5f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -29,6 +29,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
+import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.BypassController;
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.SectionProvider;
import javax.inject.Inject;
@@ -43,6 +44,7 @@ public class AmbientState {
private static final boolean NOTIFICATIONS_HAVE_SHADOWS = false;
private final SectionProvider mSectionProvider;
+ private final BypassController mBypassController;
private int mScrollY;
private boolean mDimmed;
private ActivatableNotificationView mActivatedChild;
@@ -152,14 +154,25 @@ public class AmbientState {
return mStackHeight;
}
+ /**
+ * @return Height of notifications panel, with the animation from pulseHeight accounted for.
+ */
+ // TODO(b/192348384): move this logic to getStackHeight, and remove this and getInnerHeight
+ public float getPulseStackHeight() {
+ float pulseHeight = Math.min(mPulseHeight, mStackHeight);
+ return MathUtils.lerp(mStackHeight, pulseHeight, mDozeAmount);
+ }
+
/** Tracks the state from AlertingNotificationManager#hasNotifications() */
private boolean mHasAlertEntries;
@Inject
public AmbientState(
Context context,
- @NonNull SectionProvider sectionProvider) {
+ @NonNull SectionProvider sectionProvider,
+ @NonNull BypassController bypassController) {
mSectionProvider = sectionProvider;
+ mBypassController = bypassController;
reload(context);
}
@@ -297,6 +310,13 @@ public class AmbientState {
}
}
+ /**
+ * Is bypass currently enabled?
+ */
+ public boolean isBypassEnabled() {
+ return mBypassController.isBypassEnabled();
+ }
+
public float getOverScrollAmount(boolean top) {
return top ? mOverScrollTopAmount : mOverScrollBottomAmount;
}
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 3fc8b8d9aef1..f460a132d65c 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
@@ -148,8 +148,22 @@ public class StackScrollAlgorithm {
AmbientState ambientState) {
NotificationShelf shelf = ambientState.getShelf();
- if (shelf != null) {
- shelf.updateState(algorithmState, ambientState);
+ if (shelf == null) {
+ return;
+ }
+
+ 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.
+ final float shelfTop = shelf.getViewState().yTranslation;
+
+ for (ExpandableView view : algorithmState.visibleChildren) {
+ final float viewTop = view.getViewState().yTranslation;
+
+ if (viewTop >= shelfTop) {
+ view.getViewState().hidden = true;
+ }
}
}
@@ -411,8 +425,7 @@ public class StackScrollAlgorithm {
} else {
if (view != ambientState.getTrackedHeadsUpRow()) {
if (ambientState.isExpansionChanging()) {
- // Show all views. Views below the shelf will later be clipped (essentially
- // hidden) in NotificationShelf.
+ // We later update shelf state, then hide views below the shelf.
viewState.hidden = false;
viewState.inShelf = algorithmState.firstViewInShelf != null
&& i >= algorithmState.visibleChildren.indexOf(
@@ -421,10 +434,20 @@ public class StackScrollAlgorithm {
// When pulsing (incoming notification on AOD), innerHeight is 0; clamp all
// to shelf start, thereby hiding all notifications (except the first one, which
// we later unhide in updatePulsingState)
- final int stackBottom =
- !ambientState.isShadeExpanded() || ambientState.isDozing()
- ? ambientState.getInnerHeight()
- : (int) ambientState.getStackHeight();
+ // TODO(b/192348384): merge InnerHeight with StackHeight
+ final int stackBottom;
+ if (ambientState.isBypassEnabled()) {
+ // We want to use the stackHeight when pulse expanding, since the animation
+ // isn't currently optimized if the pulseHeight is continuously changing
+ // Let's improve this when we're merging the heights above
+ stackBottom = ambientState.isPulseExpanding()
+ ? (int) ambientState.getStackHeight()
+ : ambientState.getInnerHeight();
+ } else {
+ stackBottom = !ambientState.isShadeExpanded() || ambientState.isDozing()
+ ? ambientState.getInnerHeight()
+ : (int) ambientState.getPulseStackHeight();
+ }
final int shelfStart =
stackBottom - ambientState.getShelf().getIntrinsicHeight();
viewState.yTranslation = Math.min(viewState.yTranslation, shelfStart);
@@ -742,4 +765,14 @@ public class StackScrollAlgorithm {
*/
boolean beginsSection(@NonNull View view, @Nullable View previous);
}
+
+ /**
+ * Interface for telling the StackScrollAlgorithm information about the bypass state
+ */
+ public interface BypassController {
+ /**
+ * True if bypass is enabled. Note that this is always false if face auth is not enabled.
+ */
+ boolean isBypassEnabled();
+ }
}
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 917c79fc6de5..6d5c53609f81 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -39,6 +39,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.KeyguardViewController;
import com.android.systemui.Dumpable;
+import com.android.systemui.biometrics.AuthController;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
@@ -165,6 +166,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
private BiometricModeListener mBiometricModeListener;
private final MetricsLogger mMetricsLogger;
+ private final AuthController mAuthController;
private static final class PendingAuthenticated {
public final int userId;
@@ -254,7 +256,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
PowerManager powerManager,
NotificationMediaManager notificationMediaManager,
WakefulnessLifecycle wakefulnessLifecycle,
- ScreenLifecycle screenLifecycle) {
+ ScreenLifecycle screenLifecycle,
+ AuthController authController) {
mContext = context;
mPowerManager = powerManager;
mShadeController = shadeController;
@@ -275,6 +278,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
mKeyguardBypassController = keyguardBypassController;
mKeyguardBypassController.setUnlockController(this);
mMetricsLogger = metricsLogger;
+ mAuthController = authController;
dumpManager.registerDumpable(getClass().getName(), this);
}
@@ -596,7 +600,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
return MODE_DISMISS_BOUNCER;
}
} else if (unlockingAllowed) {
- return bypass ? MODE_UNLOCK_FADING : MODE_NONE;
+ return bypass || mAuthController.isUdfpsFingerDown()
+ ? MODE_UNLOCK_FADING : MODE_NONE;
} else {
return bypass ? MODE_SHOW_BOUNCER : MODE_NONE;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 077500f7bfb9..f6c475690c1d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -75,6 +75,7 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.EmergencyCarrierArea;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.settingslib.Utils;
import com.android.systemui.ActivityIntentHelper;
import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -463,6 +464,10 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
if (tileIcon != null) {
mWalletButton.setImageDrawable(tileIcon);
}
+ mWalletButton.getDrawable().setTint(
+ Utils.getColorAttr(
+ mContext,
+ com.android.internal.R.attr.textColorPrimary).getDefaultColor());
mWalletButton.setVisibility(VISIBLE);
mWalletButton.setOnClickListener(this::onWalletClick);
mIndicationArea.setPadding(mIndicationPadding, 0, mIndicationPadding, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index d6ea4a828395..8c0dfc5f7ab4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -87,7 +87,7 @@ public class KeyguardBouncer {
private final Runnable mResetRunnable = ()-> {
if (mKeyguardViewController != null) {
mKeyguardViewController.resetSecurityContainer();
- for (KeyguardResetCallback callback : mResetCallbacks) {
+ for (KeyguardResetCallback callback : new ArrayList<>(mResetCallbacks)) {
callback.onKeyguardReset();
}
}
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 c9d08427c8ca..2cb0a3a28901 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
@@ -28,6 +28,7 @@ import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.tuner.TunerService
import java.io.FileDescriptor
@@ -35,7 +36,7 @@ import java.io.PrintWriter
import javax.inject.Inject
@SysUISingleton
-open class KeyguardBypassController : Dumpable {
+open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassController {
private val mKeyguardStateController: KeyguardStateController
private val statusBarStateController: StatusBarStateController
@@ -67,6 +68,9 @@ open class KeyguardBypassController : Dumpable {
lateinit var unlockController: BiometricUnlockController
var isPulseExpanding = false
+ /** delegates to [bypassEnabled] but conforms to [StackScrollAlgorithm.BypassController] */
+ override fun isBypassEnabled() = bypassEnabled
+
/**
* If face unlock dismisses the lock screen or keeps user on keyguard for the current user.
*/
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 c89f698f2656..fb3790cf4599 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -115,6 +115,7 @@ import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.qs.QSDetailDisplayer;
+import com.android.systemui.screenrecord.RecordingController;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.FeatureFlags;
@@ -329,6 +330,7 @@ public class NotificationPanelViewController extends PanelViewController {
private final int mMaxKeyguardNotifications;
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
private final TapAgainViewController mTapAgainViewController;
+ private final RecordingController mRecordingController;
private boolean mShouldUseSplitNotificationShade;
// Current max allowed keyguard notifications determined by measuring the panel
private int mMaxAllowedKeyguardNotifications;
@@ -716,6 +718,7 @@ public class NotificationPanelViewController extends PanelViewController {
FragmentService fragmentService,
ContentResolver contentResolver,
QuickAccessWalletController quickAccessWalletController,
+ RecordingController recordingController,
@Main Executor uiExecutor,
SecureSettings secureSettings,
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
@@ -762,6 +765,7 @@ public class NotificationPanelViewController extends PanelViewController {
mView.setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
setPanelAlpha(255, false /* animate */);
mCommandQueue = commandQueue;
+ mRecordingController = recordingController;
mDisplayId = displayId;
mPulseExpansionHandler = pulseExpansionHandler;
mDozeParameters = dozeParameters;
@@ -1361,7 +1365,8 @@ public class NotificationPanelViewController extends PanelViewController {
float lockIconPadding = 0;
if (mLockIconViewController.getTop() != 0) {
- lockIconPadding = mStatusBar.getDisplayHeight() - mLockIconViewController.getTop();
+ lockIconPadding = mStatusBar.getDisplayHeight() - mLockIconViewController.getTop()
+ + mResources.getDimensionPixelSize(R.dimen.min_lock_icon_padding);
}
float bottomPadding = Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding);
@@ -1581,7 +1586,10 @@ public class NotificationPanelViewController extends PanelViewController {
public void expandWithQsDetail(DetailAdapter qsDetailAdapter) {
traceQsJank(true /* startTracing */, false /* wasCancelled */);
flingSettings(0 /* velocity */, FLING_EXPAND);
- mQSDetailDisplayer.showDetailAdapter(qsDetailAdapter, 0, 0);
+ // When expanding with a panel, there's no meaningful touch point to correspond to. Set the
+ // origin to somewhere above the screen. This is used for animations.
+ int x = mQsFrame.getWidth() / 2;
+ mQSDetailDisplayer.showDetailAdapter(qsDetailAdapter, x, -getHeight());
if (mAccessibilityManager.isEnabled()) {
mView.setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
}
@@ -1636,7 +1644,6 @@ public class NotificationPanelViewController extends PanelViewController {
mView.getParent().requestDisallowInterceptTouchEvent(true);
}
if (mQsExpansionAnimator != null) {
- onQsExpansionStarted();
mInitialHeightOnTouch = mQsExpansionHeight;
mQsTracking = true;
traceQsJank(true /* startTracing */, false /* wasCancelled */);
@@ -2370,7 +2377,8 @@ public class NotificationPanelViewController extends PanelViewController {
// The padding on this area is large enough that we can use a cheaper clipping strategy
mKeyguardStatusAreaClipBounds.set(left, top, right, bottom);
clipStatusView = qsVisible;
- radius = (int) MathUtils.lerp(mScreenCornerRadius, mScrimCornerRadius,
+ float screenCornerRadius = mRecordingController.isRecording() ? 0 : mScreenCornerRadius;
+ radius = (int) MathUtils.lerp(screenCornerRadius, mScrimCornerRadius,
Math.min(top / (float) mScrimCornerRadius, 1f));
statusBarClipTop = top - mKeyguardStatusBar.getTop();
}
@@ -3638,6 +3646,8 @@ 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/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
index 022faf78b946..5e105bb64350 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
@@ -55,16 +55,18 @@ import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.google.android.collect.Lists;
-
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
+import java.util.stream.Collectors;
import javax.inject.Inject;
@@ -100,7 +102,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
private ForcePluginOpenListener mForcePluginOpenListener;
private Consumer<Integer> mScrimsVisibilityListener;
private final ArrayList<WeakReference<StatusBarWindowCallback>>
- mCallbacks = Lists.newArrayList();
+ mCallbacks = new ArrayList<>();
private final SysuiColorExtractor mColorExtractor;
private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
@@ -464,13 +466,15 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
@Override
public void notifyStateChangedCallbacks() {
- for (int i = 0; i < mCallbacks.size(); i++) {
- StatusBarWindowCallback cb = mCallbacks.get(i).get();
- if (cb != null) {
- cb.onStateChanged(mCurrentState.mKeyguardShowing,
- mCurrentState.mKeyguardOccluded,
- mCurrentState.mBouncerShowing);
- }
+ // Copy callbacks to separate ArrayList to avoid concurrent modification
+ List<StatusBarWindowCallback> activeCallbacks = mCallbacks.stream()
+ .map(Reference::get)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ for (StatusBarWindowCallback cb : activeCallbacks) {
+ cb.onStateChanged(mCurrentState.mKeyguardShowing,
+ mCurrentState.mKeyguardOccluded,
+ mCurrentState.mBouncerShowing);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index dc45bf1d324e..234df9ef48f7 100755
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -109,7 +109,8 @@ public class PhoneStatusBarPolicy
private final String mSlotBluetooth;
private final String mSlotTty;
private final String mSlotZen;
- private final String mSlotVolume;
+ private final String mSlotMute;
+ private final String mSlotVibrate;
private final String mSlotAlarmClock;
private final String mSlotManagedProfile;
private final String mSlotRotate;
@@ -151,7 +152,8 @@ public class PhoneStatusBarPolicy
private final PrivacyLogger mPrivacyLogger;
private boolean mZenVisible;
- private boolean mVolumeVisible;
+ private boolean mVibrateVisible;
+ private boolean mMuteVisible;
private boolean mCurrentUserSetup;
private boolean mManagedProfileIconVisible = false;
@@ -209,7 +211,8 @@ public class PhoneStatusBarPolicy
mSlotBluetooth = resources.getString(com.android.internal.R.string.status_bar_bluetooth);
mSlotTty = resources.getString(com.android.internal.R.string.status_bar_tty);
mSlotZen = resources.getString(com.android.internal.R.string.status_bar_zen);
- mSlotVolume = resources.getString(com.android.internal.R.string.status_bar_volume);
+ mSlotMute = resources.getString(com.android.internal.R.string.status_bar_mute);
+ mSlotVibrate = resources.getString(com.android.internal.R.string.status_bar_volume);
mSlotAlarmClock = resources.getString(com.android.internal.R.string.status_bar_alarm_clock);
mSlotManagedProfile = resources.getString(
com.android.internal.R.string.status_bar_managed_profile);
@@ -266,9 +269,14 @@ public class PhoneStatusBarPolicy
mIconController.setIcon(mSlotZen, R.drawable.stat_sys_dnd, null);
mIconController.setIconVisibility(mSlotZen, false);
- // volume
- mIconController.setIcon(mSlotVolume, R.drawable.stat_sys_ringer_vibrate, null);
- mIconController.setIconVisibility(mSlotVolume, false);
+ // vibrate
+ mIconController.setIcon(mSlotVibrate, R.drawable.stat_sys_ringer_vibrate,
+ mResources.getString(R.string.accessibility_ringer_vibrate));
+ mIconController.setIconVisibility(mSlotVibrate, false);
+ // mute
+ mIconController.setIcon(mSlotMute, R.drawable.stat_sys_ringer_silent,
+ mResources.getString(R.string.accessibility_ringer_silent));
+ mIconController.setIconVisibility(mSlotMute, false);
updateVolumeZen();
// cast
@@ -369,9 +377,8 @@ public class PhoneStatusBarPolicy
int zenIconId = 0;
String zenDescription = null;
- boolean volumeVisible = false;
- int volumeIconId = 0;
- String volumeDescription = null;
+ boolean vibrateVisible = false;
+ boolean muteVisible = false;
int zen = mZenController.getZen();
if (DndTile.isVisible(mSharedPreferences) || DndTile.isCombinedIcon(mSharedPreferences)) {
@@ -393,13 +400,9 @@ public class PhoneStatusBarPolicy
mRingerModeTracker.getRingerModeInternal().getValue();
if (ringerModeInternal != null) {
if (ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE) {
- volumeVisible = true;
- volumeIconId = R.drawable.stat_sys_ringer_vibrate;
- volumeDescription = mResources.getString(R.string.accessibility_ringer_vibrate);
+ vibrateVisible = true;
} else if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) {
- volumeVisible = true;
- volumeIconId = R.drawable.stat_sys_ringer_silent;
- volumeDescription = mResources.getString(R.string.accessibility_ringer_silent);
+ muteVisible = true;
}
}
}
@@ -412,13 +415,16 @@ public class PhoneStatusBarPolicy
mZenVisible = zenVisible;
}
- if (volumeVisible) {
- mIconController.setIcon(mSlotVolume, volumeIconId, volumeDescription);
+ if (vibrateVisible != mVibrateVisible) {
+ mIconController.setIconVisibility(mSlotVibrate, vibrateVisible);
+ mVibrateVisible = vibrateVisible;
}
- if (volumeVisible != mVolumeVisible) {
- mIconController.setIconVisibility(mSlotVolume, volumeVisible);
- mVolumeVisible = volumeVisible;
+
+ if (muteVisible != mMuteVisible) {
+ mIconController.setIconVisibility(mSlotMute, muteVisible);
+ mMuteVisible = muteVisible;
}
+
updateAlarm();
}
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 8eb22c63bbcf..c68429a56225 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -247,6 +247,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.StartingSurface;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -685,9 +686,7 @@ public class StatusBar extends SystemUI implements DemoMode,
new FalsingManager.FalsingBeliefListener() {
@Override
public void onFalse() {
- // Hides quick settings.
- mNotificationPanelViewController.resetViews(true);
- // Hides bouncer and quick-quick settings.
+ // Hides quick settings, bouncer, and quick-quick settings.
mStatusBarKeyguardViewManager.reset(true);
}
};
@@ -705,6 +704,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private final Optional<BubblesManager> mBubblesManagerOptional;
private final Optional<Bubbles> mBubblesOptional;
private final Bubbles.BubbleExpandListener mBubbleExpandListener;
+ private final Optional<StartingSurface> mStartingSurfaceOptional;
private ActivityIntentHelper mActivityIntentHelper;
private NotificationStackScrollLayoutController mStackScrollerController;
@@ -804,7 +804,8 @@ public class StatusBar extends SystemUI implements DemoMode,
LockscreenShadeTransitionController lockscreenShadeTransitionController,
FeatureFlags featureFlags,
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
- UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) {
+ UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
+ Optional<StartingSurface> startingSurfaceOptional) {
super(context);
mNotificationsController = notificationsController;
mLightBarController = lightBarController;
@@ -891,6 +892,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
+ mStartingSurfaceOptional = startingSurfaceOptional;
lockscreenShadeTransitionController.setStatusbar(this);
mExpansionChangedListeners = new ArrayList<>();
@@ -1419,7 +1421,9 @@ public class StatusBar extends SystemUI implements DemoMode,
private void setUpPresenter() {
// Set up the initial notification state.
- mActivityLaunchAnimator = new ActivityLaunchAnimator(this, mContext);
+ mActivityLaunchAnimator = new ActivityLaunchAnimator(this,
+ mStartingSurfaceOptional.orElse(null),
+ mContext);
mNotificationAnimationProvider = new NotificationLaunchAnimatorControllerProvider(
mNotificationShadeWindowViewController,
mStackScrollerController.getNotificationListContainer(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 6f63b1780d68..8a7708aaa8c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -521,7 +521,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
@Override
public void reset(boolean hideBouncerWhenShowing) {
if (mShowing) {
- mNotificationPanelViewController.closeQs();
+ // Hide quick settings.
+ mNotificationPanelViewController.resetViews(/* animate= */ true);
+ // Hide bouncer and quick-quick settings.
if (mOccluded && !mDozing) {
mStatusBar.hideKeyguard();
if (hideBouncerWhenShowing || mBouncer.needsFullscreenBouncer()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 98b9cc9bc716..9a6dd38ffca5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -514,7 +514,8 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON
);
ActivityLaunchAnimator.Controller animationController =
- new StatusBarLaunchAnimatorController(viewController, mStatusBar,
+ viewController == null ? null
+ : new StatusBarLaunchAnimatorController(viewController, mStatusBar,
true /* isActivityIntent */);
mActivityLaunchAnimator.startIntentWithAnimation(animationController, animate,
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 2611ab5f7016..716d1dbc6462 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
@@ -109,6 +109,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.StartingSurface;
import java.util.Optional;
import java.util.concurrent.Executor;
@@ -218,7 +219,8 @@ public interface StatusBarPhoneModule {
LockscreenShadeTransitionController transitionController,
FeatureFlags featureFlags,
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
- UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) {
+ UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
+ Optional<StartingSurface> startingSurfaceOptional) {
return new StatusBar(
context,
notificationsController,
@@ -306,6 +308,7 @@ public interface StatusBarPhoneModule {
transitionController,
featureFlags,
keyguardUnlockAnimationController,
- unlockedScreenOffAnimationController);
+ unlockedScreenOffAnimationController,
+ startingSurfaceOptional);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index 081fe5a47626..a8097c4d74b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -41,6 +41,7 @@ import com.android.systemui.statusbar.notification.row.NotificationRowContentBin
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.HashSet;
/**
@@ -157,7 +158,7 @@ public abstract class HeadsUpManager extends AlertingNotificationManager {
NotificationPeekEvent.NOTIFICATION_PEEK, entry.getSbn().getUid(),
entry.getSbn().getPackageName(), entry.getSbn().getInstanceId());
}
- for (OnHeadsUpChangedListener listener : mListeners) {
+ for (OnHeadsUpChangedListener listener : new ArrayList<>(mListeners)) {
if (isPinned) {
listener.onHeadsUpPinned(entry);
} else {
@@ -177,7 +178,7 @@ public abstract class HeadsUpManager extends AlertingNotificationManager {
entry.setHeadsUp(true);
setEntryPinned((HeadsUpEntry) alertEntry, shouldHeadsUpBecomePinned(entry));
EventLogTags.writeSysuiHeadsUpStatus(entry.getKey(), 1 /* visible */);
- for (OnHeadsUpChangedListener listener : mListeners) {
+ for (OnHeadsUpChangedListener listener : new ArrayList<>(mListeners)) {
listener.onHeadsUpStateChanged(entry, true);
}
}
@@ -188,7 +189,7 @@ public abstract class HeadsUpManager extends AlertingNotificationManager {
entry.setHeadsUp(false);
setEntryPinned((HeadsUpEntry) alertEntry, false /* isPinned */);
EventLogTags.writeSysuiHeadsUpStatus(entry.getKey(), 0 /* visible */);
- for (OnHeadsUpChangedListener listener : mListeners) {
+ for (OnHeadsUpChangedListener listener : new ArrayList<>(mListeners)) {
listener.onHeadsUpStateChanged(entry, false);
}
}
@@ -206,7 +207,7 @@ public abstract class HeadsUpManager extends AlertingNotificationManager {
if (mHasPinnedNotification) {
MetricsLogger.count(mContext, "note_peek", 1);
}
- for (OnHeadsUpChangedListener listener : mListeners) {
+ for (OnHeadsUpChangedListener listener : new ArrayList<>(mListeners)) {
listener.onHeadsUpPinnedModeChanged(hasPinnedNotification);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java
index acfdda4cea49..e01b95e81da8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java
@@ -29,7 +29,7 @@ public interface IndividualSensorPrivacyController extends
void setSensorBlocked(@Source int source, @Sensor int sensor, boolean blocked);
- void suppressSensorPrivacyReminders(String packageName, boolean suppress);
+ void suppressSensorPrivacyReminders(int sensor, boolean suppress);
interface Callback {
void onSensorBlockedChanged(@Sensor int sensor, boolean blocked);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java
index 9807165f69d0..1d71301c7454 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java
@@ -68,8 +68,8 @@ public class IndividualSensorPrivacyControllerImpl implements IndividualSensorPr
}
@Override
- public void suppressSensorPrivacyReminders(String packageName, boolean suppress) {
- mSensorPrivacyManager.suppressSensorPrivacyReminders(packageName, suppress);
+ public void suppressSensorPrivacyReminders(int sensor, boolean suppress) {
+ mSensorPrivacyManager.suppressSensorPrivacyReminders(sensor, suppress);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
index 1f1817cd29f0..5e70d0dbc418 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
@@ -21,7 +21,7 @@ import android.content.res.Resources;
import android.database.DataSetObserver;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
-import android.os.UserManager;
+import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
@@ -76,7 +76,6 @@ public class KeyguardQsUserSwitchController extends ViewController<UserAvatarVie
private final KeyguardVisibilityHelper mKeyguardVisibilityHelper;
private final KeyguardUserDetailAdapter mUserDetailAdapter;
private NotificationPanelViewController mNotificationPanelViewController;
- private UserManager mUserManager;
UserSwitcherController.UserRecord mCurrentUser;
// State info for the user switch and keyguard
@@ -115,7 +114,6 @@ public class KeyguardQsUserSwitchController extends ViewController<UserAvatarVie
UserAvatarView view,
Context context,
@Main Resources resources,
- UserManager userManager,
ScreenLifecycle screenLifecycle,
UserSwitcherController userSwitcherController,
KeyguardStateController keyguardStateController,
@@ -129,7 +127,6 @@ public class KeyguardQsUserSwitchController extends ViewController<UserAvatarVie
if (DEBUG) Log.d(TAG, "New KeyguardQsUserSwitchController");
mContext = context;
mResources = resources;
- mUserManager = userManager;
mScreenLifecycle = screenLifecycle;
mUserSwitcherController = userSwitcherController;
mKeyguardStateController = keyguardStateController;
@@ -227,47 +224,39 @@ public class KeyguardQsUserSwitchController extends ViewController<UserAvatarVie
return;
}
- if (mCurrentUser == null) {
- mView.setVisibility(View.GONE);
- return;
- }
-
- mView.setVisibility(View.VISIBLE);
-
- String currentUserName = mCurrentUser.info.name;
String contentDescription = null;
-
- if (!TextUtils.isEmpty(currentUserName)) {
+ if (mCurrentUser != null && mCurrentUser.info != null && !TextUtils.isEmpty(
+ mCurrentUser.info.name)) {
+ // If we know the current user's name, have TalkBack to announce "Signed in as [user
+ // name]" when the icon is selected
+ contentDescription = mContext.getString(R.string.accessibility_quick_settings_user,
+ mCurrentUser.info.name);
+ } else {
+ // As a fallback, have TalkBack announce "Switch user"
contentDescription = mContext.getString(
- R.string.accessibility_quick_settings_user,
- currentUserName);
+ R.string.accessibility_multi_user_switch_switcher);
}
if (!TextUtils.equals(mView.getContentDescription(), contentDescription)) {
mView.setContentDescription(contentDescription);
}
- mView.setDrawableWithBadge(getCurrentUserIcon().mutate(), mCurrentUser.resolveId());
+ int userId = mCurrentUser != null ? mCurrentUser.resolveId() : UserHandle.USER_NULL;
+ mView.setDrawableWithBadge(getCurrentUserIcon().mutate(), userId);
}
Drawable getCurrentUserIcon() {
Drawable drawable;
- if (mCurrentUser.picture == null) {
- if (mCurrentUser.isCurrent && mCurrentUser.isGuest) {
+ if (mCurrentUser == null || mCurrentUser.picture == null) {
+ if (mCurrentUser != null && mCurrentUser.isGuest) {
drawable = mContext.getDrawable(R.drawable.ic_avatar_guest_user);
} else {
- drawable = mAdapter.getIconDrawable(mContext, mCurrentUser);
- }
- int iconColorRes;
- if (mCurrentUser.isSwitchToEnabled) {
- iconColorRes = R.color.kg_user_switcher_avatar_icon_color;
- } else {
- iconColorRes = R.color.kg_user_switcher_restricted_avatar_icon_color;
+ drawable = mContext.getDrawable(R.drawable.ic_avatar_user);
}
+ int iconColorRes = R.color.kg_user_switcher_avatar_icon_color;
drawable.setTint(mResources.getColor(iconColorRes, mContext.getTheme()));
} else {
- int avatarSize =
- (int) mResources.getDimension(R.dimen.kg_framed_avatar_size);
+ int avatarSize = (int) mResources.getDimension(R.dimen.kg_framed_avatar_size);
drawable = new CircleFramedDrawable(mCurrentUser.picture, avatarSize);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 740b52d332ce..9c96416361c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -705,7 +705,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
cb.setIsAirplaneMode(new IconState(mAirplaneMode,
TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext));
cb.setNoSims(mHasNoSubs, mSimDetected);
- if (mProviderModelBehavior) {
+ if (mProviderModelSetting) {
cb.setConnectivityStatus(mNoDefaultNetwork, !mInetCondition, mNoNetworksAvailable);
}
mWifiSignalController.notifyListeners(cb);
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 b18dfd2866c4..bbaf65a399a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -807,7 +807,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
}
private void onEditTextFocusChanged(RemoteEditText remoteEditText, boolean focused) {
- for (View.OnFocusChangeListener listener : mEditTextFocusChangeListeners) {
+ for (View.OnFocusChangeListener listener : new ArrayList<>(mEditTextFocusChangeListeners)) {
listener.onFocusChange(remoteEditText, focused);
}
}
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 e2b6895e7039..4e921a036b36 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -67,6 +67,7 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.qs.QSUserSwitcherEvent;
import com.android.systemui.qs.tiles.UserDetailView;
@@ -131,6 +132,7 @@ public class UserSwitcherController implements Dumpable {
private final Executor mUiBgExecutor;
private final boolean mGuestUserAutoCreated;
private final AtomicBoolean mGuestCreationScheduled;
+ private FalsingManager mFalsingManager;
@Inject
public UserSwitcherController(Context context,
@@ -139,6 +141,7 @@ public class UserSwitcherController implements Dumpable {
ActivityStarter activityStarter,
BroadcastDispatcher broadcastDispatcher,
UiEventLogger uiEventLogger,
+ FalsingManager falsingManager,
TelephonyListenerManager telephonyListenerManager,
IActivityTaskManager activityTaskManager,
UserDetailAdapter userDetailAdapter,
@@ -148,6 +151,7 @@ public class UserSwitcherController implements Dumpable {
mTelephonyListenerManager = telephonyListenerManager;
mActivityTaskManager = activityTaskManager;
mUiEventLogger = uiEventLogger;
+ mFalsingManager = falsingManager;
mGuestResumeSessionReceiver = new GuestResumeSessionReceiver(this, mUiEventLogger);
mUserDetailAdapter = userDetailAdapter;
mUiBgExecutor = uiBgExecutor;
@@ -1031,6 +1035,11 @@ public class UserSwitcherController implements Dumpable {
@Override
public void onClick(DialogInterface dialog, int which) {
+ int penalty = which == BUTTON_NEGATIVE ? FalsingManager.NO_PENALTY
+ : FalsingManager.HIGH_PENALTY;
+ if (mFalsingManager.isFalseTap(penalty)) {
+ return;
+ }
if (which == BUTTON_NEGATIVE) {
cancel();
} else {
@@ -1057,6 +1066,11 @@ public class UserSwitcherController implements Dumpable {
@Override
public void onClick(DialogInterface dialog, int which) {
+ int penalty = which == BUTTON_NEGATIVE ? FalsingManager.NO_PENALTY
+ : FalsingManager.MODERATE_PENALTY;
+ if (mFalsingManager.isFalseTap(penalty)) {
+ return;
+ }
if (which == BUTTON_NEGATIVE) {
cancel();
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index 11ddbd045cd4..81999b534046 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -450,19 +450,23 @@ public class ThemeOverlayController extends SystemUI implements Dumpable {
OverlayIdentifier systemPalette = categoryToPackage.get(OVERLAY_CATEGORY_SYSTEM_PALETTE);
if (mIsMonetEnabled && systemPalette != null && systemPalette.getPackageName() != null) {
try {
- int color = Integer.parseInt(systemPalette.getPackageName().toLowerCase(), 16);
+ String colorString = systemPalette.getPackageName().toLowerCase();
+ if (!colorString.startsWith("#")) {
+ colorString = "#" + colorString;
+ }
+ int color = Color.parseColor(colorString);
mNeutralOverlay = getOverlay(color, NEUTRAL);
mNeedsOverlayCreation = true;
categoryToPackage.remove(OVERLAY_CATEGORY_SYSTEM_PALETTE);
- } catch (NumberFormatException e) {
- Log.w(TAG, "Invalid color definition: " + systemPalette.getPackageName());
+ } catch (Exception e) {
+ // Color.parseColor doesn't catch any exceptions from the calls it makes
+ Log.w(TAG, "Invalid color definition: " + systemPalette.getPackageName(), e);
}
} else if (!mIsMonetEnabled && systemPalette != null) {
try {
// It's possible that we flipped the flag off and still have a @ColorInt in the
// setting. We need to sanitize the input, otherwise the overlay transaction will
// fail.
- Integer.parseInt(systemPalette.getPackageName().toLowerCase(), 16);
categoryToPackage.remove(OVERLAY_CATEGORY_SYSTEM_PALETTE);
} catch (NumberFormatException e) {
// This is a package name. All good, let's continue
@@ -473,12 +477,17 @@ public class ThemeOverlayController extends SystemUI implements Dumpable {
OverlayIdentifier accentPalette = categoryToPackage.get(OVERLAY_CATEGORY_ACCENT_COLOR);
if (mIsMonetEnabled && accentPalette != null && accentPalette.getPackageName() != null) {
try {
- int color = Integer.parseInt(accentPalette.getPackageName().toLowerCase(), 16);
+ String colorString = accentPalette.getPackageName().toLowerCase();
+ if (!colorString.startsWith("#")) {
+ colorString = "#" + colorString;
+ }
+ int color = Color.parseColor(colorString);
mSecondaryOverlay = getOverlay(color, ACCENT);
mNeedsOverlayCreation = true;
categoryToPackage.remove(OVERLAY_CATEGORY_ACCENT_COLOR);
- } catch (NumberFormatException e) {
- Log.w(TAG, "Invalid color definition: " + accentPalette.getPackageName());
+ } catch (Exception e) {
+ // Color.parseColor doesn't catch any exceptions from the calls it makes
+ Log.w(TAG, "Invalid color definition: " + accentPalette.getPackageName(), e);
}
} else if (!mIsMonetEnabled && accentPalette != null) {
try {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java b/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
index 361604c461b4..a40cf4f37cc3 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
@@ -101,7 +101,12 @@ abstract public class SafetyWarningDialog extends SystemUIDialog
@Override
public void onDismiss(DialogInterface unused) {
- mContext.unregisterReceiver(mReceiver);
+ try {
+ mContext.unregisterReceiver(mReceiver);
+ } catch (IllegalArgumentException e) {
+ // Don't crash if the receiver has already been unregistered.
+ e.printStackTrace();
+ }
cleanUp();
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 5de7846a820e..3320852ca1f4 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -1743,7 +1743,7 @@ public class VolumeDialogImpl implements VolumeDialog,
mContext, android.R.attr.colorBackgroundFloating);
final ColorStateList inverseTextTint = Utils.getColorAttr(
- mContext, com.android.internal.R.attr.textColorPrimaryInverse);
+ mContext, com.android.internal.R.attr.textColorOnAccent);
row.sliderProgressSolid.setTintList(colorTint);
if (row.sliderBgIcon != null) {