Merge "A new shade pull down animation" into sc-dev
This commit is contained in:
@@ -14,7 +14,6 @@
|
||||
|
||||
package com.android.systemui.plugins.qs;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
@@ -57,7 +56,6 @@ public interface QS extends FragmentBase {
|
||||
void setQsExpansion(float qsExpansionFraction, float headerTranslation);
|
||||
void setHeaderListening(boolean listening);
|
||||
void notifyCustomizeChanged();
|
||||
|
||||
void setContainer(ViewGroup container);
|
||||
void setExpandClickListener(OnClickListener onClickListener);
|
||||
|
||||
@@ -75,6 +73,16 @@ public interface QS extends FragmentBase {
|
||||
return isShowingDetail();
|
||||
}
|
||||
|
||||
/**
|
||||
* If QS should translate as we pull it down, or if it should be static.
|
||||
*/
|
||||
void setTranslateWhileExpanding(boolean shouldTranslate);
|
||||
|
||||
/**
|
||||
* A rounded corner clipping that makes QS feel as if it were behind everything.
|
||||
*/
|
||||
void setFancyClipping(int top, int bottom, int cornerRadius, boolean visible);
|
||||
|
||||
@ProvidesInterface(version = HeightListener.VERSION)
|
||||
interface HeightListener {
|
||||
int VERSION = 1;
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
android:visibility="invisible" />
|
||||
</com.android.systemui.statusbar.BackDropView>
|
||||
|
||||
<com.android.systemui.statusbar.ScrimView
|
||||
<com.android.systemui.scrim.ScrimView
|
||||
android:id="@+id/scrim_behind"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
@@ -51,7 +51,7 @@
|
||||
sysui:ignoreRightInset="true"
|
||||
/>
|
||||
|
||||
<com.android.systemui.statusbar.ScrimView
|
||||
<com.android.systemui.scrim.ScrimView
|
||||
android:id="@+id/scrim_notifications"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
@@ -72,7 +72,7 @@
|
||||
|
||||
<include layout="@layout/brightness_mirror_container" />
|
||||
|
||||
<com.android.systemui.statusbar.ScrimView
|
||||
<com.android.systemui.scrim.ScrimView
|
||||
android:id="@+id/scrim_in_front"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.keyguard;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Slog;
|
||||
|
||||
@@ -48,6 +49,7 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
|
||||
private final ConfigurationController mConfigurationController;
|
||||
private final DozeParameters mDozeParameters;
|
||||
private final KeyguardVisibilityHelper mKeyguardVisibilityHelper;
|
||||
private final Rect mClipBounds = new Rect();
|
||||
|
||||
private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
|
||||
|
||||
@@ -299,4 +301,17 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
|
||||
mView.updateLogoutView(shouldShowLogout());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Rect that specifies how KSV should be clipped, on its parent's coordinates.
|
||||
*/
|
||||
public void setClipBounds(Rect clipBounds) {
|
||||
if (clipBounds != null) {
|
||||
mClipBounds.set(clipBounds.left, (int) (clipBounds.top - mView.getY()),
|
||||
clipBounds.right, (int) (clipBounds.bottom - mView.getY()));
|
||||
mView.setClipBounds(mClipBounds);
|
||||
} else {
|
||||
mView.setClipBounds(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,6 @@ import com.android.internal.R;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.colorextraction.ColorExtractor;
|
||||
import com.android.internal.colorextraction.ColorExtractor.GradientColors;
|
||||
import com.android.internal.colorextraction.drawable.ScrimDrawable;
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.UiEvent;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
@@ -117,6 +116,7 @@ import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.model.SysUiState;
|
||||
import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
|
||||
import com.android.systemui.plugins.GlobalActionsPanelPlugin;
|
||||
import com.android.systemui.scrim.ScrimDrawable;
|
||||
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
|
||||
@@ -30,11 +30,11 @@ import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.colorextraction.drawable.ScrimDrawable;
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.settingslib.Utils;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.plugins.GlobalActions;
|
||||
import com.android.systemui.scrim.ScrimDrawable;
|
||||
import com.android.systemui.statusbar.BlurUtils;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.phone.ScrimController;
|
||||
|
||||
@@ -29,6 +29,7 @@ public class NonInterceptingScrollView extends ScrollView {
|
||||
|
||||
private final int mTouchSlop;
|
||||
private float mDownY;
|
||||
private boolean mScrollEnabled = true;
|
||||
|
||||
public NonInterceptingScrollView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
@@ -85,6 +86,16 @@ public class NonInterceptingScrollView extends ScrollView {
|
||||
return super.onInterceptTouchEvent(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canScrollVertically(int direction) {
|
||||
return mScrollEnabled && super.canScrollVertically(direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canScrollHorizontally(int direction) {
|
||||
return mScrollEnabled && super.canScrollHorizontally(direction);
|
||||
}
|
||||
|
||||
public int getScrollRange() {
|
||||
int scrollRange = 0;
|
||||
if (getChildCount() > 0) {
|
||||
@@ -94,4 +105,12 @@ public class NonInterceptingScrollView extends ScrollView {
|
||||
}
|
||||
return scrollRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable scrolling for this view. Needed because the view might be clipped but still intercepts
|
||||
* touches on the lockscreen.
|
||||
*/
|
||||
public void setScrollingEnabled(boolean enabled) {
|
||||
mScrollEnabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
|
||||
private static final String MOVE_FULL_ROWS = "sysui_qs_move_whole_rows";
|
||||
|
||||
public static final float EXPANDED_TILE_DELAY = .86f;
|
||||
public static final float SHORT_PARALLAX_AMOUNT = 0.1f;
|
||||
private static final long QQS_FADE_IN_DURATION = 200L;
|
||||
// Fade out faster than fade in to finish before QQS hides.
|
||||
private static final long QQS_FADE_OUT_DURATION = 50L;
|
||||
@@ -101,6 +102,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
|
||||
private final Executor mExecutor;
|
||||
private final TunerService mTunerService;
|
||||
private boolean mShowCollapsedOnKeyguard;
|
||||
private boolean mTranslateWhileExpanding;
|
||||
|
||||
@Inject
|
||||
public QSAnimator(QS qs, QuickQSPanel quickPanel, QuickStatusBarHeader quickStatusBarHeader,
|
||||
@@ -242,6 +244,9 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
|
||||
int width = mQs.getView() != null ? mQs.getView().getMeasuredWidth() : 0;
|
||||
int heightDiff = height - mQs.getHeader().getBottom()
|
||||
+ mQs.getHeader().getPaddingBottom();
|
||||
if (!mTranslateWhileExpanding) {
|
||||
heightDiff *= SHORT_PARALLAX_AMOUNT;
|
||||
}
|
||||
firstPageBuilder.addFloat(tileLayout, "translationY", heightDiff, 0);
|
||||
|
||||
int qqsTileHeight = 0;
|
||||
@@ -570,6 +575,13 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
|
||||
setCurrentPosition();
|
||||
};
|
||||
|
||||
/**
|
||||
* True whe QS will be pulled from the top, false when it will be clipped.
|
||||
*/
|
||||
public void setTranslateWhileExpanding(boolean shouldTranslate) {
|
||||
mTranslateWhileExpanding = shouldTranslate;
|
||||
}
|
||||
|
||||
static class HeightExpansionAnimator {
|
||||
private final List<View> mViews = new ArrayList<>();
|
||||
private final ValueAnimator mAnimator;
|
||||
|
||||
@@ -20,6 +20,8 @@ import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Point;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
@@ -54,6 +56,10 @@ public class QSContainerImpl extends FrameLayout {
|
||||
private static final PhysicsAnimator.SpringConfig BACKGROUND_SPRING
|
||||
= new PhysicsAnimator.SpringConfig(SpringForce.STIFFNESS_MEDIUM,
|
||||
SpringForce.DAMPING_RATIO_LOW_BOUNCY);
|
||||
private int mFancyClippingTop;
|
||||
private int mFancyClippingBottom;
|
||||
private final float[] mFancyClippingRadii = new float[] {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
private final Path mFancyClippingPath = new Path();
|
||||
private int mBackgroundBottom = -1;
|
||||
private int mHeightOverride = -1;
|
||||
private View mQSDetail;
|
||||
@@ -70,6 +76,7 @@ public class QSContainerImpl extends FrameLayout {
|
||||
private int mContentPadding = -1;
|
||||
private boolean mAnimateBottomOnNextLayout;
|
||||
private int mNavBarInset = 0;
|
||||
private boolean mClippingEnabled;
|
||||
|
||||
public QSContainerImpl(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
@@ -169,6 +176,15 @@ public class QSContainerImpl extends FrameLayout {
|
||||
MeasureSpec.makeMeasureSpec(getDisplayHeight(), MeasureSpec.EXACTLY));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchDraw(Canvas canvas) {
|
||||
if (!mFancyClippingPath.isEmpty()) {
|
||||
canvas.translate(0, -getTranslationY());
|
||||
canvas.clipOutPath(mFancyClippingPath);
|
||||
canvas.translate(0, getTranslationY());
|
||||
}
|
||||
super.dispatchDraw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed,
|
||||
@@ -187,6 +203,7 @@ public class QSContainerImpl extends FrameLayout {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
updateExpansion(mAnimateBottomOnNextLayout /* animate */);
|
||||
mAnimateBottomOnNextLayout = false;
|
||||
updateClippingPath();
|
||||
}
|
||||
|
||||
public void disable(int state1, int state2, boolean animate) {
|
||||
@@ -281,6 +298,7 @@ public class QSContainerImpl extends FrameLayout {
|
||||
|
||||
public void setExpansion(float expansion) {
|
||||
mQsExpansion = expansion;
|
||||
mQSPanelContainer.setScrollingEnabled(expansion > 0.0f);
|
||||
updateExpansion();
|
||||
}
|
||||
|
||||
@@ -318,4 +336,46 @@ public class QSContainerImpl extends FrameLayout {
|
||||
}
|
||||
return mSizePoint.y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clip QS bottom using a concave shape.
|
||||
*/
|
||||
public void setFancyClipping(int top, int bottom, int radius, boolean enabled) {
|
||||
boolean updatePath = false;
|
||||
if (mFancyClippingRadii[0] != radius) {
|
||||
mFancyClippingRadii[0] = radius;
|
||||
mFancyClippingRadii[1] = radius;
|
||||
mFancyClippingRadii[2] = radius;
|
||||
mFancyClippingRadii[3] = radius;
|
||||
updatePath = true;
|
||||
}
|
||||
if (mFancyClippingTop != top) {
|
||||
mFancyClippingTop = top;
|
||||
updatePath = true;
|
||||
}
|
||||
if (mFancyClippingBottom != bottom) {
|
||||
mFancyClippingBottom = bottom;
|
||||
updatePath = true;
|
||||
}
|
||||
if (mClippingEnabled != enabled) {
|
||||
mClippingEnabled = enabled;
|
||||
updatePath = true;
|
||||
}
|
||||
|
||||
if (updatePath) {
|
||||
updateClippingPath();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateClippingPath() {
|
||||
mFancyClippingPath.reset();
|
||||
if (!mClippingEnabled) {
|
||||
invalidate();
|
||||
return;
|
||||
}
|
||||
|
||||
mFancyClippingPath.addRoundRect(0, mFancyClippingTop, getWidth(),
|
||||
mFancyClippingBottom, mFancyClippingRadii, Path.Direction.CW);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +107,11 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
||||
private QuickQSPanelController mQuickQSPanelController;
|
||||
private QSCustomizerController mQSCustomizerController;
|
||||
private FeatureFlags mFeatureFlags;
|
||||
/**
|
||||
* When true, QS will translate from outside the screen. It will be clipped with parallax
|
||||
* otherwise.
|
||||
*/
|
||||
private boolean mTranslateWhileExpanding;
|
||||
|
||||
@Inject
|
||||
public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
|
||||
@@ -254,6 +259,13 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFancyClipping(int top, int bottom, int cornerRadius, boolean visible) {
|
||||
if (getView() instanceof QSContainerImpl) {
|
||||
((QSContainerImpl) getView()).setFancyClipping(top, bottom, cornerRadius, visible);
|
||||
}
|
||||
}
|
||||
|
||||
private void setEditLocation(View view) {
|
||||
View edit = view.findViewById(android.R.id.edit);
|
||||
int[] loc = edit.getLocationOnScreen();
|
||||
@@ -393,17 +405,24 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
||||
mFooter.setListening(listening);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTranslateWhileExpanding(boolean shouldTranslate) {
|
||||
mTranslateWhileExpanding = shouldTranslate;
|
||||
mQSAnimator.setTranslateWhileExpanding(shouldTranslate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setQsExpansion(float expansion, float headerTranslation) {
|
||||
if (DEBUG) Log.d(TAG, "setQSExpansion " + expansion + " " + headerTranslation);
|
||||
|
||||
if (mQSAnimator != null) {
|
||||
final boolean showQSOnLockscreen = expansion > 0;
|
||||
final boolean showQSUnlocked = headerTranslation == 0;
|
||||
final boolean showQSUnlocked = headerTranslation == 0 || !mTranslateWhileExpanding;
|
||||
mQSAnimator.startAlphaAnimation(showQSOnLockscreen || showQSUnlocked);
|
||||
}
|
||||
mContainer.setExpansion(expansion);
|
||||
final float translationScaleY = expansion - 1;
|
||||
final float translationScaleY = (mTranslateWhileExpanding
|
||||
? 1 : QSAnimator.SHORT_PARALLAX_AMOUNT) * (expansion - 1);
|
||||
boolean onKeyguardAndExpanded = isKeyguardShowing() && !mShowCollapsedOnKeyguard;
|
||||
if (!mHeaderAnimating && !headerWillBeAnimating()) {
|
||||
getView().setTranslationY(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
* 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.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.internal.colorextraction.drawable;
|
||||
package com.android.systemui.scrim;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
@@ -49,6 +49,7 @@ public class ScrimDrawable extends Drawable {
|
||||
private float mCornerRadius;
|
||||
private Rect mBounds;
|
||||
private ConcaveInfo mConcaveInfo;
|
||||
private int mBottomEdgePosition;
|
||||
|
||||
public ScrimDrawable() {
|
||||
mPaint = new Paint();
|
||||
@@ -143,21 +144,43 @@ public class ScrimDrawable extends Drawable {
|
||||
* Make bottom edge concave with provided corner radius
|
||||
*/
|
||||
public void setBottomEdgeConcave(float radius) {
|
||||
if (radius == 0) {
|
||||
// Disable clipping completely when there's no radius.
|
||||
mConcaveInfo = null;
|
||||
return;
|
||||
}
|
||||
// only rounding top corners for clip out path
|
||||
float[] cornerRadii = new float[]{radius, radius, radius, radius, 0, 0, 0, 0};
|
||||
mConcaveInfo = new ConcaveInfo(radius, cornerRadii);
|
||||
}
|
||||
|
||||
/**
|
||||
* Location of concave edge.
|
||||
* @see #setBottomEdgeConcave(float)
|
||||
*/
|
||||
public void setBottomEdgePosition(int y) {
|
||||
if (mBottomEdgePosition == y) {
|
||||
return;
|
||||
}
|
||||
mBottomEdgePosition = y;
|
||||
if (mConcaveInfo == null) {
|
||||
return;
|
||||
}
|
||||
updatePath();
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(@NonNull Canvas canvas) {
|
||||
mPaint.setColor(mMainColor);
|
||||
mPaint.setAlpha(mAlpha);
|
||||
if (mConcaveInfo != null) {
|
||||
drawConcave(canvas);
|
||||
} else {
|
||||
canvas.drawRoundRect(getBounds().left, getBounds().top, getBounds().right,
|
||||
getBounds().bottom + mCornerRadius,
|
||||
/* x radius*/ mCornerRadius, /* y radius*/ mCornerRadius, mPaint);
|
||||
}
|
||||
canvas.drawRoundRect(getBounds().left, getBounds().top, getBounds().right,
|
||||
getBounds().bottom + mCornerRadius,
|
||||
/* x radius*/ mCornerRadius, /* y radius*/ mCornerRadius, mPaint);
|
||||
}
|
||||
|
||||
private void drawConcave(Canvas canvas) {
|
||||
@@ -165,19 +188,23 @@ public class ScrimDrawable extends Drawable {
|
||||
if (mBounds == null
|
||||
|| getBounds().right != mBounds.right
|
||||
|| getBounds().left != mBounds.left) {
|
||||
mConcaveInfo.mPath.reset();
|
||||
float left = getBounds().left;
|
||||
float right = getBounds().right;
|
||||
float top = 0f;
|
||||
float bottom = mConcaveInfo.mPathOverlap;
|
||||
mConcaveInfo.mPath.addRoundRect(left, top, right, bottom,
|
||||
mConcaveInfo.mCornerRadii, Path.Direction.CW);
|
||||
mBounds = getBounds();
|
||||
updatePath();
|
||||
}
|
||||
mBounds = getBounds();
|
||||
int translation = (int) (mBounds.bottom - mConcaveInfo.mPathOverlap);
|
||||
canvas.translate(0, translation);
|
||||
canvas.clipOutPath(mConcaveInfo.mPath);
|
||||
canvas.translate(0, -translation);
|
||||
canvas.drawRect(getBounds().left, getBounds().top, getBounds().right,
|
||||
mBottomEdgePosition + mConcaveInfo.mPathOverlap, mPaint);
|
||||
}
|
||||
|
||||
private void updatePath() {
|
||||
mConcaveInfo.mPath.reset();
|
||||
if (mBounds == null) {
|
||||
mBounds = getBounds();
|
||||
}
|
||||
float top = mBottomEdgePosition;
|
||||
float bottom = mBottomEdgePosition + mConcaveInfo.mPathOverlap;
|
||||
mConcaveInfo.mPath.addRoundRect(mBounds.left, top, mBounds.right, bottom,
|
||||
mConcaveInfo.mCornerRadii, Path.Direction.CW);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
* 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.
|
||||
@@ -11,10 +11,10 @@
|
||||
* 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
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.statusbar;
|
||||
package com.android.systemui.scrim;
|
||||
|
||||
import static java.lang.Float.isNaN;
|
||||
|
||||
@@ -38,7 +38,6 @@ import androidx.core.graphics.ColorUtils;
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.colorextraction.ColorExtractor;
|
||||
import com.android.internal.colorextraction.drawable.ScrimDrawable;
|
||||
import com.android.systemui.R;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
@@ -96,6 +95,9 @@ public class ScrimView extends View {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Needed for WM Shell, which has its own thread structure.
|
||||
*/
|
||||
public void setExecutor(Executor executor, Looper looper) {
|
||||
mExecutor = executor;
|
||||
mExecutorLooper = looper;
|
||||
@@ -108,7 +110,8 @@ public class ScrimView extends View {
|
||||
}
|
||||
}
|
||||
|
||||
public void setDrawable(Drawable drawable) {
|
||||
@VisibleForTesting
|
||||
void setDrawable(Drawable drawable) {
|
||||
executeOnExecutor(() -> {
|
||||
mDrawable = drawable;
|
||||
mDrawable.setCallback(this);
|
||||
@@ -144,16 +147,24 @@ public class ScrimView extends View {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color of the scrim, without animating them.
|
||||
*/
|
||||
public void setColors(@NonNull ColorExtractor.GradientColors colors) {
|
||||
setColors(colors, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the scrim colors, optionally animating them.
|
||||
* @param colors The colors.
|
||||
* @param animated If we should animate the transition.
|
||||
*/
|
||||
public void setColors(@NonNull ColorExtractor.GradientColors colors, boolean animated) {
|
||||
if (colors == null) {
|
||||
throw new IllegalArgumentException("Colors cannot be null");
|
||||
}
|
||||
executeOnExecutor(() -> {
|
||||
synchronized(mColorLock) {
|
||||
synchronized (mColorLock) {
|
||||
if (mColors.equals(colors)) {
|
||||
return;
|
||||
}
|
||||
@@ -168,17 +179,28 @@ public class ScrimView extends View {
|
||||
return mDrawable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current scrim colors.
|
||||
*/
|
||||
public ColorExtractor.GradientColors getColors() {
|
||||
synchronized(mColorLock) {
|
||||
synchronized (mColorLock) {
|
||||
mTmpColors.set(mColors);
|
||||
}
|
||||
return mTmpColors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies tint to this view, without animations.
|
||||
*/
|
||||
public void setTint(int color) {
|
||||
setTint(color, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tints this view, optionally animating it.
|
||||
* @param color The color.
|
||||
* @param animated If we should animate.
|
||||
*/
|
||||
public void setTint(int color, boolean animated) {
|
||||
executeOnExecutor(() -> {
|
||||
if (mTintColor == color) {
|
||||
@@ -200,8 +222,8 @@ public class ScrimView extends View {
|
||||
} else {
|
||||
boolean hasAlpha = Color.alpha(mTintColor) != 0;
|
||||
if (hasAlpha) {
|
||||
PorterDuff.Mode targetMode = mColorFilter == null ? Mode.SRC_OVER :
|
||||
mColorFilter.getMode();
|
||||
PorterDuff.Mode targetMode = mColorFilter == null
|
||||
? Mode.SRC_OVER : mColorFilter.getMode();
|
||||
if (mColorFilter == null || mColorFilter.getColor() != mTintColor) {
|
||||
mColorFilter = new PorterDuffColorFilter(mTintColor, targetMode);
|
||||
}
|
||||
@@ -254,6 +276,9 @@ public class ScrimView extends View {
|
||||
return mViewAlpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a callback that is invoked whenever the alpha, color, or tint change.
|
||||
*/
|
||||
public void setChangeRunnable(Runnable changeRunnable, Executor changeRunnableExecutor) {
|
||||
mChangeRunnable = changeRunnable;
|
||||
mChangeRunnableExecutor = changeRunnableExecutor;
|
||||
@@ -276,15 +301,25 @@ public class ScrimView extends View {
|
||||
* Make bottom edge concave so overlap between layers is not visible for alphas between 0 and 1
|
||||
* @return height of concavity
|
||||
*/
|
||||
public float enableBottomEdgeConcave() {
|
||||
public float enableBottomEdgeConcave(boolean clipScrim) {
|
||||
if (mDrawable instanceof ScrimDrawable) {
|
||||
float radius = getResources().getDimensionPixelSize(CORNER_RADIUS);
|
||||
float radius = clipScrim ? getResources().getDimensionPixelSize(CORNER_RADIUS) : 0;
|
||||
((ScrimDrawable) mDrawable).setBottomEdgeConcave(radius);
|
||||
return radius;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The position of the bottom of the scrim, used for clipping.
|
||||
* @see #enableBottomEdgeConcave(boolean)
|
||||
*/
|
||||
public void setBottomEdgePosition(int y) {
|
||||
if (mDrawable instanceof ScrimDrawable) {
|
||||
((ScrimDrawable) mDrawable).setBottomEdgePosition(y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable view to have rounded corners with radius of {@link #CORNER_RADIUS}
|
||||
*/
|
||||
@@ -780,7 +780,7 @@ public class NotificationStackScrollLayoutController {
|
||||
return mView.isLayoutRtl();
|
||||
}
|
||||
|
||||
public float getLeft() {
|
||||
public int getLeft() {
|
||||
return mView.getLeft();
|
||||
}
|
||||
|
||||
|
||||
@@ -515,6 +515,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
private boolean mDelayShowingKeyguardStatusBar;
|
||||
|
||||
private boolean mAnimatingQS;
|
||||
private final Rect mKeyguardStatusAreaClipBounds = new Rect();
|
||||
private int mOldLayoutDirection;
|
||||
private NotificationShelfController mNotificationShelfController;
|
||||
|
||||
@@ -522,6 +523,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
private final Executor mUiExecutor;
|
||||
|
||||
private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
|
||||
private int mScrimCornerRadius;
|
||||
|
||||
private View.AccessibilityDelegate mAccessibilityDelegate = new View.AccessibilityDelegate() {
|
||||
@Override
|
||||
@@ -628,6 +630,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
mDozeParameters = dozeParameters;
|
||||
mBiometricUnlockController = biometricUnlockController;
|
||||
mScrimController = scrimController;
|
||||
mScrimController.setClipsQsScrim(!mShouldUseSplitNotificationShade);
|
||||
mUserManager = userManager;
|
||||
mMediaDataManager = mediaDataManager;
|
||||
mQuickAccessWalletClient = quickAccessWalletClient;
|
||||
@@ -852,10 +855,16 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
public void updateResources() {
|
||||
mSplitShadeNotificationsTopPadding =
|
||||
mResources.getDimensionPixelSize(R.dimen.notifications_top_padding_split_shade);
|
||||
mScrimCornerRadius =
|
||||
mResources.getDimensionPixelSize(R.dimen.notification_scrim_corner_radius);
|
||||
int qsWidth = mResources.getDimensionPixelSize(R.dimen.qs_panel_width);
|
||||
int panelWidth = mResources.getDimensionPixelSize(R.dimen.notification_panel_width);
|
||||
mShouldUseSplitNotificationShade =
|
||||
Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources);
|
||||
mScrimController.setClipsQsScrim(!mShouldUseSplitNotificationShade);
|
||||
if (mQs != null) {
|
||||
mQs.setTranslateWhileExpanding(mShouldUseSplitNotificationShade);
|
||||
}
|
||||
// To change the constraints at runtime, all children of the ConstraintLayout must have ids
|
||||
ensureAllViewsHaveIds(mNotificationContainerParent);
|
||||
ConstraintSet constraintSet = new ConstraintSet();
|
||||
@@ -2003,15 +2012,23 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
mDepthController.setQsPanelExpansion(qsExpansionFraction);
|
||||
}
|
||||
|
||||
private void setNotificationBounds(float qsExpansionFraction, int qsPanelBottomY) {
|
||||
float top = 0;
|
||||
float bottom = 0;
|
||||
float left = 0;
|
||||
float right = 0;
|
||||
if (qsPanelBottomY > 0) {
|
||||
// notification shade is expanding/expanded
|
||||
/**
|
||||
* Updates scrim bounds, QS clipping, and KSV clipping as well based on the bounds of the shade
|
||||
* and QS state.
|
||||
*
|
||||
* @param qsFraction QS expansion fraction, from getQsExpansionFraction().
|
||||
* @param qsPanelBottomY Absolute y position of the bottom of QS as it's being pulled.
|
||||
*/
|
||||
private void setNotificationBounds(float qsFraction, int qsPanelBottomY) {
|
||||
int top = 0;
|
||||
int bottom = 0;
|
||||
int left = 0;
|
||||
int right = 0;
|
||||
boolean visible = qsFraction > 0 || qsPanelBottomY > 0;
|
||||
if (visible || !mShouldUseSplitNotificationShade) {
|
||||
if (!mShouldUseSplitNotificationShade) {
|
||||
top = qsPanelBottomY;
|
||||
float notificationTop = mAmbientState.getStackY() - mQsNotificationTopPadding;
|
||||
top = (int) Math.min(qsPanelBottomY, notificationTop);
|
||||
bottom = getView().getBottom();
|
||||
left = getView().getLeft();
|
||||
right = getView().getRight();
|
||||
@@ -2022,6 +2039,17 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
right = mNotificationStackScrollLayoutController.getRight();
|
||||
}
|
||||
}
|
||||
|
||||
if (!mShouldUseSplitNotificationShade) {
|
||||
// Fancy clipping for quick settings
|
||||
if (mQs != null) {
|
||||
mQs.setFancyClipping(top, bottom, mScrimCornerRadius, visible);
|
||||
}
|
||||
// The padding on this area is large enough that we can use a cheaper clipping strategy
|
||||
mKeyguardStatusAreaClipBounds.set(left, top, right, bottom);
|
||||
mKeyguardStatusViewController.setClipBounds(visible
|
||||
? mKeyguardStatusAreaClipBounds : null);
|
||||
}
|
||||
mScrimController.setNotificationsBounds(left, top, right, bottom);
|
||||
}
|
||||
|
||||
@@ -2493,6 +2521,10 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
float appearAmount = mNotificationStackScrollLayoutController
|
||||
.calculateAppearFraction(mExpandedHeight);
|
||||
float startHeight = -mQsExpansionHeight;
|
||||
if (!mShouldUseSplitNotificationShade && mBarState == StatusBarState.SHADE) {
|
||||
// Small parallax as we pull down and clip QS
|
||||
startHeight = -mQsExpansionHeight * 0.2f;
|
||||
}
|
||||
if (mKeyguardBypassController.getBypassEnabled() && isOnKeyguard()
|
||||
&& mNotificationStackScrollLayoutController.isPulseExpanding()) {
|
||||
if (!mPulseExpansionHandler.isExpanding()
|
||||
@@ -3128,8 +3160,10 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
mQs.setPanelView(mHeightListener);
|
||||
mQs.setExpandClickListener(mOnClickListener);
|
||||
mQs.setHeaderClickable(mQsExpansionEnabled);
|
||||
mQs.setTranslateWhileExpanding(mShouldUseSplitNotificationShade);
|
||||
updateQSPulseExpansion();
|
||||
mQs.setOverscrolling(mStackScrollerOverscrolling);
|
||||
mQs.setTranslateWhileExpanding(mShouldUseSplitNotificationShade);
|
||||
|
||||
// recompute internal state when qspanel height changes
|
||||
mQs.getView().addOnLayoutChangeListener(
|
||||
@@ -3925,7 +3959,10 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
// animate out
|
||||
// the top of QS
|
||||
if (!mQsExpanded) {
|
||||
mQs.animateHeaderSlidingOut();
|
||||
// TODO(b/185683835) Nicer clipping when using new spacial model
|
||||
if (mShouldUseSplitNotificationShade) {
|
||||
mQs.animateHeaderSlidingOut();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mKeyguardStatusBar.setAlpha(1f);
|
||||
|
||||
@@ -147,9 +147,6 @@ public abstract class PanelViewController {
|
||||
private float mInitialTouchX;
|
||||
private boolean mTouchDisabled;
|
||||
|
||||
// AmbientState will never be null since it provides an @Inject constructor for Dagger to call.
|
||||
private AmbientState mAmbientState;
|
||||
|
||||
/**
|
||||
* Whether or not the PanelView can be expanded or collapsed with a drag.
|
||||
*/
|
||||
@@ -172,6 +169,7 @@ public abstract class PanelViewController {
|
||||
protected final Resources mResources;
|
||||
protected final KeyguardStateController mKeyguardStateController;
|
||||
protected final SysuiStatusBarStateController mStatusBarStateController;
|
||||
protected final AmbientState mAmbientState;
|
||||
|
||||
protected void onExpandingFinished() {
|
||||
mBar.onExpandingFinished();
|
||||
|
||||
@@ -48,8 +48,8 @@ import com.android.systemui.R;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.dock.DockManager;
|
||||
import com.android.systemui.scrim.ScrimView;
|
||||
import com.android.systemui.statusbar.FeatureFlags;
|
||||
import com.android.systemui.statusbar.ScrimView;
|
||||
import com.android.systemui.statusbar.notification.stack.ViewState;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
@@ -96,6 +96,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
* When at least 1 scrim is fully opaque (alpha set to 1.)
|
||||
*/
|
||||
public static final int OPAQUE = 2;
|
||||
private boolean mClipsQsScrim;
|
||||
|
||||
@IntDef(prefix = {"VISIBILITY_"}, value = {
|
||||
TRANSPARENT,
|
||||
@@ -165,6 +166,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
// Assuming the shade is expanded during initialization
|
||||
private float mExpansionFraction = 1f;
|
||||
private float mQsExpansion;
|
||||
private boolean mQsBottomVisible;
|
||||
|
||||
private boolean mDarkenWhileDragging;
|
||||
private boolean mExpansionAffectsAlpha = true;
|
||||
@@ -183,6 +185,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
|
||||
private int mInFrontTint;
|
||||
private int mBehindTint;
|
||||
private int mNotificationsTint;
|
||||
private int mBubbleTint;
|
||||
|
||||
private boolean mWallpaperVisibilityTimedOut;
|
||||
@@ -265,6 +268,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
mScrimForBubble = scrimForBubble;
|
||||
updateThemeColors();
|
||||
|
||||
behindScrim.enableBottomEdgeConcave(mClipsQsScrim);
|
||||
mNotificationsScrim.enableRoundedCorners();
|
||||
|
||||
if (mScrimBehindChangeRunnable != null) {
|
||||
@@ -331,14 +335,17 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
|
||||
mInFrontTint = state.getFrontTint();
|
||||
mBehindTint = state.getBehindTint();
|
||||
mNotificationsTint = state.getNotifTint();
|
||||
mBubbleTint = state.getBubbleTint();
|
||||
|
||||
mInFrontAlpha = state.getFrontAlpha();
|
||||
mBehindAlpha = state.getBehindAlpha();
|
||||
mBubbleAlpha = state.getBubbleAlpha();
|
||||
if (isNaN(mBehindAlpha) || isNaN(mInFrontAlpha)) {
|
||||
mNotificationsAlpha = state.getNotifAlpha();
|
||||
if (isNaN(mBehindAlpha) || isNaN(mInFrontAlpha) || isNaN(mNotificationsAlpha)) {
|
||||
throw new IllegalStateException("Scrim opacity is NaN for state: " + state + ", front: "
|
||||
+ mInFrontAlpha + ", back: " + mBehindAlpha);
|
||||
+ mInFrontAlpha + ", back: " + mBehindAlpha + ", notif: "
|
||||
+ mNotificationsAlpha);
|
||||
}
|
||||
applyExpansionToAlpha();
|
||||
|
||||
@@ -397,7 +404,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
scheduleUpdate();
|
||||
}
|
||||
|
||||
dispatchScrimState(mScrimBehind.getViewAlpha());
|
||||
dispatchBackScrimState(mScrimBehind.getViewAlpha());
|
||||
}
|
||||
|
||||
private boolean shouldFadeAwayWallpaper() {
|
||||
@@ -491,21 +498,25 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
*/
|
||||
public void setNotificationsBounds(float left, float top, float right, float bottom) {
|
||||
mNotificationsScrim.setDrawableBounds(left, top, right, bottom);
|
||||
if (mClipsQsScrim) {
|
||||
mScrimBehind.setBottomEdgePosition((int) top);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Current state of the QuickSettings when pulling it from the top.
|
||||
*
|
||||
* @param expansionFraction From 0 to 1 where 0 means collapsed and 1 expanded.
|
||||
* @param qsPanelBottomY absolute Y position of qs panel bottom
|
||||
* @param qsPanelBottomY Absolute Y position of qs panel bottom
|
||||
*/
|
||||
public void setQsPosition(float expansionFraction, int qsPanelBottomY) {
|
||||
if (isNaN(expansionFraction)) {
|
||||
return;
|
||||
}
|
||||
updateNotificationsScrimAlpha(expansionFraction, qsPanelBottomY);
|
||||
if (mQsExpansion != expansionFraction) {
|
||||
boolean qsBottomVisible = qsPanelBottomY > 0;
|
||||
if (mQsExpansion != expansionFraction || mQsBottomVisible != qsBottomVisible) {
|
||||
mQsExpansion = expansionFraction;
|
||||
mQsBottomVisible = qsBottomVisible;
|
||||
boolean relevantState = (mState == ScrimState.SHADE_LOCKED
|
||||
|| mState == ScrimState.KEYGUARD
|
||||
|| mState == ScrimState.PULSING
|
||||
@@ -517,22 +528,26 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNotificationsScrimAlpha(float qsExpansion, int qsPanelBottomY) {
|
||||
float newAlpha = 0;
|
||||
if (qsPanelBottomY > 0) {
|
||||
float interpolator = 0;
|
||||
if (mState == ScrimState.UNLOCKED || mState == ScrimState.SHADE_LOCKED) {
|
||||
interpolator = getInterpolatedFraction();
|
||||
} else {
|
||||
interpolator = qsExpansion;
|
||||
}
|
||||
newAlpha = MathUtils.lerp(0, 1, interpolator);
|
||||
/**
|
||||
* If QS and notification scrims should not overlap, and should be clipped to each other's
|
||||
* bounds instead.
|
||||
*/
|
||||
public void setClipsQsScrim(boolean clipScrim) {
|
||||
if (clipScrim == mClipsQsScrim) {
|
||||
return;
|
||||
}
|
||||
if (newAlpha != mNotificationsAlpha) {
|
||||
mNotificationsAlpha = newAlpha;
|
||||
// update alpha without animating
|
||||
mNotificationsScrim.setViewAlpha(newAlpha);
|
||||
mClipsQsScrim = clipScrim;
|
||||
for (ScrimState state : ScrimState.values()) {
|
||||
state.setClipQsScrim(mClipsQsScrim);
|
||||
}
|
||||
if (mScrimBehind != null) {
|
||||
mScrimBehind.enableBottomEdgeConcave(mClipsQsScrim);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public boolean getClipQsScrim() {
|
||||
return mClipsQsScrim;
|
||||
}
|
||||
|
||||
private void setOrAdaptCurrentAnimation(@Nullable View scrim) {
|
||||
@@ -541,7 +556,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
}
|
||||
|
||||
float alpha = getCurrentScrimAlpha(scrim);
|
||||
if (isAnimating(scrim)) {
|
||||
boolean qsScrimPullingDown = scrim == mScrimBehind && mQsBottomVisible;
|
||||
if (isAnimating(scrim) && !qsScrimPullingDown) {
|
||||
// Adapt current animation.
|
||||
ValueAnimator previousAnimator = (ValueAnimator) scrim.getTag(TAG_KEY_ANIM);
|
||||
float previousEndValue = (Float) scrim.getTag(TAG_END_ALPHA);
|
||||
@@ -562,7 +578,19 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
return;
|
||||
}
|
||||
|
||||
if (mState == ScrimState.UNLOCKED || mState == ScrimState.BUBBLE_EXPANDED) {
|
||||
if (mState == ScrimState.UNLOCKED) {
|
||||
// Darken scrim as you pull down the shade when unlocked
|
||||
float behindFraction = getInterpolatedFraction();
|
||||
behindFraction = (float) Math.pow(behindFraction, 0.8f);
|
||||
if (mClipsQsScrim) {
|
||||
mBehindAlpha = 1;
|
||||
mNotificationsAlpha = behindFraction * mDefaultScrimAlpha;
|
||||
} else {
|
||||
mBehindAlpha = behindFraction * mDefaultScrimAlpha;
|
||||
mNotificationsAlpha = mBehindAlpha;
|
||||
}
|
||||
mInFrontAlpha = 0;
|
||||
} else if (mState == ScrimState.BUBBLE_EXPANDED) {
|
||||
// Darken scrim as you pull down the shade when unlocked
|
||||
float behindFraction = getInterpolatedFraction();
|
||||
behindFraction = (float) Math.pow(behindFraction, 0.8f);
|
||||
@@ -573,27 +601,45 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
// Either darken of make the scrim transparent when you
|
||||
// pull down the shade
|
||||
float interpolatedFract = getInterpolatedFraction();
|
||||
float alphaBehind = mState.getBehindAlpha();
|
||||
float stateBehind = mClipsQsScrim ? mState.getNotifAlpha() : mState.getBehindAlpha();
|
||||
float backAlpha;
|
||||
if (mDarkenWhileDragging) {
|
||||
mBehindAlpha = MathUtils.lerp(mDefaultScrimAlpha, alphaBehind,
|
||||
backAlpha = MathUtils.lerp(mDefaultScrimAlpha, stateBehind,
|
||||
interpolatedFract);
|
||||
mInFrontAlpha = mState.getFrontAlpha();
|
||||
} else {
|
||||
mBehindAlpha = MathUtils.lerp(0 /* start */, alphaBehind,
|
||||
backAlpha = MathUtils.lerp(0 /* start */, stateBehind,
|
||||
interpolatedFract);
|
||||
mInFrontAlpha = mState.getFrontAlpha();
|
||||
}
|
||||
mBehindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(),
|
||||
mState.getBehindTint(), interpolatedFract);
|
||||
mInFrontAlpha = mState.getFrontAlpha();
|
||||
int backTint;
|
||||
if (mClipsQsScrim) {
|
||||
backTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getNotifTint(),
|
||||
mState.getNotifTint(), interpolatedFract);
|
||||
} else {
|
||||
backTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(),
|
||||
mState.getBehindTint(), interpolatedFract);
|
||||
}
|
||||
if (mQsExpansion > 0) {
|
||||
mBehindAlpha = MathUtils.lerp(mBehindAlpha, mDefaultScrimAlpha, mQsExpansion);
|
||||
mBehindTint = ColorUtils.blendARGB(mBehindTint,
|
||||
ScrimState.SHADE_LOCKED.getBehindTint(), mQsExpansion);
|
||||
backAlpha = MathUtils.lerp(backAlpha, mDefaultScrimAlpha, mQsExpansion);
|
||||
int stateTint = mClipsQsScrim ? ScrimState.SHADE_LOCKED.getNotifTint()
|
||||
: ScrimState.SHADE_LOCKED.getBehindTint();
|
||||
backTint = ColorUtils.blendARGB(backTint, stateTint, mQsExpansion);
|
||||
}
|
||||
if (mClipsQsScrim) {
|
||||
mNotificationsAlpha = backAlpha;
|
||||
mNotificationsTint = backTint;
|
||||
mBehindAlpha = 1;
|
||||
mBehindTint = Color.BLACK;
|
||||
} else {
|
||||
mBehindAlpha = backAlpha;
|
||||
mNotificationsAlpha = Math.max(1.0f - getInterpolatedFraction(), mQsExpansion);
|
||||
mBehindTint = backTint;
|
||||
}
|
||||
}
|
||||
if (isNaN(mBehindAlpha) || isNaN(mInFrontAlpha)) {
|
||||
if (isNaN(mBehindAlpha) || isNaN(mInFrontAlpha) || isNaN(mNotificationsAlpha)) {
|
||||
throw new IllegalStateException("Scrim opacity is NaN for state: " + mState
|
||||
+ ", front: " + mInFrontAlpha + ", back: " + mBehindAlpha);
|
||||
+ ", front: " + mInFrontAlpha + ", back: " + mBehindAlpha + ", notif: "
|
||||
+ mNotificationsAlpha);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -606,7 +652,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
setOrAdaptCurrentAnimation(mNotificationsScrim);
|
||||
setOrAdaptCurrentAnimation(mScrimInFront);
|
||||
setOrAdaptCurrentAnimation(mScrimForBubble);
|
||||
dispatchScrimState(mScrimBehind.getViewAlpha());
|
||||
dispatchBackScrimState(mScrimBehind.getViewAlpha());
|
||||
|
||||
// Reset wallpaper timeout if it's already timeout like expanding panel while PULSING
|
||||
// and docking.
|
||||
@@ -693,10 +739,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
&& !mBlankScreen;
|
||||
|
||||
mScrimInFront.setColors(mColors, animateScrimInFront);
|
||||
mScrimBehind.setColors(mColors, animateScrimNotifications);
|
||||
mScrimBehind.setColors(mColors, animateBehindScrim);
|
||||
mNotificationsScrim.setColors(mColors, animateScrimNotifications);
|
||||
|
||||
dispatchScrimState(mScrimBehind.getViewAlpha());
|
||||
dispatchBackScrimState(mScrimBehind.getViewAlpha());
|
||||
}
|
||||
|
||||
// We want to override the back scrim opacity for the AOD state
|
||||
@@ -723,15 +769,21 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
dispatchScrimsVisible();
|
||||
}
|
||||
|
||||
private void dispatchScrimState(float alpha) {
|
||||
private void dispatchBackScrimState(float alpha) {
|
||||
// When clipping QS, the notification scrim is the one that feels behind.
|
||||
// mScrimBehind will be drawing black and its opacity will always be 1.
|
||||
if (mClipsQsScrim && mQsBottomVisible) {
|
||||
alpha = mNotificationsAlpha;
|
||||
}
|
||||
mScrimStateListener.accept(mState, alpha, mScrimInFront.getColors());
|
||||
}
|
||||
|
||||
private void dispatchScrimsVisible() {
|
||||
final ScrimView backScrim = mClipsQsScrim ? mNotificationsScrim : mScrimBehind;
|
||||
final int currentScrimVisibility;
|
||||
if (mScrimInFront.getViewAlpha() == 1 || mScrimBehind.getViewAlpha() == 1) {
|
||||
if (mScrimInFront.getViewAlpha() == 1 || backScrim.getViewAlpha() == 1) {
|
||||
currentScrimVisibility = OPAQUE;
|
||||
} else if (mScrimInFront.getViewAlpha() == 0 && mScrimBehind.getViewAlpha() == 0) {
|
||||
} else if (mScrimInFront.getViewAlpha() == 0 && backScrim.getViewAlpha() == 0) {
|
||||
currentScrimVisibility = TRANSPARENT;
|
||||
} else {
|
||||
currentScrimVisibility = SEMI_TRANSPARENT;
|
||||
@@ -859,7 +911,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
} else if (scrim == mScrimBehind) {
|
||||
return mBehindTint;
|
||||
} else if (scrim == mNotificationsScrim) {
|
||||
return Color.TRANSPARENT;
|
||||
return mNotificationsTint;
|
||||
} else if (scrim == mScrimForBubble) {
|
||||
return mBubbleTint;
|
||||
} else {
|
||||
@@ -917,9 +969,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
if (mState == ScrimState.UNLOCKED) {
|
||||
mInFrontTint = Color.TRANSPARENT;
|
||||
mBehindTint = mState.getBehindTint();
|
||||
mNotificationsTint = mState.getNotifTint();
|
||||
mBubbleTint = Color.TRANSPARENT;
|
||||
updateScrimColor(mScrimInFront, mInFrontAlpha, mInFrontTint);
|
||||
updateScrimColor(mScrimBehind, mBehindAlpha, mBehindTint);
|
||||
updateScrimColor(mNotificationsScrim, mNotificationsAlpha, mNotificationsTint);
|
||||
if (mScrimForBubble != null) {
|
||||
updateScrimColor(mScrimForBubble, mBubbleAlpha, mBubbleTint);
|
||||
}
|
||||
@@ -964,7 +1018,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
}
|
||||
|
||||
if (scrim == mScrimBehind) {
|
||||
dispatchScrimState(alpha);
|
||||
dispatchBackScrimState(alpha);
|
||||
}
|
||||
|
||||
final boolean wantsAlphaUpdate = alpha != currentAlpha;
|
||||
|
||||
@@ -22,7 +22,7 @@ import android.os.Trace;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.systemui.dock.DockManager;
|
||||
import com.android.systemui.statusbar.ScrimView;
|
||||
import com.android.systemui.scrim.ScrimView;
|
||||
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
|
||||
|
||||
/**
|
||||
@@ -80,11 +80,16 @@ public enum ScrimState {
|
||||
}
|
||||
mFrontTint = Color.BLACK;
|
||||
mBehindTint = Color.BLACK;
|
||||
mNotifTint = mClipQsScrim ? Color.BLACK : Color.TRANSPARENT;
|
||||
mBubbleTint = Color.TRANSPARENT;
|
||||
|
||||
mFrontAlpha = 0;
|
||||
mBehindAlpha = mScrimBehindAlphaKeyguard;
|
||||
mBehindAlpha = mClipQsScrim ? 1 : mScrimBehindAlphaKeyguard;
|
||||
mNotifAlpha = mClipQsScrim ? mScrimBehindAlphaKeyguard : 0;
|
||||
mBubbleAlpha = 0;
|
||||
if (mClipQsScrim) {
|
||||
updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -105,7 +110,10 @@ public enum ScrimState {
|
||||
BOUNCER {
|
||||
@Override
|
||||
public void prepare(ScrimState previousState) {
|
||||
mBehindAlpha = mDefaultScrimAlpha;
|
||||
mBehindAlpha = mClipQsScrim ? 1 : mDefaultScrimAlpha;
|
||||
mBehindTint = mClipQsScrim ? Color.BLACK : Color.TRANSPARENT;
|
||||
mNotifAlpha = mClipQsScrim ? mDefaultScrimAlpha : 0;
|
||||
mNotifTint = Color.TRANSPARENT;
|
||||
mFrontAlpha = 0f;
|
||||
mBubbleAlpha = 0f;
|
||||
}
|
||||
@@ -126,10 +134,15 @@ public enum ScrimState {
|
||||
SHADE_LOCKED {
|
||||
@Override
|
||||
public void prepare(ScrimState previousState) {
|
||||
mBehindAlpha = mDefaultScrimAlpha;
|
||||
mBehindAlpha = mClipQsScrim ? 1 : mDefaultScrimAlpha;
|
||||
mNotifAlpha = 1f;
|
||||
mBubbleAlpha = 0f;
|
||||
mFrontAlpha = 0f;
|
||||
mBehindTint = Color.BLACK;
|
||||
|
||||
if (mClipQsScrim) {
|
||||
updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
// to make sure correct color is returned before "prepare" is called
|
||||
@@ -224,7 +237,8 @@ public enum ScrimState {
|
||||
@Override
|
||||
public void prepare(ScrimState previousState) {
|
||||
// State that UI will sync to.
|
||||
mBehindAlpha = 0;
|
||||
mBehindAlpha = mClipQsScrim ? 1 : 0;
|
||||
mNotifAlpha = 0;
|
||||
mFrontAlpha = 0;
|
||||
mBubbleAlpha = 0;
|
||||
|
||||
@@ -253,6 +267,10 @@ public enum ScrimState {
|
||||
mBubbleTint = Color.BLACK;
|
||||
mBlankScreen = true;
|
||||
}
|
||||
|
||||
if (mClipQsScrim) {
|
||||
updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -279,12 +297,14 @@ public enum ScrimState {
|
||||
int mFrontTint = Color.TRANSPARENT;
|
||||
int mBehindTint = Color.TRANSPARENT;
|
||||
int mBubbleTint = Color.TRANSPARENT;
|
||||
int mNotifTint = Color.TRANSPARENT;
|
||||
|
||||
boolean mAnimateChange = true;
|
||||
float mAodFrontScrimAlpha;
|
||||
float mFrontAlpha;
|
||||
float mBehindAlpha;
|
||||
float mBubbleAlpha;
|
||||
float mNotifAlpha;
|
||||
|
||||
float mScrimBehindAlphaKeyguard;
|
||||
float mDefaultScrimAlpha;
|
||||
@@ -301,6 +321,7 @@ public enum ScrimState {
|
||||
boolean mWakeLockScreenSensorActive;
|
||||
boolean mKeyguardFadingAway;
|
||||
long mKeyguardFadingAwayDuration;
|
||||
boolean mClipQsScrim;
|
||||
|
||||
public void init(ScrimView scrimInFront, ScrimView scrimBehind, ScrimView scrimForBubble,
|
||||
DozeParameters dozeParameters, DockManager dockManager) {
|
||||
@@ -325,6 +346,10 @@ public enum ScrimState {
|
||||
return mBehindAlpha;
|
||||
}
|
||||
|
||||
public float getNotifAlpha() {
|
||||
return mNotifAlpha;
|
||||
}
|
||||
|
||||
public float getBubbleAlpha() {
|
||||
return mBubbleAlpha;
|
||||
}
|
||||
@@ -337,6 +362,10 @@ public enum ScrimState {
|
||||
return mBehindTint;
|
||||
}
|
||||
|
||||
public int getNotifTint() {
|
||||
return mNotifTint;
|
||||
}
|
||||
|
||||
public int getBubbleTint() {
|
||||
return mBubbleTint;
|
||||
}
|
||||
@@ -406,4 +435,8 @@ public enum ScrimState {
|
||||
mKeyguardFadingAway = fadingAway;
|
||||
mKeyguardFadingAwayDuration = duration;
|
||||
}
|
||||
|
||||
public void setClipQsScrim(boolean clipsQsScrim) {
|
||||
mClipQsScrim = clipsQsScrim;
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,6 @@ import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
|
||||
import static android.app.StatusBarManager.WindowType;
|
||||
import static android.app.StatusBarManager.WindowVisibleState;
|
||||
import static android.app.StatusBarManager.windowStateToString;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
|
||||
import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
|
||||
import static android.view.InsetsState.ITYPE_STATUS_BAR;
|
||||
import static android.view.InsetsState.containsType;
|
||||
@@ -180,6 +179,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.qs.QSFragment;
|
||||
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.shared.plugins.PluginManager;
|
||||
import com.android.systemui.statusbar.AutoHideUiElement;
|
||||
@@ -202,7 +202,6 @@ import com.android.systemui.statusbar.NotificationShelfController;
|
||||
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
|
||||
import com.android.systemui.statusbar.PowerButtonReveal;
|
||||
import com.android.systemui.statusbar.PulseExpansionHandler;
|
||||
import com.android.systemui.statusbar.ScrimView;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
import com.android.systemui.statusbar.SuperStatusBarViewFactory;
|
||||
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||
|
||||
@@ -63,11 +63,11 @@ import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.dump.DumpManager;
|
||||
import com.android.systemui.model.SysUiState;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.scrim.ScrimView;
|
||||
import com.android.systemui.shared.system.QuickStepContract;
|
||||
import com.android.systemui.statusbar.FeatureFlags;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||
import com.android.systemui.statusbar.ScrimView;
|
||||
import com.android.systemui.statusbar.notification.NotificationChannelHelper;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryListener;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
* 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.
|
||||
@@ -11,10 +11,10 @@
|
||||
* 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
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.statusbar;
|
||||
package com.android.systemui.scrim;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
|
||||
@@ -31,7 +31,6 @@ import android.view.View;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.colorextraction.ColorExtractor;
|
||||
import com.android.internal.colorextraction.drawable.ScrimDrawable;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.utils.leaks.LeakCheckedTest;
|
||||
|
||||
@@ -49,8 +49,8 @@ import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.systemui.DejankUtils;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.dock.DockManager;
|
||||
import com.android.systemui.scrim.ScrimView;
|
||||
import com.android.systemui.statusbar.FeatureFlags;
|
||||
import com.android.systemui.statusbar.ScrimView;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
import com.android.systemui.util.concurrency.FakeExecutor;
|
||||
@@ -69,6 +69,7 @@ import org.mockito.stubbing.Answer;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -91,7 +92,7 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private AlarmManager mAlarmManager;
|
||||
@Mock
|
||||
private DozeParameters mDozeParamenters;
|
||||
private DozeParameters mDozeParameters;
|
||||
@Mock
|
||||
LightBarController mLightBarController;
|
||||
@Mock
|
||||
@@ -200,8 +201,8 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
return null;
|
||||
}).when(mScrimBehind).postOnAnimationDelayed(any(Runnable.class), anyLong());
|
||||
|
||||
when(mDozeParamenters.getAlwaysOn()).thenAnswer(invocation -> mAlwaysOnEnabled);
|
||||
when(mDozeParamenters.getDisplayNeedsBlanking()).thenReturn(true);
|
||||
when(mDozeParameters.getAlwaysOn()).thenAnswer(invocation -> mAlwaysOnEnabled);
|
||||
when(mDozeParameters.getDisplayNeedsBlanking()).thenReturn(true);
|
||||
|
||||
doAnswer((Answer<Void>) invocation -> {
|
||||
mScrimState = invocation.getArgument(0);
|
||||
@@ -220,7 +221,7 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
when(mDockManager.isDocked()).thenReturn(false);
|
||||
|
||||
mScrimController = new ScrimController(mLightBarController,
|
||||
mDozeParamenters, mAlarmManager, mKeyguardStateController, mDelayedWakeLockBuilder,
|
||||
mDozeParameters, mAlarmManager, mKeyguardStateController, mDelayedWakeLockBuilder,
|
||||
new FakeHandler(mLooper.getLooper()), mKeyguardUpdateMonitor,
|
||||
mDockManager, mConfigurationController, mFeatureFlags,
|
||||
new FakeExecutor(new FakeSystemClock()));
|
||||
@@ -238,6 +239,10 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
@After
|
||||
public void tearDown() {
|
||||
finishAnimationsImmediately();
|
||||
Arrays.stream(ScrimState.values()).forEach((scrim) -> {
|
||||
scrim.setAodFrontScrimAlpha(0f);
|
||||
scrim.setClipQsScrim(false);
|
||||
});
|
||||
DejankUtils.setImmediate(false);
|
||||
}
|
||||
|
||||
@@ -259,9 +264,30 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void transitionToShadeLocked() {
|
||||
mScrimController.transitionTo(ScrimState.SHADE_LOCKED);
|
||||
mScrimController.setQsPosition(1f, 0);
|
||||
finishAnimationsImmediately();
|
||||
|
||||
assertScrimAlpha(Map.of(
|
||||
mNotificationsScrim, OPAQUE,
|
||||
mScrimInFront, TRANSPARENT,
|
||||
mScrimBehind, OPAQUE));
|
||||
|
||||
assertScrimTinted(Map.of(
|
||||
mScrimInFront, false,
|
||||
mScrimBehind, true,
|
||||
mScrimForBubble, false
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transitionToShadeLocked_clippingQs() {
|
||||
mScrimController.setClipsQsScrim(true);
|
||||
mScrimController.transitionTo(ScrimState.SHADE_LOCKED);
|
||||
mScrimController.setQsPosition(1f, 0);
|
||||
finishAnimationsImmediately();
|
||||
|
||||
assertScrimAlpha(Map.of(
|
||||
mNotificationsScrim, OPAQUE,
|
||||
mScrimInFront, TRANSPARENT,
|
||||
mScrimBehind, OPAQUE));
|
||||
|
||||
@@ -403,9 +429,6 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
mScrimController.setAodFrontScrimAlpha(0.3f);
|
||||
Assert.assertEquals(ScrimState.AOD.getFrontAlpha(), mScrimInFront.getViewAlpha(), 0.001f);
|
||||
Assert.assertNotEquals(0.3f, mScrimInFront.getViewAlpha(), 0.001f);
|
||||
|
||||
// Reset value since enums are static.
|
||||
mScrimController.setAodFrontScrimAlpha(0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -500,11 +523,34 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
// Back scrim should be visible without tint
|
||||
assertScrimAlpha(Map.of(
|
||||
mScrimInFront, TRANSPARENT,
|
||||
mNotificationsScrim, TRANSPARENT,
|
||||
mScrimBehind, OPAQUE));
|
||||
|
||||
assertScrimTinted(Map.of(
|
||||
mScrimInFront, false,
|
||||
mScrimBehind, false,
|
||||
mNotificationsScrim, false,
|
||||
mScrimForBubble, false
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transitionToKeyguardBouncer_clippingQs() {
|
||||
mScrimController.setClipsQsScrim(true);
|
||||
mScrimController.transitionTo(ScrimState.BOUNCER);
|
||||
finishAnimationsImmediately();
|
||||
// Front scrim should be transparent
|
||||
// Back scrim should be clipping QS
|
||||
// Notif scrim should be visible without tint
|
||||
assertScrimAlpha(Map.of(
|
||||
mScrimInFront, TRANSPARENT,
|
||||
mNotificationsScrim, OPAQUE,
|
||||
mScrimBehind, OPAQUE));
|
||||
|
||||
assertScrimTinted(Map.of(
|
||||
mScrimInFront, false,
|
||||
mScrimBehind, true,
|
||||
mNotificationsScrim, false,
|
||||
mScrimForBubble, false
|
||||
));
|
||||
}
|
||||
@@ -530,9 +576,11 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
finishAnimationsImmediately();
|
||||
assertScrimAlpha(Map.of(
|
||||
mScrimInFront, TRANSPARENT,
|
||||
mNotificationsScrim, TRANSPARENT,
|
||||
mScrimBehind, TRANSPARENT));
|
||||
|
||||
assertScrimTinted(Map.of(
|
||||
mNotificationsScrim, false,
|
||||
mScrimInFront, false,
|
||||
mScrimBehind, true,
|
||||
mScrimForBubble, false
|
||||
@@ -542,6 +590,7 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
mScrimController.setPanelExpansion(0.5f);
|
||||
assertScrimAlpha(Map.of(
|
||||
mScrimInFront, TRANSPARENT,
|
||||
mNotificationsScrim, SEMI_TRANSPARENT,
|
||||
mScrimBehind, SEMI_TRANSPARENT));
|
||||
}
|
||||
|
||||
@@ -616,6 +665,32 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
mNotificationsScrim, OPAQUE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void qsExpansion_clippingQs() {
|
||||
reset(mScrimBehind);
|
||||
mScrimController.setClipsQsScrim(true);
|
||||
mScrimController.setQsPosition(1f, 999 /* value doesn't matter */);
|
||||
finishAnimationsImmediately();
|
||||
|
||||
assertScrimAlpha(Map.of(
|
||||
mScrimInFront, TRANSPARENT,
|
||||
mScrimBehind, OPAQUE,
|
||||
mNotificationsScrim, OPAQUE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void qsExpansion_half_clippingQs() {
|
||||
reset(mScrimBehind);
|
||||
mScrimController.setClipsQsScrim(true);
|
||||
mScrimController.setQsPosition(0.5f, 999 /* value doesn't matter */);
|
||||
finishAnimationsImmediately();
|
||||
|
||||
assertScrimAlpha(Map.of(
|
||||
mScrimInFront, TRANSPARENT,
|
||||
mScrimBehind, OPAQUE,
|
||||
mNotificationsScrim, SEMI_TRANSPARENT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void panelExpansionAffectsAlpha() {
|
||||
mScrimController.setPanelExpansion(0f);
|
||||
@@ -919,13 +994,13 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testAnimatesTransitionToAod() {
|
||||
when(mDozeParamenters.shouldControlScreenOff()).thenReturn(false);
|
||||
when(mDozeParameters.shouldControlScreenOff()).thenReturn(false);
|
||||
ScrimState.AOD.prepare(ScrimState.KEYGUARD);
|
||||
Assert.assertFalse("No animation when ColorFade kicks in",
|
||||
ScrimState.AOD.getAnimateChange());
|
||||
|
||||
reset(mDozeParamenters);
|
||||
when(mDozeParamenters.shouldControlScreenOff()).thenReturn(true);
|
||||
reset(mDozeParameters);
|
||||
when(mDozeParameters.shouldControlScreenOff()).thenReturn(true);
|
||||
ScrimState.AOD.prepare(ScrimState.KEYGUARD);
|
||||
Assert.assertTrue("Animate scrims when ColorFade won't be triggered",
|
||||
ScrimState.AOD.getAnimateChange());
|
||||
@@ -977,6 +1052,7 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
mScrimController.setPanelExpansion(0.5f);
|
||||
// notifications scrim alpha change require calling setQsPosition
|
||||
mScrimController.setQsPosition(0, 300);
|
||||
finishAnimationsImmediately();
|
||||
|
||||
assertScrimAlpha(Map.of(
|
||||
mScrimBehind, SEMI_TRANSPARENT,
|
||||
@@ -984,6 +1060,21 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
mScrimInFront, TRANSPARENT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScrimsVisible_whenShadeVisible_clippingQs() {
|
||||
mScrimController.setClipsQsScrim(true);
|
||||
mScrimController.transitionTo(ScrimState.UNLOCKED);
|
||||
mScrimController.setPanelExpansion(0.5f);
|
||||
// notifications scrim alpha change require calling setQsPosition
|
||||
mScrimController.setQsPosition(0.5f, 300);
|
||||
finishAnimationsImmediately();
|
||||
|
||||
assertScrimAlpha(Map.of(
|
||||
mScrimBehind, OPAQUE,
|
||||
mNotificationsScrim, SEMI_TRANSPARENT,
|
||||
mScrimInFront, TRANSPARENT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScrimsVisible_whenShadeVisibleOnLockscreen() {
|
||||
mScrimController.transitionTo(ScrimState.KEYGUARD);
|
||||
@@ -1008,8 +1099,6 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
private void assertScrimTinted(Map<ScrimView, Boolean> scrimToTint) {
|
||||
// notifications scrim should have always transparent tint
|
||||
assertScrimTint(mNotificationsScrim, false);
|
||||
scrimToTint.forEach((scrim, hasTint) -> assertScrimTint(scrim, hasTint));
|
||||
}
|
||||
|
||||
@@ -1047,6 +1136,12 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
}
|
||||
scrimToAlpha.forEach((scrimView, alpha) -> assertScrimAlpha(scrimView, alpha));
|
||||
|
||||
// When clipping, QS scrim should not affect combined visibility.
|
||||
if (mScrimController.getClipQsScrim() && scrimToAlpha.get(mScrimBehind) == OPAQUE) {
|
||||
scrimToAlpha = new HashMap<>(scrimToAlpha);
|
||||
scrimToAlpha.remove(mScrimBehind);
|
||||
}
|
||||
|
||||
// Check combined scrim visibility.
|
||||
final int visibility;
|
||||
if (scrimToAlpha.values().contains(OPAQUE)) {
|
||||
|
||||
Reference in New Issue
Block a user