Merge changes from topic "b204127880_pipeline_backport_1" into sc-v2-dev
* changes:
New pipeline: Fix notification re-inflation on dark mode change.
Make FeatureFlagManager Dumpable
New Pipeline: Implement lifetime extension for guts
Add ListenerSet and use in places which currently copy-on-iterate.
Populate buckets to ensure correct corner rounds on notifications
Enabled x button for clearable silent Notif[s]
New pipeline: Section manager is old pipeline, so don't call it for the new.
Remove dismiss-rtl setters because dismiss is bidirectional
New pipeline: remove non-silent section headers
diff --git a/core/api/current.txt b/core/api/current.txt
index d47d6a2..1dd401d 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -30857,6 +30857,7 @@
field public static final int Q = 29; // 0x1d
field public static final int R = 30; // 0x1e
field public static final int S = 31; // 0x1f
+ field public static final int S_V2 = 32; // 0x20
}
public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index eb10f09..7c2b1b7 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -626,7 +626,7 @@
// If our stale view has been prepared to match active, and the new
// layout matches, try recycling it
- if (layoutId == mLayoutId && mView != null) {
+ if (remoteViews.canRecycleView(mView)) {
try {
mLastExecutionSignal = remoteViews.reapplyAsync(mContext,
mView,
diff --git a/core/java/android/hardware/biometrics/BiometricOverlayConstants.java b/core/java/android/hardware/biometrics/BiometricOverlayConstants.java
index 065ae64a..603b06d 100644
--- a/core/java/android/hardware/biometrics/BiometricOverlayConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricOverlayConstants.java
@@ -38,16 +38,13 @@
int REASON_AUTH_KEYGUARD = 4;
/** Non-specific usage (from FingerprintManager). */
int REASON_AUTH_OTHER = 5;
- /** Usage from Settings. */
- int REASON_AUTH_SETTINGS = 6;
@IntDef({REASON_UNKNOWN,
REASON_ENROLL_FIND_SENSOR,
REASON_ENROLL_ENROLLING,
REASON_AUTH_BP,
REASON_AUTH_KEYGUARD,
- REASON_AUTH_OTHER,
- REASON_AUTH_SETTINGS})
+ REASON_AUTH_OTHER})
@Retention(RetentionPolicy.SOURCE)
@interface ShowReason {}
}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 6bf394d..b7dd36e 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -1024,7 +1024,7 @@
* will also enable {@link StrictMode.ThreadPolicy.Builder#detectUnbufferedIo}.</li>
* <li>{@link android.provider.DocumentsContract}'s various methods will throw failure
* exceptions back to the caller instead of returning null.
- * <li>{@link View#hasFocusable View.hasFocusable} now includes auto-focusable views.</li>
+ * <li>{@link View#hasFocusable() View.hasFocusable} now includes auto-focusable views.</li>
* <li>{@link android.view.SurfaceView} will no longer always change the underlying
* Surface object when something about it changes; apps need to look at the current
* state of the object to determine which things they are interested in have changed.</li>
@@ -1130,6 +1130,15 @@
* S.
*/
public static final int S = 31;
+
+ /**
+ * S V2.
+ *
+ * Once more unto the breach, dear friends, once more.
+ *
+ */
+ public static final int S_V2 = 32;
+
}
/** The type of build, like "user" or "eng". */
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 0f309f1..2357d13 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -5795,7 +5795,7 @@
// across orientation change, and has the RemoteViews re-applied in the new orientation,
// we throw an exception, since the layouts may be completely unrelated.
if (hasMultipleLayouts()) {
- if ((Integer) v.getTag(R.id.widget_frame) != rvToApply.getLayoutId()) {
+ if (!rvToApply.canRecycleView(v)) {
throw new RuntimeException("Attempting to re-apply RemoteViews to a view that" +
" that does not share the same root layout id.");
}
diff --git a/libs/WindowManager/Shell/res/values-land/styles.xml b/libs/WindowManager/Shell/res/values-land/styles.xml
index 9eddac4..0ed9368 100644
--- a/libs/WindowManager/Shell/res/values-land/styles.xml
+++ b/libs/WindowManager/Shell/res/values-land/styles.xml
@@ -23,7 +23,7 @@
</style>
<style name="DockedDividerHandle">
- <item name="android:layout_gravity">center_vertical</item>
+ <item name="android:layout_gravity">center</item>
<item name="android:layout_width">48dp</item>
<item name="android:layout_height">96dp</item>
</style>
diff --git a/libs/WindowManager/Shell/res/values/styles.xml b/libs/WindowManager/Shell/res/values/styles.xml
index cb6d4de..7733201 100644
--- a/libs/WindowManager/Shell/res/values/styles.xml
+++ b/libs/WindowManager/Shell/res/values/styles.xml
@@ -43,7 +43,7 @@
</style>
<style name="DockedDividerHandle">
- <item name="android:layout_gravity">center_horizontal</item>
+ <item name="android:layout_gravity">center</item>
<item name="android:layout_width">96dp</item>
<item name="android:layout_height">48dp</item>
</style>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
index 6ea806b..4b125b1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
@@ -19,6 +19,8 @@
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Rect;
@@ -57,6 +59,7 @@
private final int mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
private SplitLayout mSplitLayout;
+ private SplitWindowManager mSplitWindowManager;
private SurfaceControlViewHost mViewHost;
private DividerHandleView mHandle;
private View mBackground;
@@ -67,6 +70,7 @@
private int mStartPos;
private GestureDetector mDoubleTapDetector;
private boolean mInteractive;
+ private boolean mSetTouchRegion = true;
/**
* Tracks divider bar visible bounds in screen-based coordination. Used to calculate with
@@ -93,6 +97,18 @@
}
};
+ private AnimatorListenerAdapter mAnimatorListener = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mSetTouchRegion = true;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mSetTouchRegion = true;
+ }
+ };
+
public DividerView(@NonNull Context context) {
super(context);
}
@@ -114,9 +130,11 @@
/** Sets up essential dependencies of the divider bar. */
public void setup(
SplitLayout layout,
+ SplitWindowManager splitWindowManager,
SurfaceControlViewHost viewHost,
InsetsState insetsState) {
mSplitLayout = layout;
+ mSplitWindowManager = splitWindowManager;
mViewHost = viewHost;
mDividerBounds.set(layout.getDividerBounds());
onInsetsChanged(insetsState, false /* animate */);
@@ -138,9 +156,11 @@
DIVIDER_HEIGHT_PROPERTY, mDividerBounds.height(), mTempRect.height());
animator.setInterpolator(InsetsController.RESIZE_INTERPOLATOR);
animator.setDuration(InsetsController.ANIMATION_DURATION_RESIZE);
+ animator.addListener(mAnimatorListener);
animator.start();
} else {
DIVIDER_HEIGHT_PROPERTY.set(this, mTempRect.height());
+ mSetTouchRegion = true;
}
mDividerBounds.set(mTempRect);
}
@@ -162,6 +182,17 @@
}
@Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ if (mSetTouchRegion) {
+ mTempRect.set(mHandle.getLeft(), mHandle.getTop(), mHandle.getRight(),
+ mHandle.getBottom());
+ mSplitWindowManager.setTouchRegion(mTempRect);
+ mSetTouchRegion = false;
+ }
+ }
+
+ @Override
public boolean onTouch(View v, MotionEvent event) {
if (mSplitLayout == null || !mInteractive) {
return false;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index a9ed64c..625bcee 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -40,8 +40,10 @@
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
+import android.view.Display;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
+import android.view.RoundedCorner;
import android.view.SurfaceControl;
import android.view.WindowInsets;
import android.view.WindowManager;
@@ -53,6 +55,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.internal.policy.DockedDividerUtils;
+import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.animation.Interpolators;
import com.android.wm.shell.common.DisplayImeController;
@@ -133,17 +136,32 @@
mDismissingEffectPolicy = new DismissingEffectPolicy(applyDismissingParallax);
final Resources resources = context.getResources();
- mDividerWindowWidth = resources.getDimensionPixelSize(
- com.android.internal.R.dimen.docked_stack_divider_thickness);
- mDividerInsets = resources.getDimensionPixelSize(
- com.android.internal.R.dimen.docked_stack_divider_insets);
- mDividerSize = mDividerWindowWidth - mDividerInsets * 2;
+ mDividerSize = resources.getDimensionPixelSize(R.dimen.split_divider_bar_width);
+ mDividerInsets = getDividerInsets(resources, context.getDisplay());
+ mDividerWindowWidth = mDividerSize + 2 * mDividerInsets;
mRootBounds.set(configuration.windowConfiguration.getBounds());
mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds);
resetDividerPosition();
}
+ private int getDividerInsets(Resources resources, Display display) {
+ final int dividerInset = resources.getDimensionPixelSize(
+ com.android.internal.R.dimen.docked_stack_divider_insets);
+
+ int radius = 0;
+ RoundedCorner corner = display.getRoundedCorner(RoundedCorner.POSITION_TOP_LEFT);
+ radius = corner != null ? Math.max(radius, corner.getRadius()) : radius;
+ corner = display.getRoundedCorner(RoundedCorner.POSITION_TOP_RIGHT);
+ radius = corner != null ? Math.max(radius, corner.getRadius()) : radius;
+ corner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT);
+ radius = corner != null ? Math.max(radius, corner.getRadius()) : radius;
+ corner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT);
+ radius = corner != null ? Math.max(radius, corner.getRadius()) : radius;
+
+ return Math.max(dividerInset, radius);
+ }
+
/** Gets bounds of the primary split. */
public Rect getBounds1() {
return new Rect(mBounds1);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
index 08754d3..4903f9d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
@@ -31,7 +31,6 @@
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Binder;
-import android.os.IBinder;
import android.view.IWindow;
import android.view.InsetsState;
import android.view.LayoutInflater;
@@ -41,6 +40,7 @@
import android.view.WindowManager;
import android.view.WindowlessWindowManager;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.wm.shell.R;
@@ -71,9 +71,10 @@
mWindowName = windowName;
}
- @Override
- public void setTouchRegion(IBinder window, Region region) {
- super.setTouchRegion(window, region);
+ void setTouchRegion(@NonNull Rect region) {
+ if (mViewHost != null) {
+ setTouchRegion(mViewHost.getWindowToken().asBinder(), new Region(region));
+ }
}
@Override
@@ -122,7 +123,7 @@
lp.setTitle(mWindowName);
lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
mViewHost.setView(mDividerView, lp);
- mDividerView.setup(splitLayout, mViewHost, insetsState);
+ mDividerView.setup(splitLayout, this, mViewHost, insetsState);
}
/**
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
index c07f0eb..c4be785 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
@@ -78,7 +78,7 @@
assertLayersEnd {
val dividerRegion = layer(APP_PAIR_SPLIT_DIVIDER_COMPONENT).visibleRegion.region
visibleRegion(primaryComponent)
- .coversExactly(getPrimaryRegion(dividerRegion, rotation))
+ .overlaps(getPrimaryRegion(dividerRegion, rotation))
}
}
@@ -89,7 +89,7 @@
assertLayersEnd {
val dividerRegion = layer(DOCKED_STACK_DIVIDER_COMPONENT).visibleRegion.region
visibleRegion(primaryComponent)
- .coversExactly(getPrimaryRegion(dividerRegion, rotation))
+ .overlaps(getPrimaryRegion(dividerRegion, rotation))
}
}
@@ -100,7 +100,7 @@
assertLayersEnd {
val dividerRegion = layer(APP_PAIR_SPLIT_DIVIDER_COMPONENT).visibleRegion.region
visibleRegion(secondaryComponent)
- .coversExactly(getSecondaryRegion(dividerRegion, rotation))
+ .overlaps(getSecondaryRegion(dividerRegion, rotation))
}
}
@@ -111,7 +111,7 @@
assertLayersEnd {
val dividerRegion = layer(DOCKED_STACK_DIVIDER_COMPONENT).visibleRegion.region
visibleRegion(secondaryComponent)
- .coversExactly(getSecondaryRegion(dividerRegion, rotation))
+ .overlaps(getSecondaryRegion(dividerRegion, rotation))
}
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
index c2b3608..669a054 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
@@ -21,11 +21,16 @@
import android.graphics.Color
import android.os.Looper
import android.util.Log
+import android.view.GhostView
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
-import android.view.ViewTreeObserver
+import android.view.ViewTreeObserver.OnPreDrawListener
+import android.view.WindowInsets
import android.view.WindowManager
+import android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
+import android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+import android.view.WindowManagerPolicyConstants
import android.widget.FrameLayout
private const val TAG = "DialogLaunchAnimator"
@@ -221,10 +226,12 @@
private var isDismissing = false
private var dismissRequested = false
- private var drawHostDialog = false
var ignoreNextCallToHide = false
var exitAnimationDisabled = false
+ private var isTouchSurfaceGhostDrawn = false
+ private var isOriginalDialogViewLaidOut = false
+
fun start() {
// Show the host (fullscreen) dialog, to which we will add the stolen dialog view.
hostDialog.show()
@@ -252,19 +259,76 @@
WindowManager.LayoutParams.MATCH_PARENT
)
- // Prevent the host dialog from drawing until the animation starts.
- hostDialogRoot.viewTreeObserver.addOnPreDrawListener(
- object : ViewTreeObserver.OnPreDrawListener {
- override fun onPreDraw(): Boolean {
- if (drawHostDialog) {
- hostDialogRoot.viewTreeObserver.removeOnPreDrawListener(this)
- return true
- }
+ // If we are using gesture navigation, then we can overlay the navigation/task bars with
+ // the host dialog.
+ val navigationMode = context.resources.getInteger(
+ com.android.internal.R.integer.config_navBarInteractionMode)
+ if (navigationMode == WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL) {
+ window.attributes.fitInsetsTypes = window.attributes.fitInsetsTypes and
+ WindowInsets.Type.navigationBars().inv()
+ window.addFlags(FLAG_LAYOUT_IN_SCREEN or FLAG_LAYOUT_INSET_DECOR)
+ window.setDecorFitsSystemWindows(false)
+ }
- return false
- }
+ // Disable the dim. We will enable it once we start the animation.
+ window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
+
+ // Add a temporary touch surface ghost as soon as the window is ready to draw. This
+ // temporary ghost will be drawn together with the touch surface, but in the host dialog
+ // window. Once it is drawn, we will make the touch surface invisible, and then start the
+ // animation. We do all this synchronization to avoid flicker that would occur if we made
+ // the touch surface invisible too early (before its ghost is drawn), leading to one or more
+ // frames with a hole instead of the touch surface (or its ghost).
+ hostDialogRoot.viewTreeObserver.addOnPreDrawListener(object : OnPreDrawListener {
+ override fun onPreDraw(): Boolean {
+ hostDialogRoot.viewTreeObserver.removeOnPreDrawListener(this)
+ addTemporaryTouchSurfaceGhost()
+ return true
}
- )
+ })
+ hostDialogRoot.invalidate()
+ }
+
+ private fun addTemporaryTouchSurfaceGhost() {
+ // Create a ghost of the touch surface (which will make the touch surface invisible) and add
+ // it to the host dialog. We will wait for this ghost to be drawn before starting the
+ // animation.
+ val ghost = GhostView.addGhost(touchSurface, hostDialogRoot)
+
+ // The ghost of the touch surface was just created, so the touch surface was made invisible.
+ // We make it visible again until the ghost is actually drawn.
+ touchSurface.visibility = View.VISIBLE
+
+ // Wait for the ghost to be drawn before continuing.
+ ghost.viewTreeObserver.addOnPreDrawListener(object : OnPreDrawListener {
+ override fun onPreDraw(): Boolean {
+ ghost.viewTreeObserver.removeOnPreDrawListener(this)
+ onTouchSurfaceGhostDrawn()
+ return true
+ }
+ })
+ ghost.invalidate()
+ }
+
+ private fun onTouchSurfaceGhostDrawn() {
+ // Make the touch surface invisible and make sure that it stays invisible as long as the
+ // dialog is shown or animating.
+ touchSurface.visibility = View.INVISIBLE
+ if (touchSurface is LaunchableView) {
+ touchSurface.setShouldBlockVisibilityChanges(true)
+ }
+
+ // Add a pre draw listener to (maybe) start the animation once the touch surface is
+ // actually invisible.
+ touchSurface.viewTreeObserver.addOnPreDrawListener(object : OnPreDrawListener {
+ override fun onPreDraw(): Boolean {
+ touchSurface.viewTreeObserver.removeOnPreDrawListener(this)
+ isTouchSurfaceGhostDrawn = true
+ maybeStartLaunchAnimation()
+ return true
+ }
+ })
+ touchSurface.invalidate()
}
/** Get the content view of [originalDialog] and pass it to [then]. */
@@ -276,7 +340,7 @@
?: throw IllegalStateException("Dialog does not have any android.R.id.content view")
androidContent.viewTreeObserver.addOnPreDrawListener(
- object : ViewTreeObserver.OnPreDrawListener {
+ object : OnPreDrawListener {
override fun onPreDraw(): Boolean {
if (androidContent.childCount == 1) {
androidContent.viewTreeObserver.removeOnPreDrawListener(this)
@@ -354,32 +418,47 @@
oldBottom: Int
) {
dialogView.removeOnLayoutChangeListener(this)
- startAnimation(
- isLaunching = true,
- onLaunchAnimationStart = { drawHostDialog = true },
- onLaunchAnimationEnd = {
- touchSurface.setTag(R.id.launch_animation_running, null)
- // We hide the touch surface when the dialog is showing. We will make this
- // view visible again when dismissing the dialog.
- // TODO(b/193634619): Provide an easy way for views to check if they should
- // be hidden because of a dialog launch so that they don't override this
- // visibility when updating/refreshing itself.
- touchSurface.visibility = View.INVISIBLE
-
- isLaunching = false
-
- // dismiss was called during the animation, dismiss again now to actually
- // dismiss.
- if (dismissRequested) {
- hostDialog.dismiss()
- }
- }
- )
+ isOriginalDialogViewLaidOut = true
+ maybeStartLaunchAnimation()
}
})
}
+ private fun maybeStartLaunchAnimation() {
+ if (!isTouchSurfaceGhostDrawn || !isOriginalDialogViewLaidOut) {
+ return
+ }
+
+ // Show the background dim.
+ hostDialog.window.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
+
+ startAnimation(
+ isLaunching = true,
+ onLaunchAnimationStart = {
+ // Remove the temporary ghost. Another ghost (that ghosts only the touch surface
+ // content, and not its background) will be added right after this and will be
+ // animated.
+ GhostView.removeGhost(touchSurface)
+ },
+ onLaunchAnimationEnd = {
+ touchSurface.setTag(R.id.launch_animation_running, null)
+
+ // We hide the touch surface when the dialog is showing. We will make this
+ // view visible again when dismissing the dialog.
+ touchSurface.visibility = View.INVISIBLE
+
+ isLaunching = false
+
+ // dismiss was called during the animation, dismiss again now to actually
+ // dismiss.
+ if (dismissRequested) {
+ hostDialog.dismiss()
+ }
+ }
+ )
+ }
+
private fun onHostDialogDismissed(actualDismiss: () -> Unit) {
if (Looper.myLooper() != Looper.getMainLooper()) {
context.mainExecutor.execute { onHostDialogDismissed(actualDismiss) }
@@ -417,6 +496,11 @@
if (!shouldAnimateDialogIntoView()) {
Log.i(TAG, "Skipping animation of dialog into the touch surface")
+ // Make sure we allow the touch surface to change its visibility again.
+ if (touchSurface is LaunchableView) {
+ touchSurface.setShouldBlockVisibilityChanges(false)
+ }
+
// If the view is invisible it's probably because of us, so we make it visible again.
if (touchSurface.visibility == View.INVISIBLE) {
touchSurface.visibility = View.VISIBLE
@@ -434,10 +518,33 @@
hostDialog.window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
},
onLaunchAnimationEnd = {
+ // Make sure we allow the touch surface to change its visibility again.
+ if (touchSurface is LaunchableView) {
+ touchSurface.setShouldBlockVisibilityChanges(false)
+ }
+
touchSurface.visibility = View.VISIBLE
originalDialogView!!.visibility = View.INVISIBLE
- dismissDialogs(true /* instantDismiss */)
- onDialogDismissed(this@DialogLaunchAnimation)
+
+ // The animated ghost was just removed. We create a temporary ghost that will be
+ // removed only once we draw the touch surface, to avoid flickering that would
+ // happen when removing the ghost too early (before the touch surface is drawn).
+ GhostView.addGhost(touchSurface, hostDialogRoot)
+
+ touchSurface.viewTreeObserver.addOnPreDrawListener(object : OnPreDrawListener {
+ override fun onPreDraw(): Boolean {
+ touchSurface.viewTreeObserver.removeOnPreDrawListener(this)
+
+ // Now that the touch surface was drawn, we can remove the temporary ghost
+ // and instantly dismiss the dialog.
+ GhostView.removeGhost(touchSurface)
+ dismissDialogs(true /* instantDismiss */)
+ onDialogDismissed(this@DialogLaunchAnimation)
+
+ return true
+ }
+ })
+ touchSurface.invalidate()
}
)
}
@@ -472,10 +579,13 @@
}
override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) {
+ // During launch, onLaunchAnimationStart will be used to remove the temporary touch
+ // surface ghost so it is important to call this before calling
+ // onLaunchAnimationStart on the controller (which will create its own ghost).
+ onLaunchAnimationStart()
+
startViewController.onLaunchAnimationStart(isExpandingFullyAbove)
endViewController.onLaunchAnimationStart(isExpandingFullyAbove)
-
- onLaunchAnimationStart()
}
override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) {
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
new file mode 100644
index 0000000..80a3eb8
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
@@ -0,0 +1,30 @@
+/*
+ * 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.animation
+
+/** A view that can expand/launch into an app or a dialog. */
+interface LaunchableView {
+ /**
+ * Set whether this view should block/prevent all visibility changes. This ensures that this
+ * view remains invisible during the launch animation given that it is ghosted and already drawn
+ * somewhere else.
+ *
+ * Note that when this is set to true, both the [normal][android.view.View.setVisibility] and
+ * [transition][android.view.View.setTransitionVisibility] visibility changes must be blocked.
+ */
+ fun setShouldBlockVisibilityChanges(block: Boolean)
+}
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/drawable/super_lock_icon.xml b/packages/SystemUI/res-keyguard/drawable/super_lock_icon.xml
index 7f0f68f..c58e2e3 100644
--- a/packages/SystemUI/res-keyguard/drawable/super_lock_icon.xml
+++ b/packages/SystemUI/res-keyguard/drawable/super_lock_icon.xml
@@ -37,7 +37,7 @@
android:id="@+id/locked_fp"
android:state_middle="true"
android:state_single="false"
- android:drawable="@drawable/ic_fingerprint" />
+ android:drawable="@drawable/ic_kg_fingerprint" />
<item
android:id="@+id/unlocked"
diff --git a/packages/SystemUI/res/drawable/ic_fingerprint.xml b/packages/SystemUI/res/drawable/ic_kg_fingerprint.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_fingerprint.xml
rename to packages/SystemUI/res/drawable/ic_kg_fingerprint.xml
diff --git a/packages/SystemUI/res/drawable/internet_dialog_background.xml b/packages/SystemUI/res/drawable/internet_dialog_background.xml
deleted file mode 100644
index 3ceb0f6..0000000
--- a/packages/SystemUI/res/drawable/internet_dialog_background.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 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.
- -->
-
-<inset xmlns:android="http://schemas.android.com/apk/res/android">
- <shape android:shape="rectangle">
- <corners android:radius="8dp" />
- <solid android:color="?android:attr/colorBackground" />
- </shape>
-</inset>
diff --git a/packages/SystemUI/res/drawable/internet_dialog_rounded_top_corner_background.xml b/packages/SystemUI/res/drawable/internet_dialog_rounded_top_corner_background.xml
deleted file mode 100644
index 14672ef..0000000
--- a/packages/SystemUI/res/drawable/internet_dialog_rounded_top_corner_background.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<inset xmlns:android="http://schemas.android.com/apk/res/android">
- <shape android:shape="rectangle">
- <corners
- android:topLeftRadius="@dimen/internet_dialog_corner_radius"
- android:topRightRadius="@dimen/internet_dialog_corner_radius"
- android:bottomLeftRadius="@dimen/internet_dialog_corner_radius"
- android:bottomRightRadius="@dimen/internet_dialog_corner_radius"/>
- <solid android:color="?android:attr/colorBackground" />
- </shape>
-</inset>
diff --git a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
index 79ac737..f4faa62 100644
--- a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
+++ b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
@@ -20,8 +20,7 @@
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/internet_connectivity_dialog"
android:layout_width="@dimen/large_dialog_width"
- android:layout_height="@dimen/internet_dialog_list_max_height"
- android:background="@drawable/internet_dialog_rounded_top_corner_background"
+ android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
diff --git a/packages/SystemUI/res/values-land/styles.xml b/packages/SystemUI/res/values-land/styles.xml
index 82cba58..f3d83645 100644
--- a/packages/SystemUI/res/values-land/styles.xml
+++ b/packages/SystemUI/res/values-land/styles.xml
@@ -25,12 +25,6 @@
<item name="android:layout_gravity">center_horizontal</item>
</style>
- <style name="DockedDividerHandle">
- <item name="android:layout_gravity">center_vertical</item>
- <item name="android:layout_width">48dp</item>
- <item name="android:layout_height">96dp</item>
- </style>
-
<style name="DockedDividerMinimizedShadow">
<item name="android:layout_width">8dp</item>
<item name="android:layout_height">match_parent</item>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 85f8f09..4e57861 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -105,5 +105,5 @@
<dimen name="qs_detail_margin_top">0dp</dimen>
<!-- The width of large/content heavy dialogs (e.g. Internet, Media output, etc) -->
- <dimen name="large_dialog_width">624dp</dimen>
+ <dimen name="large_dialog_width">504dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 7293f31..db6985d 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1602,7 +1602,6 @@
<!-- Internet panel related dimensions -->
<dimen name="internet_dialog_list_margin">12dp</dimen>
- <dimen name="internet_dialog_list_max_height">662dp</dimen>
<!-- The width of large/content heavy dialogs (e.g. Internet, Media output, etc) -->
<dimen name="large_dialog_width">@dimen/match_parent</dimen>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index ff299ea..9bdd572 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -956,10 +956,6 @@
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
- <style name="Theme.SystemUI.Dialog.Internet">
- <item name="android:windowBackground">@drawable/internet_dialog_background</item>
- </style>
-
<style name="MainSwitch.Settingslib" parent="@android:style/Theme.DeviceDefault">
<item name="android:switchMinWidth">@dimen/settingslib_min_switch_width</item>
</style>
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt
index e2a2d07..b7398d8 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt
@@ -22,7 +22,6 @@
import android.graphics.Rect
import android.hardware.biometrics.BiometricOverlayConstants
import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_KEYGUARD
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_SETTINGS
import android.hardware.display.DisplayManager
import android.hardware.fingerprint.FingerprintManager
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
@@ -182,7 +181,6 @@
@BiometricOverlayConstants.ShowReason
private fun Int.isReasonToShow(): Boolean = when (this) {
REASON_AUTH_KEYGUARD -> false
- REASON_AUTH_SETTINGS -> false
else -> true
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
index f32dad6..042a337 100644
--- a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
@@ -106,6 +106,7 @@
*/
@JvmStatic fun create(inflater: LayoutInflater, parent: ViewGroup): PlayerViewHolder {
val mediaView = inflater.inflate(R.layout.media_view, parent, false)
+ mediaView.setLayerType(View.LAYER_TYPE_HARDWARE, null)
// Because this media view (a TransitionLayout) is used to measure and layout the views
// in various states before being attached to its parent, we can't depend on the default
// LAYOUT_DIRECTION_INHERIT to correctly resolve the ltr direction.
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
index 6895ef1..26ce645 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
@@ -104,8 +104,6 @@
lp.setFitInsetsIgnoringVisibility(true);
window.setAttributes(lp);
window.setContentView(mDialogView);
- window.setLayout(mContext.getResources().getDimensionPixelSize(R.dimen.large_dialog_width),
- ViewGroup.LayoutParams.WRAP_CONTENT);
mHeaderTitle = mDialogView.requireViewById(R.id.header_title);
mHeaderSubtitle = mDialogView.requireViewById(R.id.header_subtitle);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java
index e3e2367..00124ac 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java
@@ -37,6 +37,8 @@
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
+import androidx.annotation.Keep;
+
import java.util.ArrayList;
import java.util.HashSet;
@@ -184,19 +186,27 @@
}
}
+ /** Gets the glow alpha, used by {@link android.animation.ObjectAnimator} via reflection. */
+ @Keep
public float getGlowAlpha() {
return mGlowAlpha;
}
+ /** Sets the glow alpha, used by {@link android.animation.ObjectAnimator} via reflection. */
+ @Keep
public void setGlowAlpha(float x) {
mGlowAlpha = x;
invalidateSelf();
}
+ /** Gets the glow scale, used by {@link android.animation.ObjectAnimator} via reflection. */
+ @Keep
public float getGlowScale() {
return mGlowScale;
}
+ /** Sets the glow scale, used by {@link android.animation.ObjectAnimator} via reflection. */
+ @Keep
public void setGlowScale(float x) {
mGlowScale = x;
invalidateSelf();
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt
index 9e8f6b8..23482677 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt
@@ -24,7 +24,6 @@
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.view.WindowInsets
import android.widget.ImageView
import android.widget.TextView
@@ -65,7 +64,6 @@
window?.apply {
attributes.fitInsetsTypes = attributes.fitInsetsTypes or WindowInsets.Type.statusBars()
attributes.receiveInsetsIgnoringZOrder = true
- setLayout(context.resources.getDimensionPixelSize(R.dimen.qs_panel_width), WRAP_CONTENT)
setGravity(Gravity.TOP or Gravity.CENTER_HORIZONTAL)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 2665f3a..71eb4a2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -41,7 +41,7 @@
import com.android.systemui.R;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSTile;
-import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -69,7 +69,7 @@
@Nullable
protected View mBrightnessView;
@Nullable
- protected BrightnessSlider mToggleSliderController;
+ protected BrightnessSliderController mToggleSliderController;
private final H mHandler = new H();
/** Whether or not the QS media player feature is enabled. */
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index 70892a7..6794d5b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -41,7 +41,7 @@
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.settings.brightness.BrightnessController;
import com.android.systemui.settings.brightness.BrightnessMirrorHandler;
-import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.tuner.TunerService;
@@ -63,7 +63,7 @@
private final FalsingManager mFalsingManager;
private final CommandQueue mCommandQueue;
private final BrightnessController mBrightnessController;
- private final BrightnessSlider mBrightnessSlider;
+ private final BrightnessSliderController mBrightnessSliderController;
private final BrightnessMirrorHandler mBrightnessMirrorHandler;
private boolean mGridContentVisible = true;
@@ -99,8 +99,8 @@
QSTileRevealController.Factory qsTileRevealControllerFactory,
DumpManager dumpManager, MetricsLogger metricsLogger, UiEventLogger uiEventLogger,
QSLogger qsLogger, BrightnessController.Factory brightnessControllerFactory,
- BrightnessSlider.Factory brightnessSliderFactory, FalsingManager falsingManager,
- CommandQueue commandQueue) {
+ BrightnessSliderController.Factory brightnessSliderFactory,
+ FalsingManager falsingManager, CommandQueue commandQueue) {
super(view, qstileHost, qsCustomizerController, usingMediaPlayer, mediaHost,
metricsLogger, uiEventLogger, qsLogger, dumpManager);
mQsSecurityFooter = qsSecurityFooter;
@@ -111,10 +111,10 @@
mCommandQueue = commandQueue;
mQsSecurityFooter.setHostEnvironment(qstileHost);
- mBrightnessSlider = brightnessSliderFactory.create(getContext(), mView);
- mView.setBrightnessView(mBrightnessSlider.getRootView());
+ mBrightnessSliderController = brightnessSliderFactory.create(getContext(), mView);
+ mView.setBrightnessView(mBrightnessSliderController.getRootView());
- mBrightnessController = brightnessControllerFactory.create(mBrightnessSlider);
+ mBrightnessController = brightnessControllerFactory.create(mBrightnessSliderController);
mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController);
}
@@ -125,7 +125,7 @@
mMediaHost.setShowsOnlyActiveMedia(false);
mMediaHost.init(MediaHierarchyManager.LOCATION_QS);
mQsCustomizerController.init();
- mBrightnessSlider.init();
+ mBrightnessSliderController.init();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt b/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt
index 14374ff..65889d7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt
@@ -18,7 +18,7 @@
import androidx.annotation.VisibleForTesting
import com.android.systemui.settings.brightness.BrightnessController
-import com.android.systemui.settings.brightness.BrightnessSlider
+import com.android.systemui.settings.brightness.BrightnessSliderController
import com.android.systemui.settings.brightness.MirroredBrightnessController
import com.android.systemui.statusbar.policy.BrightnessMirrorController
import javax.inject.Inject
@@ -33,10 +33,11 @@
@Inject constructor(
brightnessControllerFactory: BrightnessController.Factory,
- brightnessSliderFactory: BrightnessSlider.Factory,
+ brightnessSliderControllerFactory: BrightnessSliderController.Factory,
quickQSPanel: QuickQSPanel
) : this(brightnessControllerFactory = {
- val slider = brightnessSliderFactory.create(quickQSPanel.context, quickQSPanel)
+ val slider = brightnessSliderControllerFactory.create(quickQSPanel.context,
+ quickQSPanel)
slider.init()
quickQSPanel.setBrightnessView(slider.rootView)
brightnessControllerFactory.create(slider)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
index 36101c9..69be3326 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -42,6 +42,7 @@
import com.android.settingslib.Utils
import com.android.systemui.FontSizeUtils
import com.android.systemui.R
+import com.android.systemui.animation.LaunchableView
import com.android.systemui.plugins.qs.QSIconView
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.plugins.qs.QSTile.BooleanState
@@ -54,7 +55,7 @@
context: Context,
private val _icon: QSIconView,
private val collapsed: Boolean = false
-) : QSTileView(context), HeightOverrideable {
+) : QSTileView(context), HeightOverrideable, LaunchableView {
companion object {
private const val INVALID = -1
@@ -130,6 +131,8 @@
private var lastStateDescription: CharSequence? = null
private var tileState = false
private var lastState = INVALID
+ private var blockVisibilityChanges = false
+ private var lastVisibility = View.VISIBLE
private val locInScreen = IntArray(2)
@@ -319,6 +322,36 @@
return sideView
}
+ override fun setShouldBlockVisibilityChanges(block: Boolean) {
+ blockVisibilityChanges = block
+
+ if (block) {
+ lastVisibility = visibility
+ } else {
+ visibility = lastVisibility
+ }
+ }
+
+ override fun setVisibility(visibility: Int) {
+ if (blockVisibilityChanges) {
+ lastVisibility = visibility
+ return
+ }
+
+ super.setVisibility(visibility)
+ }
+
+ override fun setTransitionVisibility(visibility: Int) {
+ if (blockVisibilityChanges) {
+ // View.setTransitionVisibility just sets the visibility flag, so we don't have to save
+ // the transition visibility separately from the normal visibility.
+ lastVisibility = visibility
+ return
+ }
+
+ super.setTransitionVisibility(visibility)
+ }
+
// Accessibility
override fun onInitializeAccessibilityEvent(event: AccessibilityEvent) {
@@ -484,7 +517,7 @@
}
private fun setColor(color: Int) {
- colorBackgroundDrawable.setTint(color)
+ colorBackgroundDrawable.mutate().setTint(color)
paintColor = color
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
index 98d0a72..23b2a76 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
@@ -124,7 +124,7 @@
protected void handleClick(@Nullable View view) {
mHandler.post(() -> mInternetDialogFactory.create(true,
mAccessPointController.canConfigMobileData(),
- mAccessPointController.canConfigWifi()));
+ mAccessPointController.canConfigWifi(), view));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
index 58e8992..1dab263 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
@@ -15,14 +15,10 @@
*/
package com.android.systemui.qs.tiles.dialog;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
-
import static com.android.systemui.Prefs.Key.QS_HAS_TURNED_OFF_MOBILE_DATA;
import android.app.AlertDialog;
import android.content.Context;
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Network;
import android.net.NetworkCapabilities;
@@ -41,10 +37,7 @@
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
import android.view.Window;
-import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
@@ -87,7 +80,6 @@
private final Handler mHandler;
private final Executor mBackgroundExecutor;
- private final LinearLayoutManager mLayoutManager;
@VisibleForTesting
protected InternetAdapter mAdapter;
@@ -130,7 +122,6 @@
private Switch mWiFiToggle;
private FrameLayout mDoneLayout;
private Drawable mBackgroundOn;
- private int mListMaxHeight;
private int mDefaultDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private boolean mCanConfigMobileData;
@@ -149,20 +140,11 @@
mInternetDialogSubTitle.setText(getSubtitleText());
};
- private final ViewTreeObserver.OnGlobalLayoutListener mInternetListLayoutListener = () -> {
- // Set max height for list
- if (mInternetDialogLayout.getHeight() > mListMaxHeight) {
- ViewGroup.LayoutParams params = mInternetDialogLayout.getLayoutParams();
- params.height = mListMaxHeight;
- mInternetDialogLayout.setLayoutParams(params);
- }
- };
-
public InternetDialog(Context context, InternetDialogFactory internetDialogFactory,
InternetDialogController internetDialogController, boolean canConfigMobileData,
boolean canConfigWifi, boolean aboveStatusBar, UiEventLogger uiEventLogger,
@Main Handler handler, @Background Executor executor) {
- super(context, R.style.Theme_SystemUI_Dialog_Internet);
+ super(context);
if (DEBUG) {
Log.d(TAG, "Init InternetDialog");
}
@@ -178,14 +160,6 @@
mCanConfigMobileData = canConfigMobileData;
mCanConfigWifi = canConfigWifi;
- mLayoutManager = new LinearLayoutManager(mContext) {
- @Override
- public boolean canScrollVertically() {
- return false;
- }
- };
- mListMaxHeight = context.getResources().getDimensionPixelSize(
- R.dimen.internet_dialog_list_max_height);
mUiEventLogger = uiEventLogger;
mAdapter = new InternetAdapter(mInternetDialogController);
if (!aboveStatusBar) {
@@ -203,21 +177,9 @@
mDialogView = LayoutInflater.from(mContext).inflate(R.layout.internet_connectivity_dialog,
null);
final Window window = getWindow();
- final WindowManager.LayoutParams layoutParams = window.getAttributes();
- layoutParams.gravity = Gravity.BOTTOM;
- // Move down the dialog to overlay the navigation bar.
- layoutParams.setFitInsetsTypes(
- layoutParams.getFitInsetsTypes() & ~WindowInsets.Type.navigationBars());
- layoutParams.setFitInsetsSides(WindowInsets.Side.all());
- layoutParams.setFitInsetsIgnoringVisibility(true);
- window.setAttributes(layoutParams);
window.setContentView(mDialogView);
- //Only fix the width for large screen or tablet.
- window.setLayout(mContext.getResources().getDimensionPixelSize(
- R.dimen.large_dialog_width), ViewGroup.LayoutParams.WRAP_CONTENT);
+
window.setWindowAnimations(R.style.Animation_InternetDialog);
- window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
- window.addFlags(FLAG_LAYOUT_NO_LIMITS);
mInternetDialogLayout = mDialogView.requireViewById(R.id.internet_connectivity_dialog);
mInternetDialogTitle = mDialogView.requireViewById(R.id.internet_dialog_title);
@@ -244,14 +206,12 @@
mMobileDataToggle = mDialogView.requireViewById(R.id.mobile_toggle);
mWiFiToggle = mDialogView.requireViewById(R.id.wifi_toggle);
mBackgroundOn = mContext.getDrawable(R.drawable.settingslib_switch_bar_bg_on);
- mInternetDialogLayout.getViewTreeObserver().addOnGlobalLayoutListener(
- mInternetListLayoutListener);
mInternetDialogTitle.setText(getDialogTitleText());
mInternetDialogTitle.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
setOnClickListener();
mTurnWifiOnLayout.setBackground(null);
- mWifiRecyclerView.setLayoutManager(mLayoutManager);
+ mWifiRecyclerView.setLayoutManager(new LinearLayoutManager(mContext));
mWifiRecyclerView.setAdapter(mAdapter);
}
@@ -502,10 +462,6 @@
}
private void setProgressBarVisible(boolean visible) {
- if (mWifiManager.isWifiEnabled() && mAdapter.mHolderView != null
- && mAdapter.mHolderView.isAttachedToWindow()) {
- mIsProgressBarVisible = true;
- }
mIsProgressBarVisible = visible;
mProgressBar.setVisibility(mIsProgressBarVisible ? View.VISIBLE : View.GONE);
mDivider.setVisibility(mIsProgressBarVisible ? View.GONE : View.VISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index 40590a7..5673136 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -71,6 +71,7 @@
import com.android.settingslib.net.SignalStrengthUtil;
import com.android.settingslib.wifi.WifiUtils;
import com.android.systemui.R;
+import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
@@ -152,6 +153,7 @@
private ToastFactory mToastFactory;
private SignalDrawable mSignalDrawable;
private LocationController mLocationController;
+ private DialogLaunchAnimator mDialogLaunchAnimator;
@VisibleForTesting
static final float TOAST_PARAMS_HORIZONTAL_WEIGHT = 1.0f;
@@ -202,7 +204,8 @@
WindowManager windowManager, ToastFactory toastFactory,
@Background Handler workerHandler,
CarrierConfigTracker carrierConfigTracker,
- LocationController locationController) {
+ LocationController locationController,
+ DialogLaunchAnimator dialogLaunchAnimator) {
if (DEBUG) {
Log.d(TAG, "Init InternetDialogController");
}
@@ -231,6 +234,7 @@
mToastFactory = toastFactory;
mSignalDrawable = new SignalDrawable(mContext);
mLocationController = locationController;
+ mDialogLaunchAnimator = dialogLaunchAnimator;
}
void onStart(@NonNull InternetDialogCallback callback, boolean canConfigWifi) {
@@ -596,20 +600,32 @@
}
void launchNetworkSetting() {
+ // Dismissing a dialog into its touch surface and starting an activity at the same time
+ // looks bad, so let's make sure the dialog just fades out quickly.
+ mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
mCallback.dismissDialog();
+
mActivityStarter.postStartActivityDismissingKeyguard(getSettingsIntent(), 0);
}
void launchWifiNetworkDetailsSetting(String key) {
Intent intent = getWifiDetailsSettingsIntent(key);
if (intent != null) {
+ // Dismissing a dialog into its touch surface and starting an activity at the same time
+ // looks bad, so let's make sure the dialog just fades out quickly.
+ mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
mCallback.dismissDialog();
+
mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
}
}
void launchWifiScanningSetting() {
+ // Dismissing a dialog into its touch surface and starting an activity at the same time
+ // looks bad, so let's make sure the dialog just fades out quickly.
+ mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
mCallback.dismissDialog();
+
final Intent intent = new Intent(ACTION_WIFI_SCANNING_SETTINGS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
index ea5df17..93828b3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
@@ -18,9 +18,11 @@
import android.content.Context
import android.os.Handler
import android.util.Log
+import android.view.View
import com.android.internal.logging.UiEventLogger
+import com.android.systemui.animation.DialogLaunchAnimator
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import java.util.concurrent.Executor
import javax.inject.Inject
@@ -37,14 +39,20 @@
@Background private val executor: Executor,
private val internetDialogController: InternetDialogController,
private val context: Context,
- private val uiEventLogger: UiEventLogger
+ private val uiEventLogger: UiEventLogger,
+ private val dialogLaunchAnimator: DialogLaunchAnimator
) {
companion object {
var internetDialog: InternetDialog? = null
}
- /** Creates a [InternetDialog]. */
- fun create(aboveStatusBar: Boolean, canConfigMobileData: Boolean, canConfigWifi: Boolean) {
+ /** Creates a [InternetDialog]. The dialog will be animated from [view] if it is not null. */
+ fun create(
+ aboveStatusBar: Boolean,
+ canConfigMobileData: Boolean,
+ canConfigWifi: Boolean,
+ view: View?
+ ) {
if (internetDialog != null) {
if (DEBUG) {
Log.d(TAG, "InternetDialog is showing, do not create it twice.")
@@ -54,7 +62,11 @@
internetDialog = InternetDialog(context, this, internetDialogController,
canConfigMobileData, canConfigWifi, aboveStatusBar, uiEventLogger, handler,
executor)
- internetDialog?.show()
+ if (view != null) {
+ dialogLaunchAnimator.showFromView(internetDialog!!, view)
+ } else {
+ internetDialog?.show()
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/user/UserDialog.kt b/packages/SystemUI/src/com/android/systemui/qs/user/UserDialog.kt
index 01afa56..26d1bbd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/user/UserDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/user/UserDialog.kt
@@ -71,10 +71,6 @@
setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL)
attributes.fitInsetsTypes = attributes.fitInsetsTypes or WindowInsets.Type.statusBars()
attributes.receiveInsetsIgnoringZOrder = true
- setLayout(
- context.resources.getDimensionPixelSize(R.dimen.notification_panel_width),
- ViewGroup.LayoutParams.WRAP_CONTENT
- )
setGravity(Gravity.CENTER)
}
setContentView(R.layout.qs_user_dialog_content)
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
index acc6ee1..d7d1de0 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
@@ -51,8 +51,6 @@
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
-import java.util.ArrayList;
-
import javax.inject.Inject;
public class BrightnessController implements ToggleSlider.Listener, MirroredBrightnessController {
@@ -92,13 +90,9 @@
@Override
public void onDisplayChanged(int displayId) {
mBackgroundHandler.post(mUpdateSliderRunnable);
- notifyCallbacks();
}
};
- private ArrayList<BrightnessStateChangeCallback> mChangeCallbacks =
- new ArrayList<BrightnessStateChangeCallback>();
-
private volatile boolean mAutomatic; // Brightness adjusted automatically using ambient light.
private volatile boolean mIsVrModeEnabled;
private boolean mListening;
@@ -114,11 +108,6 @@
mControl.setMirrorControllerAndMirror(controller);
}
- public interface BrightnessStateChangeCallback {
- /** Indicates that some of the brightness settings have changed */
- void onBrightnessLevelChanged();
- }
-
/** ContentObserver to watch brightness */
private class BrightnessObserver extends ContentObserver {
@@ -139,7 +128,6 @@
mBackgroundHandler.post(mUpdateModeRunnable);
mBackgroundHandler.post(mUpdateSliderRunnable);
}
- notifyCallbacks();
}
public void startObserving() {
@@ -317,14 +305,6 @@
Context.VR_SERVICE));
}
- public void addStateChangedCallback(BrightnessStateChangeCallback cb) {
- mChangeCallbacks.add(cb);
- }
-
- public boolean removeStateChangedCallback(BrightnessStateChangeCallback cb) {
- return mChangeCallbacks.remove(cb);
- }
-
public void registerCallbacks() {
mBackgroundHandler.post(mStartListeningRunnable);
}
@@ -375,10 +355,6 @@
}
});
}
-
- for (BrightnessStateChangeCallback cb : mChangeCallbacks) {
- cb.onBrightnessLevelChanged();
- }
}
public void checkRestrictionAndSetEnabled() {
@@ -435,8 +411,12 @@
}
private void animateSliderTo(int target) {
- if (!mControlValueInitialized) {
+ if (!mControlValueInitialized || !mControl.isVisible()) {
// Don't animate the first value since its default state isn't meaningful to users.
+ // We also don't want to animate slider if it's not visible - especially important when
+ // two sliders are active at the same time in split shade (one in QS and one in QQS),
+ // as this negatively affects transition between them and they share mirror slider -
+ // animating it from two different sources causes janky motion
mControl.setValue(target);
mControlValueInitialized = true;
}
@@ -455,13 +435,6 @@
mSliderAnimator.start();
}
- private void notifyCallbacks() {
- final int size = mChangeCallbacks.size();
- for (int i = 0; i < size; i++) {
- mChangeCallbacks.get(i).onBrightnessLevelChanged();
- }
- }
-
/** Factory for creating a {@link BrightnessController}. */
public static class Factory {
private final Context mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
index 8fc831a..c9c1a9b 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
@@ -41,14 +41,14 @@
public class BrightnessDialog extends Activity {
private BrightnessController mBrightnessController;
- private final BrightnessSlider.Factory mToggleSliderFactory;
+ private final BrightnessSliderController.Factory mToggleSliderFactory;
private final BroadcastDispatcher mBroadcastDispatcher;
private final Handler mBackgroundHandler;
@Inject
public BrightnessDialog(
BroadcastDispatcher broadcastDispatcher,
- BrightnessSlider.Factory factory,
+ BrightnessSliderController.Factory factory,
@Background Handler bgHandler) {
mBroadcastDispatcher = broadcastDispatcher;
mToggleSliderFactory = factory;
@@ -77,7 +77,7 @@
// The brightness mirror container is INVISIBLE by default.
frame.setVisibility(View.VISIBLE);
- BrightnessSlider controller = mToggleSliderFactory.create(this, frame);
+ BrightnessSliderController controller = mToggleSliderFactory.create(this, frame);
controller.init();
frame.addView(controller.getRootView(), MATCH_PARENT, WRAP_CONTENT);
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
similarity index 89%
rename from packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
rename to packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
index b0e320a..6c8190a 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
@@ -44,7 +44,8 @@
*
* @see BrightnessMirrorController
*/
-public class BrightnessSlider extends ViewController<BrightnessSliderView> implements ToggleSlider {
+public class BrightnessSliderController extends ViewController<BrightnessSliderView> implements
+ ToggleSlider {
private Listener mListener;
private ToggleSlider mMirror;
@@ -69,7 +70,7 @@
}
};
- BrightnessSlider(
+ BrightnessSliderController(
BrightnessSliderView brightnessSliderView,
FalsingManager falsingManager) {
super(brightnessSliderView);
@@ -184,6 +185,15 @@
mView.setVisibility(View.VISIBLE);
}
+ @Override
+ public boolean isVisible() {
+ // this should be called rarely - once or twice per slider's value change, but not for
+ // every value change when user slides finger - only the final one.
+ // If view is not visible this call is quick (around 50 µs) as it sees parent is not visible
+ // otherwise it's slightly longer (70 µs) because there are more checks to be done
+ return mView.isVisibleToUser();
+ }
+
private final SeekBar.OnSeekBarChangeListener mSeekListener =
new SeekBar.OnSeekBarChangeListener() {
@Override
@@ -222,7 +232,7 @@
};
/**
- * Creates a {@link BrightnessSlider} with its associated view.
+ * Creates a {@link BrightnessSliderController} with its associated view.
*/
public static class Factory {
@@ -240,11 +250,11 @@
* @param viewRoot the {@link ViewGroup} that will contain the hierarchy. The inflated
* hierarchy will not be attached
*/
- public BrightnessSlider create(Context context, @Nullable ViewGroup viewRoot) {
+ public BrightnessSliderController create(Context context, @Nullable ViewGroup viewRoot) {
int layout = getLayout();
BrightnessSliderView root = (BrightnessSliderView) LayoutInflater.from(context)
.inflate(layout, viewRoot, false);
- return new BrightnessSlider(root, mFalsingManager);
+ return new BrightnessSliderController(root, mFalsingManager);
}
/** Get the layout to inflate based on what slider to use */
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
index 15aa2b7..0e037ad 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
@@ -60,6 +60,7 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
+ setLayerType(LAYER_TYPE_HARDWARE, null);
mSlider = requireViewById(R.id.slider);
mSlider.setAccessibilityLabel(getContentDescription().toString());
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java
index 5de22d4..648e33b 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java
@@ -38,4 +38,5 @@
void showView();
void hideView();
+ boolean isVisible();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
index 6da981b..cbb3aba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
@@ -28,7 +28,6 @@
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.os.SystemProperties;
-import android.os.Trace;
import android.text.format.DateFormat;
import android.util.FloatProperty;
import android.util.Log;
@@ -182,7 +181,6 @@
}
synchronized (mListeners) {
- Trace.beginSection(TAG + "#setState(" + StatusBarState.toShortString(state) + ")");
String tag = getClass().getSimpleName() + "#setState(" + state + ")";
DejankUtils.startDetectingBlockingIpcs(tag);
for (RankedListener rl : new ArrayList<>(mListeners)) {
@@ -200,7 +198,6 @@
rl.mListener.onStatePostChange();
}
DejankUtils.stopDetectingBlockingIpcs(tag);
- Trace.endSection();
}
return true;
@@ -265,14 +262,12 @@
mIsDozing = isDozing;
synchronized (mListeners) {
- Trace.beginSection(TAG + "#setDozing(" + isDozing + ")");
String tag = getClass().getSimpleName() + "#setIsDozing";
DejankUtils.startDetectingBlockingIpcs(tag);
for (RankedListener rl : new ArrayList<>(mListeners)) {
rl.mListener.onDozingChanged(isDozing);
}
DejankUtils.stopDetectingBlockingIpcs(tag);
- Trace.endSection();
}
return true;
@@ -338,14 +333,12 @@
mDozeAmount = dozeAmount;
float interpolatedAmount = mDozeInterpolator.getInterpolation(dozeAmount);
synchronized (mListeners) {
- Trace.beginSection(TAG + "#setDozeAmount");
String tag = getClass().getSimpleName() + "#setDozeAmount";
DejankUtils.startDetectingBlockingIpcs(tag);
for (RankedListener rl : new ArrayList<>(mListeners)) {
rl.mListener.onDozeAmountChanged(mDozeAmount, interpolatedAmount);
}
DejankUtils.stopDetectingBlockingIpcs(tag);
- Trace.endSection();
}
}
@@ -476,13 +469,11 @@
public void setPulsing(boolean pulsing) {
if (mPulsing != pulsing) {
mPulsing = pulsing;
- Trace.beginSection(TAG + "#setPulsing(" + pulsing + ")");
synchronized (mListeners) {
for (RankedListener rl : new ArrayList<>(mListeners)) {
rl.mListener.onPulsingChanged(pulsing);
}
}
- Trace.endSection();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
index f72178f..daae43f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
@@ -811,7 +811,8 @@
break;
case Settings.Panel.ACTION_INTERNET_CONNECTIVITY:
mMainHandler.post(() -> mInternetDialogFactory.create(true,
- mAccessPoints.canConfigMobileData(), mAccessPoints.canConfigWifi()));
+ mAccessPoints.canConfigMobileData(), mAccessPoints.canConfigWifi(),
+ null /* view */));
break;
default:
int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
index cf9daf6..4e5bc8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -34,7 +34,6 @@
import android.view.ViewGroup
import com.android.settingslib.Utils
import com.android.systemui.R
-import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.ActivityStarter
@@ -190,24 +189,19 @@
val ssView = plugin.getView(parent)
ssView.registerDataProvider(plugin)
- val animationController = ActivityLaunchAnimator.Controller.fromView(
- ssView as View,
- null /* cujType */
- )
-
ssView.setIntentStarter(object : BcSmartspaceDataPlugin.IntentStarter {
- override fun startIntent(v: View?, i: Intent?, showOnLockscreen: Boolean) {
+ override fun startIntent(view: View, intent: Intent, showOnLockscreen: Boolean) {
activityStarter.startActivity(
- i,
+ intent,
true, /* dismissShade */
- animationController,
+ null, /* launch animator - looks bad with the transparent smartspace bg */
showOnLockscreen
)
}
- override fun startPendingIntent(pi: PendingIntent?, showOnLockscreen: Boolean) {
+ override fun startPendingIntent(pi: PendingIntent, showOnLockscreen: Boolean) {
if (showOnLockscreen) {
- pi?.send()
+ pi.send()
} else {
activityStarter.startPendingIntentDismissingKeyguard(pi)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index e368aad..4f3bbdb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -195,12 +195,21 @@
1.0f /* panelExpansion */, 1.0f /* darkAmount */);
result.clockAlpha = getClockAlpha(y);
result.stackScrollerPadding = getStackScrollerPadding(y);
- result.stackScrollerPaddingExpanded = mBypassEnabled ? mUnlockedStackScrollerPadding
- : getClockY(1.0f, mDarkAmount) + mKeyguardStatusHeight;
+ result.stackScrollerPaddingExpanded = getStackScrollerPaddingExpanded();
result.clockX = (int) interpolate(0, burnInPreventionOffsetX(), mDarkAmount);
result.clockScale = interpolate(getBurnInScale(), 1.0f, 1.0f - mDarkAmount);
}
+ private int getStackScrollerPaddingExpanded() {
+ if (mBypassEnabled) {
+ return mUnlockedStackScrollerPadding;
+ } else if (mIsSplitShade) {
+ return getClockY(1.0f, mDarkAmount);
+ } else {
+ return getClockY(1.0f, mDarkAmount) + mKeyguardStatusHeight;
+ }
+ }
+
private int getStackScrollerPadding(int clockYPosition) {
if (mBypassEnabled) {
return (int) (mUnlockedStackScrollerPadding + mOverStretchAmount);
@@ -212,8 +221,13 @@
}
public float getMinStackScrollerPadding() {
- return mBypassEnabled ? mUnlockedStackScrollerPadding
- : mMinTopMargin + mKeyguardStatusHeight;
+ if (mBypassEnabled) {
+ return mUnlockedStackScrollerPadding;
+ } else if (mIsSplitShade) {
+ return mMinTopMargin;
+ } else {
+ return mMinTopMargin + mKeyguardStatusHeight;
+ }
}
private int getExpandedPreferredClockY() {
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 01188d3..4ad2af4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -174,7 +174,7 @@
import com.android.systemui.qs.QSPanelController;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.scrim.ScrimView;
-import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.AutoHideUiElement;
import com.android.systemui.statusbar.BackDropView;
@@ -543,7 +543,7 @@
private final NotificationViewHierarchyManager mViewHierarchyManager;
private final KeyguardViewMediator mKeyguardViewMediator;
protected final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
- private final BrightnessSlider.Factory mBrightnessSliderFactory;
+ private final BrightnessSliderController.Factory mBrightnessSliderFactory;
private final FeatureFlags mFeatureFlags;
private final UnfoldTransitionConfig mUnfoldTransitionConfig;
private final Lazy<UnfoldLightRevealOverlayAnimation> mUnfoldLightRevealOverlayAnimation;
@@ -784,7 +784,7 @@
Lazy<NotificationShadeDepthController> notificationShadeDepthControllerLazy,
StatusBarTouchableRegionManager statusBarTouchableRegionManager,
NotificationIconAreaController notificationIconAreaController,
- BrightnessSlider.Factory brightnessSliderFactory,
+ BrightnessSliderController.Factory brightnessSliderFactory,
UnfoldTransitionConfig unfoldTransitionConfig,
Lazy<UnfoldLightRevealOverlayAnimation> unfoldLightRevealOverlayAnimation,
Lazy<UnfoldTransitionWallpaperController> unfoldTransitionWallpaperController,
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 cd95cfd..cac66a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -907,7 +907,7 @@
@Override
public boolean bouncerIsOrWillBeShowing() {
- return mBouncer.isShowing() || mBouncer.getShowingSoon();
+ return isBouncerShowing() || mBouncer.getShowingSoon();
}
public boolean isFullscreenBouncer() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
index 9415d50..18aa689 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
@@ -22,7 +22,11 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.os.Bundle;
+import android.os.SystemProperties;
import android.os.UserHandle;
+import android.util.TypedValue;
+import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowInsets.Type;
import android.view.WindowManager;
@@ -45,6 +49,10 @@
* and dismisses itself when it receives the broadcast.
*/
public class SystemUIDialog extends AlertDialog implements ListenableDialog {
+ // TODO(b/203389579): Remove this once the dialog width on large screens has been agreed on.
+ private static final String FLAG_TABLET_DIALOG_WIDTH =
+ "persist.systemui.flag_tablet_dialog_width";
+
private final Context mContext;
private final DismissReceiver mDismissReceiver;
private final Set<DialogListener> mDialogListeners = new LinkedHashSet<>();
@@ -66,6 +74,41 @@
}
@Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Set the dialog window size.
+ getWindow().setLayout(getDialogWidth(), ViewGroup.LayoutParams.WRAP_CONTENT);
+ }
+
+ private int getDialogWidth() {
+ boolean isOnTablet =
+ mContext.getResources().getConfiguration().smallestScreenWidthDp >= 600;
+ if (!isOnTablet) {
+ return ViewGroup.LayoutParams.MATCH_PARENT;
+ }
+
+ int flagValue = SystemProperties.getInt(FLAG_TABLET_DIALOG_WIDTH, 0);
+ if (flagValue == -1) {
+ // The width of bottom sheets (624dp).
+ return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 624,
+ mContext.getResources().getDisplayMetrics()));
+ } else if (flagValue == -2) {
+ // The suggested small width for all dialogs (348dp)
+ return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 348,
+ mContext.getResources().getDisplayMetrics()));
+ } else if (flagValue > 0) {
+ // Any given width.
+ return Math.round(
+ TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, flagValue,
+ mContext.getResources().getDisplayMetrics()));
+ } else {
+ // By default we use the same width as the notification shade in portrait mode (504dp).
+ return mContext.getResources().getDimensionPixelSize(R.dimen.large_dialog_width);
+ }
+ }
+
+ @Override
protected void onStart() {
super.onStart();
mDismissReceiver.register();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
index e2332e9..cddde64 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
@@ -161,6 +161,8 @@
// Done going to sleep, reset this flag.
decidedToAnimateGoingToSleep = null
+ // We need to unset the listener. These are persistent for future animators
+ keyguardView.animate().setListener(null)
}
})
.start()
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 2681d5e..959c673 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
@@ -48,7 +48,7 @@
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.recents.ScreenPinningRequest;
-import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -222,7 +222,7 @@
Lazy<NotificationShadeDepthController> notificationShadeDepthController,
StatusBarTouchableRegionManager statusBarTouchableRegionManager,
NotificationIconAreaController notificationIconAreaController,
- BrightnessSlider.Factory brightnessSliderFactory,
+ BrightnessSliderController.Factory brightnessSliderFactory,
UnfoldTransitionConfig unfoldTransitionConfig,
Lazy<UnfoldLightRevealOverlayAnimation> unfoldLightRevealOverlayAnimation,
Lazy<NaturalRotationUnfoldProgressProvider> naturalRotationUnfoldProgressProvider,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
index 1e52511..5bd20ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
@@ -26,7 +26,7 @@
import android.widget.FrameLayout;
import com.android.systemui.R;
-import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
import com.android.systemui.settings.brightness.ToggleSlider;
import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
@@ -46,8 +46,8 @@
private final NotificationPanelViewController mNotificationPanel;
private final NotificationShadeDepthController mDepthController;
private final ArraySet<BrightnessMirrorListener> mBrightnessMirrorListeners = new ArraySet<>();
- private final BrightnessSlider.Factory mToggleSliderFactory;
- private BrightnessSlider mToggleSliderController;
+ private final BrightnessSliderController.Factory mToggleSliderFactory;
+ private BrightnessSliderController mToggleSliderController;
private final int[] mInt2Cache = new int[2];
private FrameLayout mBrightnessMirror;
private int mBrightnessMirrorBackgroundPadding;
@@ -56,7 +56,7 @@
public BrightnessMirrorController(NotificationShadeWindowView statusBarWindow,
NotificationPanelViewController notificationPanelViewController,
NotificationShadeDepthController notificationShadeDepthController,
- BrightnessSlider.Factory factory,
+ BrightnessSliderController.Factory factory,
@NonNull Consumer<Boolean> visibilityCallback) {
mStatusBarWindow = statusBarWindow;
mToggleSliderFactory = factory;
@@ -135,9 +135,10 @@
reinflate();
}
- private BrightnessSlider setMirrorLayout() {
+ private BrightnessSliderController setMirrorLayout() {
Context context = mBrightnessMirror.getContext();
- BrightnessSlider controller = mToggleSliderFactory.create(context, mBrightnessMirror);
+ BrightnessSliderController controller = mToggleSliderFactory.create(context,
+ mBrightnessMirror);
controller.init();
mBrightnessMirror.addView(controller.getRootView(), ViewGroup.LayoutParams.MATCH_PARENT,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt
index ca7d506..5fee7fb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt
@@ -18,7 +18,6 @@
import android.graphics.Rect
import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_KEYGUARD
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_SETTINGS
import android.hardware.biometrics.BiometricOverlayConstants.REASON_UNKNOWN
import android.hardware.biometrics.SensorProperties
import android.hardware.display.DisplayManager
@@ -183,16 +182,7 @@
@Test
fun testIgnoredForKeyguard() {
- testIgnoredFor(REASON_AUTH_KEYGUARD)
- }
-
- @Test
- fun testIgnoredForSettings() {
- testIgnoredFor(REASON_AUTH_SETTINGS)
- }
-
- private fun testIgnoredFor(reason: Int) {
- overlayController.show(SENSOR_ID, reason)
+ overlayController.show(SENSOR_ID, REASON_AUTH_KEYGUARD)
executor.runAllReady()
verify(windowManager, never()).addView(any(), any())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
index 06a4ae0..3242adb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
@@ -42,7 +42,7 @@
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.settings.brightness.BrightnessController;
-import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
import com.android.systemui.settings.brightness.ToggleSlider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.tuner.TunerService;
@@ -88,9 +88,9 @@
@Mock
private BrightnessController mBrightnessController;
@Mock
- private BrightnessSlider.Factory mToggleSliderViewControllerFactory;
+ private BrightnessSliderController.Factory mToggleSliderViewControllerFactory;
@Mock
- private BrightnessSlider mBrightnessSlider;
+ private BrightnessSliderController mBrightnessSliderController;
@Mock
QSTileImpl mQSTile;
@Mock
@@ -120,7 +120,7 @@
when(mQSTileHost.getTiles()).thenReturn(Collections.singleton(mQSTile));
when(mQSTileHost.createTileView(any(), eq(mQSTile), anyBoolean())).thenReturn(mQSTileView);
when(mToggleSliderViewControllerFactory.create(any(), any()))
- .thenReturn(mBrightnessSlider);
+ .thenReturn(mBrightnessSliderController);
when(mBrightnessControllerFactory.create(any(ToggleSlider.class)))
.thenReturn(mBrightnessController);
when(mQSTileRevealControllerFactory.create(any(), any()))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
index 5cea763..eb03b5f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
@@ -45,6 +45,7 @@
import com.android.settingslib.wifi.WifiUtils;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -138,6 +139,8 @@
private CarrierConfigTracker mCarrierConfigTracker;
@Mock
private LocationController mLocationController;
+ @Mock
+ private DialogLaunchAnimator mDialogLaunchAnimator;
private TestableResources mTestableResources;
private MockInternetDialogController mInternetDialogController;
@@ -174,7 +177,7 @@
mock(ConnectivityManager.class), mHandler, mExecutor, mBroadcastDispatcher,
mock(KeyguardUpdateMonitor.class), mGlobalSettings, mKeyguardStateController,
mWindowManager, mToastFactory, mWorkerHandler, mCarrierConfigTracker,
- mLocationController);
+ mLocationController, mDialogLaunchAnimator);
mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor,
mInternetDialogController.mOnSubscriptionsChangedListener);
mInternetDialogController.onStart(mInternetDialogCallback, true);
@@ -654,12 +657,13 @@
KeyguardStateController keyguardStateController, WindowManager windowManager,
ToastFactory toastFactory, Handler workerHandler,
CarrierConfigTracker carrierConfigTracker,
- LocationController locationController) {
+ LocationController locationController,
+ DialogLaunchAnimator dialogLaunchAnimator) {
super(context, uiEventLogger, starter, accessPointController, subscriptionManager,
telephonyManager, wifiManager, connectivityManager, handler, mainExecutor,
broadcastDispatcher, keyguardUpdateMonitor, globalSettings,
keyguardStateController, windowManager, toastFactory, workerHandler,
- carrierConfigTracker, locationController);
+ carrierConfigTracker, locationController, dialogLaunchAnimator);
mGlobalSettings = globalSettings;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
similarity index 96%
rename from packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
index bceb928..2b39354 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
@@ -45,7 +45,7 @@
@SmallTest
@RunWith(AndroidTestingRunner::class)
-class BrightnessSliderTest : SysuiTestCase() {
+class BrightnessSliderControllerTest : SysuiTestCase() {
@Mock
private lateinit var brightnessSliderView: BrightnessSliderView
@@ -66,7 +66,7 @@
private lateinit var seekBar: SeekBar
private var mFalsingManager: FalsingManagerFake = FalsingManagerFake()
- private lateinit var mController: BrightnessSlider
+ private lateinit var mController: BrightnessSliderController
@Before
fun setUp() {
@@ -75,7 +75,7 @@
whenever(mirrorController.toggleSlider).thenReturn(mirror)
whenever(motionEvent.copy()).thenReturn(motionEvent)
- mController = BrightnessSlider(brightnessSliderView, mFalsingManager)
+ mController = BrightnessSliderController(brightnessSliderView, mFalsingManager)
mController.init()
mController.setOnChangedListener(listener)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
index d098e1a..624bedc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
@@ -58,7 +58,6 @@
private KeyguardClockPositionAlgorithm.Result mClockPosition;
private MockitoSession mStaticMockSession;
- private int mNotificationStackHeight;
private float mPanelExpansion;
private int mKeyguardStatusBarHeaderHeight;
@@ -264,6 +263,30 @@
}
@Test
+ public void notifPaddingExpandedAlignedWithClockInSplitShadeMode() {
+ givenLockScreen();
+ mIsSplitShade = true;
+ mKeyguardStatusHeight = 200;
+ // WHEN the position algorithm is run
+ positionClock();
+ // THEN the padding DOESN'T adjust for keyguard status height.
+ assertThat(mClockPosition.stackScrollerPaddingExpanded)
+ .isEqualTo(mClockPosition.clockYFullyDozing);
+ }
+
+ @Test
+ public void notifMinPaddingAlignedWithClockInSplitShadeMode() {
+ givenLockScreen();
+ mIsSplitShade = true;
+ mKeyguardStatusHeight = 200;
+ // WHEN the position algorithm is run
+ positionClock();
+ // THEN the padding DOESN'T adjust for keyguard status height.
+ assertThat(mClockPositionAlgorithm.getMinStackScrollerPadding())
+ .isEqualTo(mKeyguardStatusBarHeaderHeight);
+ }
+
+ @Test
public void notifPositionWithLargeClockOnLockScreen() {
// GIVEN on lock screen and clock has a nonzero height
givenLockScreen();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 35d15af..2d944aa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.phone;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
@@ -97,6 +98,8 @@
@Mock
private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
@Mock
+ private StatusBarKeyguardViewManager.AlternateAuthInterceptor mAlternateAuthInterceptor;
+ @Mock
private KeyguardMessageArea mKeyguardMessageArea;
@Mock
private Lazy<ShadeController> mShadeController;
@@ -287,6 +290,24 @@
}
@Test
+ public void testShowing_whenAlternateAuthShowing() {
+ mStatusBarKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor);
+ when(mBouncer.isShowing()).thenReturn(false);
+ when(mAlternateAuthInterceptor.isShowingAlternateAuthBouncer()).thenReturn(true);
+ assertTrue("Is showing not accurate when alternative auth showing",
+ mStatusBarKeyguardViewManager.isShowing());
+ }
+
+ @Test
+ public void testWillBeShowing_whenAlternateAuthShowing() {
+ mStatusBarKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor);
+ when(mBouncer.isShowing()).thenReturn(false);
+ when(mAlternateAuthInterceptor.isShowingAlternateAuthBouncer()).thenReturn(true);
+ assertTrue("Is or will be showing not accurate when alternative auth showing",
+ mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing());
+ }
+
+ @Test
public void testUpdateResources_delegatesToBouncer() {
mStatusBarKeyguardViewManager.updateResources();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index ca8b6c8..f14b126 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -96,7 +96,7 @@
import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.ScreenPinningRequest;
-import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -259,7 +259,7 @@
@Mock private PhoneStatusBarPolicy mPhoneStatusBarPolicy;
@Mock private DemoModeController mDemoModeController;
@Mock private Lazy<NotificationShadeDepthController> mNotificationShadeDepthControllerLazy;
- @Mock private BrightnessSlider.Factory mBrightnessSliderFactory;
+ @Mock private BrightnessSliderController.Factory mBrightnessSliderFactory;
@Mock private UnfoldTransitionConfig mUnfoldTransitionConfig;
@Mock private Lazy<UnfoldLightRevealOverlayAnimation> mUnfoldLightRevealOverlayAnimationLazy;
@Mock private Lazy<NaturalRotationUnfoldProgressProvider> mNaturalRotationProgressProvider;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
new file mode 100644
index 0000000..a8a33da
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
@@ -0,0 +1,92 @@
+/*
+ * 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.statusbar.phone
+
+import android.animation.Animator
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import android.view.View
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.keyguard.KeyguardViewMediator
+import com.android.systemui.keyguard.WakefulnessLifecycle
+import com.android.systemui.statusbar.LightRevealScrim
+import com.android.systemui.statusbar.StatusBarStateControllerImpl
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.settings.GlobalSettings
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.spy
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper(setAsMainLooper = true)
+class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() {
+
+ private lateinit var controller: UnlockedScreenOffAnimationController
+ @Mock
+ private lateinit var keyguardViewMediator: KeyguardViewMediator
+ @Mock
+ private lateinit var dozeParameters: DozeParameters
+ @Mock
+ private lateinit var keyguardStateController: KeyguardStateController
+ @Mock
+ private lateinit var globalSettings: GlobalSettings
+ @Mock
+ private lateinit var statusbar: StatusBar
+ @Mock
+ private lateinit var lightRevealScrim: LightRevealScrim
+ @Mock
+ private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
+ @Mock
+ private lateinit var statusBarStateController: StatusBarStateControllerImpl
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ controller = UnlockedScreenOffAnimationController(
+ context,
+ wakefulnessLifecycle,
+ statusBarStateController,
+ dagger.Lazy<KeyguardViewMediator> { keyguardViewMediator },
+ keyguardStateController,
+ dagger.Lazy<DozeParameters> { dozeParameters },
+ globalSettings
+ )
+ controller.initialize(statusbar, lightRevealScrim)
+ }
+
+ @Test
+ fun testAnimClearsEndListener() {
+ val keyguardView = View(context)
+ val animator = spy(keyguardView.animate())
+ val keyguardSpy = spy(keyguardView)
+ Mockito.`when`(keyguardSpy.animate()).thenReturn(animator)
+ val listener = ArgumentCaptor.forClass(Animator.AnimatorListener::class.java)
+ controller.animateInKeyguard(keyguardSpy, Runnable {})
+ Mockito.verify(animator).setListener(listener.capture())
+ // Verify that the listener is cleared when it ends
+ listener.value.onAnimationEnd(null)
+ Mockito.verify(animator).setListener(null)
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt b/packages/SystemUI/tests/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
index bff99bf..483dc9f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
@@ -58,3 +58,24 @@
*/
inline fun <reified T : Any> argumentCaptor(): ArgumentCaptor<T> =
ArgumentCaptor.forClass(T::class.java)
+
+/**
+ * Helper function for creating new mocks, without the need to pass in a [Class] instance.
+ *
+ * Generic T is nullable because implicitly bounded by Any?.
+ */
+inline fun <reified T : Any> mock(): T = Mockito.mock(T::class.java)
+
+/**
+ * Helper function for creating and using a single-use ArgumentCaptor in kotlin.
+ *
+ * val captor = argumentCaptor<Foo>()
+ * verify(...).someMethod(captor.capture())
+ * val captured = captor.value
+ *
+ * becomes:
+ *
+ * val captured = withArgCaptor<Foo> { verify(...).someMethod(capture()) }
+ */
+inline fun <reified T : Any> withArgCaptor(block: ArgumentCaptor<T>.() -> Unit): T =
+ argumentCaptor<T>().apply { block() }.value
\ No newline at end of file
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index 61b8ded..031f6ee 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -168,10 +168,6 @@
return Utils.isKeyguard(getContext(), getOwnerString());
}
- private boolean isSettings() {
- return Utils.isSettings(getContext(), getOwnerString());
- }
-
@Override
protected boolean isCryptoOperation() {
return mOperationId != 0;
@@ -503,8 +499,6 @@
protected int getShowOverlayReason() {
if (isKeyguard()) {
return BiometricOverlayConstants.REASON_AUTH_KEYGUARD;
- } else if (isSettings()) {
- return BiometricOverlayConstants.REASON_AUTH_SETTINGS;
} else if (isBiometricPrompt()) {
return BiometricOverlayConstants.REASON_AUTH_BP;
} else {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java
index 0050a89..be0e6ed 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java
@@ -23,7 +23,6 @@
import static android.hardware.fingerprint.FingerprintStateListener.STATE_KEYGUARD_AUTH;
import android.annotation.NonNull;
-import android.content.Context;
import android.hardware.fingerprint.FingerprintStateListener;
import android.hardware.fingerprint.IFingerprintStateListener;
import android.os.RemoteException;
@@ -34,8 +33,6 @@
import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.EnrollClient;
import com.android.server.biometrics.sensors.EnrollmentModifier;
-import com.android.server.biometrics.sensors.RemovalConsumer;
-import com.android.server.biometrics.sensors.fingerprint.hidl.FingerprintEnrollClient;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -70,7 +67,7 @@
} else {
mFingerprintState = STATE_AUTH_OTHER;
}
- } else if (client instanceof FingerprintEnrollClient) {
+ } else if (client instanceof EnrollClient) {
mFingerprintState = STATE_ENROLLING;
} else {
Slog.w(FingerprintService.TAG,
@@ -143,6 +140,7 @@
/**
* Enables clients to register a FingerprintStateListener. Used by FingerprintService to forward
* updates in fingerprint sensor state to the SideFpNsEventHandler
+ *
* @param listener
*/
public void registerFingerprintStateListener(@NonNull IFingerprintStateListener listener) {
diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
index 345dc21..72ab8c1 100644
--- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
@@ -1996,6 +1996,11 @@
+ TimeUtils.formatDuration(delayMs));
}
+ if (mDelayedRegister != null) {
+ mAlarmHelper.cancel(mDelayedRegister);
+ mDelayedRegister = null;
+ }
+
mDelayedRegister = new OnAlarmListener() {
@Override
public void onAlarm() {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 84e62d4..8ace5e4 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -3081,9 +3081,6 @@
mAtmService.deferWindowLayout();
try {
- final Transition newTransition = (!mTransitionController.isCollecting()
- && mTransitionController.getTransitionPlayer() != null)
- ? mTransitionController.createTransition(TRANSIT_CLOSE) : null;
mTaskSupervisor.mNoHistoryActivities.remove(this);
makeFinishingLocked();
// Make a local reference to its task since this.task could be set to null once this
@@ -3115,10 +3112,7 @@
final boolean endTask = task.getTopNonFinishingActivity() == null
&& !task.isClearingToReuseTask();
- if (newTransition != null) {
- mTransitionController.requestStartTransition(newTransition,
- endTask ? task : null, null /* remote */);
- }
+ mTransitionController.requestCloseTransitionIfNeeded(endTask ? task : this);
if (isState(RESUMED)) {
if (endTask) {
mAtmService.getTaskChangeNotificationController().notifyTaskRemovalStarted(
@@ -3544,13 +3538,6 @@
if (stopped) {
abortAndClearOptionsAnimation();
}
- if (mTransitionController.isCollecting()) {
- // We don't want the finishing to change the transition ready state since there will not
- // be corresponding setReady for finishing.
- mTransitionController.collectExistenceChange(this);
- } else {
- mTransitionController.requestTransitionIfNeeded(TRANSIT_CLOSE, this);
- }
}
/**
@@ -3732,6 +3719,7 @@
// to the restarted activity.
nowVisible = mVisibleRequested;
}
+ mTransitionController.requestCloseTransitionIfNeeded(this);
cleanUp(true /* cleanServices */, true /* setState */);
if (remove) {
if (mStartingData != null && mVisible && task != null) {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index ba30592..7c5f059 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -44,7 +44,6 @@
import static android.os.Process.INVALID_UID;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
@@ -1562,19 +1561,7 @@
// Prevent recursion.
return;
}
- if (task.isVisible()) {
- if (task.mTransitionController.isCollecting()) {
- // We don't want the finishing to change the transition ready state since there will
- // not be corresponding setReady for finishing.
- task.mTransitionController.collectExistenceChange(task);
- } else {
- task.mTransitionController.requestTransitionIfNeeded(TRANSIT_CLOSE, task);
- }
- } else {
- // Removing a non-visible task doesn't require a transition, but if there is one
- // collecting, this should be a member just in case.
- task.mTransitionController.collect(task);
- }
+ task.mTransitionController.requestCloseTransitionIfNeeded(task);
task.mInRemoveTask = true;
try {
task.performClearTask(reason);
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 275ed0e..f5e7967 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -864,12 +864,9 @@
int layer = 0;
// Place root home tasks to the bottom.
layer = adjustRootTaskLayer(t, mTmpHomeChildren, layer);
- adjustRootTaskLayer(t, mTmpNormalChildren, layer);
-
- // Always on top tasks layer should higher than split divider layer so set it as start.
- t.setLayer(mSplitScreenDividerAnchor, SPLIT_DIVIDER_LAYER);
- layer = SPLIT_DIVIDER_LAYER + 1;
+ layer = adjustRootTaskLayer(t, mTmpNormalChildren, layer);
adjustRootTaskLayer(t, mTmpAlwaysOnTopChildren, layer);
+ t.setLayer(mSplitScreenDividerAnchor, SPLIT_DIVIDER_LAYER);
}
/**
@@ -884,19 +881,33 @@
ArrayList<WindowContainer> children, int startLayer) {
mTmpNeedsZBoostIndexes.clear();
final int childCount = children.size();
+ boolean hasAdjacentTask = false;
for (int i = 0; i < childCount; i++) {
final WindowContainer child = children.get(i);
final TaskDisplayArea childTda = child.asTaskDisplayArea();
-
- boolean childNeedsZBoost = childTda != null
+ final boolean childNeedsZBoost = childTda != null
? childTda.childrenNeedZBoost()
: child.needsZBoost();
- if (!childNeedsZBoost) {
- child.assignLayer(t, startLayer++);
- } else {
+ if (childNeedsZBoost) {
mTmpNeedsZBoostIndexes.add(i);
+ continue;
}
+
+ final Task childTask = child.asTask();
+ final boolean inAdjacentTask = childTask != null
+ && child.inMultiWindowMode()
+ && childTask.getRootTask().getAdjacentTaskFragment() != null;
+
+ if (inAdjacentTask || child.inSplitScreenWindowingMode()) {
+ hasAdjacentTask = true;
+ } else if (hasAdjacentTask && startLayer < SPLIT_DIVIDER_LAYER) {
+ // Task on top of adjacent tasks should be higher than split divider layer so
+ // set it as start.
+ startLayer = SPLIT_DIVIDER_LAYER + 1;
+ }
+
+ child.assignLayer(t, startLayer++);
}
final int zBoostSize = mTmpNeedsZBoostIndexes.size();
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 5d82553..4db8ef4 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -338,6 +338,11 @@
applyReady();
}
+ @VisibleForTesting
+ boolean allReady() {
+ return mReadyTracker.allReady();
+ }
+
/**
* Build a transaction that "resets" all the re-parenting and layer changes. This is
* intended to be applied at the end of the transition but before the finish callback. This
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index 91825cc..a21e4f2 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -35,7 +35,6 @@
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.WindowManager;
-import android.window.IRemoteTransition;
import android.window.ITransitionMetricsReporter;
import android.window.ITransitionPlayer;
import android.window.RemoteTransition;
@@ -226,7 +225,7 @@
}
/**
- * @see #requestTransitionIfNeeded(int, int, WindowContainer, IRemoteTransition)
+ * @see #requestTransitionIfNeeded(int, int, WindowContainer, WindowContainer, RemoteTransition)
*/
@Nullable
Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
@@ -235,7 +234,7 @@
}
/**
- * @see #requestTransitionIfNeeded(int, int, WindowContainer, IRemoteTransition)
+ * @see #requestTransitionIfNeeded(int, int, WindowContainer, WindowContainer, RemoteTransition)
*/
@Nullable
Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
@@ -306,6 +305,22 @@
return transition;
}
+ /** Requests transition for a window container which will be removed or invisible. */
+ void requestCloseTransitionIfNeeded(@NonNull WindowContainer<?> wc) {
+ if (mTransitionPlayer == null) return;
+ if (wc.isVisibleRequested()) {
+ if (!isCollecting()) {
+ requestStartTransition(createTransition(TRANSIT_CLOSE, 0 /* flags */),
+ wc.asTask(), null /* remoteTransition */);
+ }
+ collectExistenceChange(wc);
+ } else {
+ // Removing a non-visible window doesn't require a transition, but if there is one
+ // collecting, this should be a member just in case.
+ collect(wc);
+ }
+ }
+
/** @see Transition#collect */
void collect(@NonNull WindowContainer wc) {
if (mCollectingTransition == null) return;
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 51ecce0..a68b09e 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -32,10 +32,6 @@
import static android.view.SurfaceControl.Transaction;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
import static android.view.WindowManager.TRANSIT_CHANGE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_BACK;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_FRONT;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
@@ -43,6 +39,7 @@
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SYNC_ENGINE;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.AppTransition.MAX_APP_TRANSITION_DURATION;
+import static com.android.server.wm.AppTransition.isTaskTransitOld;
import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
@@ -70,7 +67,6 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.ActivityThread;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
@@ -91,6 +87,7 @@
import android.view.SurfaceControl;
import android.view.SurfaceControl.Builder;
import android.view.SurfaceSession;
+import android.view.TaskTransitionSpec;
import android.view.WindowManager;
import android.view.WindowManager.TransitionOldType;
import android.view.animation.Animation;
@@ -2825,33 +2822,15 @@
mSurfaceAnimationSources.addAll(sources);
}
- TaskDisplayArea taskDisplayArea = getTaskDisplayArea();
- boolean isSettingBackgroundColor = taskDisplayArea != null
- && isTransitionWithBackgroundColor(transit);
+ AnimationRunnerBuilder animationRunnerBuilder = new AnimationRunnerBuilder();
- if (isSettingBackgroundColor) {
- Context uiContext = ActivityThread.currentActivityThread().getSystemUiContext();
- @ColorInt int backgroundColor = uiContext.getColor(R.color.overview_background);
-
- taskDisplayArea.setBackgroundColor(backgroundColor);
+ if (isTaskTransitOld(transit)) {
+ animationRunnerBuilder.setTaskBackgroundColor(getTaskAnimationBackgroundColor());
}
- // Atomic counter to make sure the clearColor callback is only called one.
- // It will be called twice in the case we cancel the animation without restart
- // (in that case it will run as the cancel and finished callbacks).
- final AtomicInteger callbackCounter = new AtomicInteger(0);
- final Runnable clearBackgroundColorHandler = () -> {
- if (callbackCounter.getAndIncrement() == 0) {
- taskDisplayArea.clearBackgroundColor();
- }
- };
-
- final Runnable cleanUpCallback = isSettingBackgroundColor
- ? clearBackgroundColorHandler : () -> {};
-
- startAnimation(getPendingTransaction(), adapter, !isVisible(),
- ANIMATION_TYPE_APP_TRANSITION, (type, anim) -> cleanUpCallback.run(),
- cleanUpCallback, thumbnailAdapter);
+ animationRunnerBuilder.build()
+ .startAnimation(getPendingTransaction(), adapter, !isVisible(),
+ ANIMATION_TYPE_APP_TRANSITION, thumbnailAdapter);
if (adapter.getShowWallpaper()) {
getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
@@ -2859,11 +2838,16 @@
}
}
- private boolean isTransitionWithBackgroundColor(@TransitionOldType int transit) {
- return transit == TRANSIT_OLD_TASK_OPEN
- || transit == TRANSIT_OLD_TASK_CLOSE
- || transit == TRANSIT_OLD_TASK_TO_FRONT
- || transit == TRANSIT_OLD_TASK_TO_BACK;
+ private @ColorInt int getTaskAnimationBackgroundColor() {
+ Context uiContext = mDisplayContent.getDisplayPolicy().getSystemUiContext();
+ TaskTransitionSpec customSpec = mWmService.mTaskTransitionSpec;
+ @ColorInt int defaultFallbackColor = uiContext.getColor(R.color.overview_background);
+
+ if (customSpec != null && customSpec.backgroundColor != 0) {
+ return customSpec.backgroundColor;
+ }
+
+ return defaultFallbackColor;
}
final SurfaceAnimationRunner getSurfaceAnimationRunner() {
@@ -3551,4 +3535,53 @@
getPendingTransaction().setSecure(mSurfaceControl, !canScreenshot);
return true;
}
+
+ private class AnimationRunnerBuilder {
+ /**
+ * Runs when the surface stops animating
+ */
+ private final List<Runnable> mOnAnimationFinished = new LinkedList<>();
+ /**
+ * Runs when the animation is cancelled but the surface is still animating
+ */
+ private final List<Runnable> mOnAnimationCancelled = new LinkedList<>();
+
+ private void setTaskBackgroundColor(@ColorInt int backgroundColor) {
+ TaskDisplayArea taskDisplayArea = getTaskDisplayArea();
+
+ if (taskDisplayArea != null) {
+ taskDisplayArea.setBackgroundColor(backgroundColor);
+
+ // Atomic counter to make sure the clearColor callback is only called one.
+ // It will be called twice in the case we cancel the animation without restart
+ // (in that case it will run as the cancel and finished callbacks).
+ final AtomicInteger callbackCounter = new AtomicInteger(0);
+ final Runnable clearBackgroundColorHandler = () -> {
+ if (callbackCounter.getAndIncrement() == 0) {
+ taskDisplayArea.clearBackgroundColor();
+ }
+ };
+
+ // We want to make sure this is called both when the surface stops animating and
+ // also when an animation is cancelled (i.e. animation is replaced by another
+ // animation but and so the surface is still animating)
+ mOnAnimationFinished.add(clearBackgroundColorHandler);
+ mOnAnimationCancelled.add(clearBackgroundColorHandler);
+ }
+ }
+
+ private IAnimationStarter build() {
+ return (Transaction t, AnimationAdapter adapter, boolean hidden,
+ @AnimationType int type, @Nullable AnimationAdapter snapshotAnim) -> {
+ startAnimation(getPendingTransaction(), adapter, !isVisible(), type,
+ (animType, anim) -> mOnAnimationFinished.forEach(Runnable::run),
+ () -> mOnAnimationCancelled.forEach(Runnable::run), snapshotAnim);
+ };
+ }
+ }
+
+ private interface IAnimationStarter {
+ void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
+ @AnimationType int type, @Nullable AnimationAdapter snapshotAnim);
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 44cff33..128bfa8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -166,6 +166,8 @@
@Before
public void setUp() throws Exception {
setBooted(mAtm);
+ // Because the booted state is set, avoid starting real home if there is no task.
+ doReturn(false).when(mRootWindowContainer).resumeHomeActivity(any(), anyString(), any());
}
private TestStartingWindowOrganizer registerTestStartingWindowOrganizer() {
@@ -1083,6 +1085,7 @@
*/
@Test
public void testFinishActivityIfPossible_nonVisibleNoAppTransition() {
+ registerTestTransitionPlayer();
final ActivityRecord activity = createActivityWithTask();
// Put an activity on top of test activity to make it invisible and prevent us from
// accidentally resuming the topmost one again.
@@ -1093,6 +1096,7 @@
activity.finishIfPossible("test", false /* oomAdj */);
verify(activity.mDisplayContent, never()).prepareAppTransition(eq(TRANSIT_CLOSE));
+ assertFalse(activity.inTransition());
}
/**
@@ -1101,11 +1105,7 @@
*/
@Test
public void testFinishActivityIfPossible_lastInTaskRequestsTransitionWithTrigger() {
- // Set-up mock shell transitions
- final TestTransitionPlayer testPlayer = new TestTransitionPlayer(
- mAtm.getTransitionController(), mAtm.mWindowOrganizerController);
- mAtm.getTransitionController().registerTransitionPlayer(testPlayer);
-
+ final TestTransitionPlayer testPlayer = registerTestTransitionPlayer();
final ActivityRecord activity = createActivityWithTask();
activity.finishing = false;
activity.mVisibleRequested = true;
@@ -1117,6 +1117,29 @@
}
/**
+ * Verify that when collecting activity to the existing close transition, it should not affect
+ * ready state.
+ */
+ @Test
+ public void testFinishActivityIfPossible_collectToExistingTransition() {
+ final TestTransitionPlayer testPlayer = registerTestTransitionPlayer();
+ final ActivityRecord activity = createActivityWithTask();
+ activity.setState(PAUSED, "test");
+ activity.finishIfPossible("test", false /* oomAdj */);
+ final Transition lastTransition = testPlayer.mLastTransit;
+ assertTrue(lastTransition.allReady());
+ assertTrue(activity.inTransition());
+
+ // Collect another activity to the existing transition without changing ready state.
+ final ActivityRecord activity2 = createActivityRecord(activity.getTask());
+ activity2.setState(PAUSING, "test");
+ activity2.finishIfPossible("test", false /* oomAdj */);
+ assertTrue(activity2.inTransition());
+ assertEquals(lastTransition, testPlayer.mLastTransit);
+ assertTrue(lastTransition.allReady());
+ }
+
+ /**
* Verify that complete finish request for non-finishing activity is invalid.
*/
@Test(expected = IllegalArgumentException.class)
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 24bbf46..f3c1ec5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1674,11 +1674,7 @@
public void testShellTransitRotation() {
DisplayContent dc = createNewDisplay();
- // Set-up mock shell transitions
- final TestTransitionPlayer testPlayer = new TestTransitionPlayer(
- mAtm.getTransitionController(), mAtm.mWindowOrganizerController);
- mAtm.getTransitionController().registerTransitionPlayer(testPlayer);
-
+ final TestTransitionPlayer testPlayer = registerTestTransitionPlayer();
final DisplayRotation dr = dc.getDisplayRotation();
doCallRealMethod().when(dr).updateRotationUnchecked(anyBoolean());
// Rotate 180 degree so the display doesn't have configuration change. This condition is
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index ac61bb1..81b00ea 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -798,6 +798,14 @@
};
}
+ /** Sets up a simple implementation of transition player for shell transitions. */
+ TestTransitionPlayer registerTestTransitionPlayer() {
+ final TestTransitionPlayer testPlayer = new TestTransitionPlayer(
+ mAtm.getTransitionController(), mAtm.mWindowOrganizerController);
+ testPlayer.mController.registerTransitionPlayer(testPlayer);
+ return testPlayer;
+ }
+
/**
* Avoids rotating screen disturbed by some conditions. It is usually used for the default
* display that is not the instance of {@link TestDisplayContent} (it bypasses the conditions).
@@ -1606,7 +1614,7 @@
}
}
- class TestTransitionPlayer extends ITransitionPlayer.Stub {
+ static class TestTransitionPlayer extends ITransitionPlayer.Stub {
final TransitionController mController;
final WindowOrganizerController mOrganizer;
Transition mLastTransit = null;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
index 22ea3d5..72b05c0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
@@ -23,7 +23,6 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
@@ -442,24 +441,42 @@
@Test
public void testDockedDividerPosition() {
- final WindowState pinnedStackWindow = createWindow(null, WINDOWING_MODE_PINNED,
- ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION, mDisplayContent,
- "pinnedStackWindow");
- final WindowState splitScreenWindow = createWindow(null,
- WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION,
- mDisplayContent, "splitScreenWindow");
- final WindowState splitScreenSecondaryWindow = createWindow(null,
- WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD,
- TYPE_BASE_APPLICATION, mDisplayContent, "splitScreenSecondaryWindow");
- final WindowState assistantStackWindow = createWindow(null,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, TYPE_BASE_APPLICATION,
- mDisplayContent, "assistantStackWindow");
+ final Task pinnedTask =
+ createTask(mDisplayContent, WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
+ final WindowState pinnedWindow =
+ createAppWindow(pinnedTask, ACTIVITY_TYPE_STANDARD, "pinnedWindow");
+
+ final Task belowTask =
+ createTask(mDisplayContent, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final WindowState belowTaskWindow =
+ createAppWindow(belowTask, ACTIVITY_TYPE_STANDARD, "belowTaskWindow");
+
+ final Task splitScreenTask1 =
+ createTask(mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
+ final WindowState splitWindow1 =
+ createAppWindow(splitScreenTask1, ACTIVITY_TYPE_STANDARD, "splitWindow1");
+ final Task splitScreenTask2 =
+ createTask(mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
+ final WindowState splitWindow2 =
+ createAppWindow(splitScreenTask2, ACTIVITY_TYPE_STANDARD, "splitWindow2");
+ splitScreenTask1.setAdjacentTaskFragment(splitScreenTask2);
+ splitScreenTask2.setAdjacentTaskFragment(splitScreenTask1);
+
+ final Task aboveTask =
+ createTask(mDisplayContent, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final WindowState aboveTaskWindow =
+ createAppWindow(aboveTask, ACTIVITY_TYPE_STANDARD, "aboveTaskWindow");
mDisplayContent.assignChildLayers(mTransaction);
- assertWindowHigher(mDockedDividerWindow, splitScreenWindow);
- assertWindowHigher(mDockedDividerWindow, splitScreenSecondaryWindow);
- assertWindowHigher(pinnedStackWindow, mDockedDividerWindow);
+ assertWindowHigher(splitWindow1, belowTaskWindow);
+ assertWindowHigher(splitWindow1, belowTaskWindow);
+ assertWindowHigher(splitWindow2, belowTaskWindow);
+ assertWindowHigher(splitWindow2, belowTaskWindow);
+ assertWindowHigher(mDockedDividerWindow, splitWindow1);
+ assertWindowHigher(mDockedDividerWindow, splitWindow2);
+ assertWindowHigher(aboveTaskWindow, mDockedDividerWindow);
+ assertWindowHigher(pinnedWindow, aboveTaskWindow);
}
@Test