From bdf75772ea2bfd60f004a5d326478bd83deda9a0 Mon Sep 17 00:00:00 2001 From: Pinyao Ting Date: Tue, 16 May 2023 22:43:45 +0000 Subject: [PATCH 01/11] Revert "Grant Launcher permission to access AppSearch" This reverts commit 0bae1f55e3fa32380298297201f46e0ad31dd3a8. Reason for revert: no product dependencies and it's causing problems in automation tests Bug: 283006437 Test: NexusLauncherTests:com.android.quickstep.FallbackRecentsTest Change-Id: I831e563c41a368d981af3a05063bf3a868c24b79 Merged-In: I831e563c41a368d981af3a05063bf3a868c24b79 --- AndroidManifest-common.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml index 0c7b48fe66..60ddfb6ce5 100644 --- a/AndroidManifest-common.xml +++ b/AndroidManifest-common.xml @@ -44,7 +44,6 @@ - + xmlns:launcher="http://schemas.android.com/apk/res-auto"> @@ -73,7 +71,6 @@ android:layout_height="match_parent" android:id="@+id/suggestions_header" android:layout_marginTop="8dp" - android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin_two_pane" android:orientation="horizontal" android:background="?attr/widgetPickerPrimarySurfaceColor" launcher:layout_sticky="true"> @@ -86,7 +83,6 @@ android:gravity="center_horizontal" android:orientation="horizontal" android:paddingVertical="8dp" - android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin_two_pane" android:background="?attr/widgetPickerPrimarySurfaceColor" style="@style/TextHeadline" launcher:layout_sticky="true"> diff --git a/res/layout/widgets_two_pane_sheet_recyclerview.xml b/res/layout/widgets_two_pane_sheet_recyclerview.xml index f8d72e89d4..c9c855c48d 100644 --- a/res/layout/widgets_two_pane_sheet_recyclerview.xml +++ b/res/layout/widgets_two_pane_sheet_recyclerview.xml @@ -13,8 +13,7 @@ limitations under the License. --> + xmlns:launcher="http://schemas.android.com/apk/res-auto"> Date: Thu, 18 May 2023 10:35:16 -0700 Subject: [PATCH 07/11] Update BorderAnimator to work with layout updates 1. if a 'ViewScaleTargetProvider' is being used, this can cause a crash 2. otherwise, the old border bounds are reapplied, which is likely no longer correct Updated BorderAnimator to use 'BorderAnimationParams' rather than 'ViewScaleTargetProvider'. This removes some unnecessary null checks while making the util class simpler to use. It also allows us to listen for specific view events for the border animation. Flag: ENABLE_KEYBOARD_QUICK_SWITCH Fixes: 283272516 Test: opened the keyboard quick switch view and highlighted a view in recents view, then rotated the screen several times Change-Id: I7959d6cd892ebcdd2c68163dd56c358815494af6 --- .../taskbar/KeyboardQuickSwitchTaskView.java | 53 +-- .../quickstep/util/BorderAnimator.java | 304 +++++++++++------- .../com/android/quickstep/views/TaskView.java | 9 +- 3 files changed, 220 insertions(+), 146 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java index 08857b7f94..8a11b57c11 100644 --- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java +++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java @@ -27,11 +27,13 @@ import android.util.AttributeSet; import android.view.View; import android.widget.ImageView; +import androidx.annotation.ColorInt; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.constraintlayout.widget.ConstraintLayout; import com.android.launcher3.R; +import com.android.launcher3.util.Preconditions; import com.android.quickstep.util.BorderAnimator; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; @@ -43,7 +45,9 @@ import java.util.function.Consumer; */ public class KeyboardQuickSwitchTaskView extends ConstraintLayout { - @NonNull private final BorderAnimator mBorderAnimator; + @ColorInt private final int mBorderColor; + + @Nullable private BorderAnimator mBorderAnimator; @Nullable private ImageView mThumbnailView1; @Nullable private ImageView mThumbnailView2; @@ -74,29 +78,9 @@ public class KeyboardQuickSwitchTaskView extends ConstraintLayout { attrs, R.styleable.TaskView, defStyleAttr, defStyleRes); setWillNotDraw(false); - Resources resources = context.getResources(); - mBorderAnimator = new BorderAnimator( - /* borderBoundsBuilder= */ bounds -> bounds.set(0, 0, getWidth(), getHeight()), - /* borderWidthPx= */ resources.getDimensionPixelSize( - R.dimen.keyboard_quick_switch_border_width), - /* borderRadiusPx= */ resources.getDimensionPixelSize( - R.dimen.keyboard_quick_switch_task_view_radius), - /* borderColor= */ ta.getColor( - R.styleable.TaskView_borderColor, DEFAULT_BORDER_COLOR), - /* invalidateViewCallback= */ KeyboardQuickSwitchTaskView.this::invalidate, - /* viewScaleTargetProvider= */ new BorderAnimator.ViewScaleTargetProvider() { - @NonNull - @Override - public View getContainerView() { - return KeyboardQuickSwitchTaskView.this; - } - @NonNull - @Override - public View getContentView() { - return mContent; - } - }); + mBorderColor = ta.getColor( + R.styleable.TaskView_borderColor, DEFAULT_BORDER_COLOR); ta.recycle(); } @@ -108,17 +92,34 @@ public class KeyboardQuickSwitchTaskView extends ConstraintLayout { mIcon1 = findViewById(R.id.icon1); mIcon2 = findViewById(R.id.icon2); mContent = findViewById(R.id.content); + + Resources resources = mContext.getResources(); + + Preconditions.assertNotNull(mContent); + mBorderAnimator = new BorderAnimator( + /* borderRadiusPx= */ resources.getDimensionPixelSize( + R.dimen.keyboard_quick_switch_task_view_radius), + /* borderColor= */ mBorderColor, + /* borderAnimationParams= */ new BorderAnimator.ScalingParams( + /* borderWidthPx= */ resources.getDimensionPixelSize( + R.dimen.keyboard_quick_switch_border_width), + /* boundsBuilder= */ bounds -> bounds.set( + 0, 0, getWidth(), getHeight()), + /* targetView= */ this, + /* contentView= */ mContent)); } - @NonNull + @Nullable protected Animator getFocusAnimator(boolean focused) { - return mBorderAnimator.buildAnimator(focused); + return mBorderAnimator == null ? null : mBorderAnimator.buildAnimator(focused); } @Override public void draw(Canvas canvas) { super.draw(canvas); - mBorderAnimator.drawBorder(canvas); + if (mBorderAnimator != null) { + mBorderAnimator.drawBorder(canvas); + } } protected void setThumbnails( diff --git a/quickstep/src/com/android/quickstep/util/BorderAnimator.java b/quickstep/src/com/android/quickstep/util/BorderAnimator.java index c43fb27f05..011d45c8e7 100644 --- a/quickstep/src/com/android/quickstep/util/BorderAnimator.java +++ b/quickstep/src/com/android/quickstep/util/BorderAnimator.java @@ -20,6 +20,7 @@ import android.animation.AnimatorListenerAdapter; import android.annotation.ColorInt; import android.annotation.Nullable; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.view.View; @@ -37,8 +38,8 @@ import com.android.launcher3.anim.Interpolators; *

* To use this class: * 1. Create an instance in the target view. NOTE: The border will animate outwards from the - * provided border bounds. If the border will not be visible outside of those bounds, then a - * {@link ViewScaleTargetProvider} must be provided in the constructor. + * provided border bounds. See {@link SimpleParams} and {@link ScalingParams} to determine + * which would be best for your target view. * 2. Override the target view's {@link android.view.View#draw(Canvas)} method and call * {@link BorderAnimator#drawBorder(Canvas)} after {@code super.draw(canvas)}. * 3. Call {@link BorderAnimator#buildAnimator(boolean)} and start the animation or call @@ -46,7 +47,7 @@ import com.android.launcher3.anim.Interpolators; */ public final class BorderAnimator { - public static final int DEFAULT_BORDER_COLOR = 0xffffffff; + public static final int DEFAULT_BORDER_COLOR = Color.WHITE; private static final long DEFAULT_APPEARANCE_ANIMATION_DURATION_MS = 300; private static final long DEFAULT_DISAPPEARANCE_ANIMATION_DURATION_MS = 133; @@ -54,68 +55,44 @@ public final class BorderAnimator { @NonNull private final AnimatedFloat mBorderAnimationProgress = new AnimatedFloat( this::updateOutline); - @NonNull private final Rect mBorderBounds = new Rect(); - @NonNull private final BorderBoundsBuilder mBorderBoundsBuilder; - @Px private final int mBorderWidthPx; @Px private final int mBorderRadiusPx; - @NonNull private final Runnable mInvalidateViewCallback; - @Nullable private final ViewScaleTargetProvider mViewScaleTargetProvider; + @NonNull private final BorderAnimationParams mBorderAnimationParams; private final long mAppearanceDurationMs; private final long mDisappearanceDurationMs; @NonNull private final Interpolator mInterpolator; @NonNull private final Paint mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - private float mAlignmentAdjustment; - @Nullable private Animator mRunningBorderAnimation; public BorderAnimator( - @NonNull BorderBoundsBuilder borderBoundsBuilder, - int borderWidthPx, - int borderRadiusPx, + @Px int borderRadiusPx, @ColorInt int borderColor, - @NonNull Runnable invalidateViewCallback) { - this(borderBoundsBuilder, - borderWidthPx, - borderRadiusPx, + @NonNull BorderAnimationParams borderAnimationParams) { + this(borderRadiusPx, borderColor, - invalidateViewCallback, - /* viewScaleTargetProvider= */ null); - } - - public BorderAnimator( - @NonNull BorderBoundsBuilder borderBoundsBuilder, - int borderWidthPx, - int borderRadiusPx, - @ColorInt int borderColor, - @NonNull Runnable invalidateViewCallback, - @Nullable ViewScaleTargetProvider viewScaleTargetProvider) { - this(borderBoundsBuilder, - borderWidthPx, - borderRadiusPx, - borderColor, - invalidateViewCallback, - viewScaleTargetProvider, + borderAnimationParams, DEFAULT_APPEARANCE_ANIMATION_DURATION_MS, DEFAULT_DISAPPEARANCE_ANIMATION_DURATION_MS, DEFAULT_INTERPOLATOR); } + /** + * @param borderRadiusPx the radius of the border's corners, in pixels + * @param borderColor the border's color + * @param borderAnimationParams params for handling different target view layout situation. + * @param appearanceDurationMs appearance animation duration, in milliseconds + * @param disappearanceDurationMs disappearance animation duration, in milliseconds + * @param interpolator animation interpolator + */ public BorderAnimator( - @NonNull BorderBoundsBuilder borderBoundsBuilder, - int borderWidthPx, - int borderRadiusPx, + @Px int borderRadiusPx, @ColorInt int borderColor, - @NonNull Runnable invalidateViewCallback, - @Nullable ViewScaleTargetProvider viewScaleTargetProvider, + @NonNull BorderAnimationParams borderAnimationParams, long appearanceDurationMs, long disappearanceDurationMs, @NonNull Interpolator interpolator) { - mBorderBoundsBuilder = borderBoundsBuilder; - mBorderWidthPx = borderWidthPx; mBorderRadiusPx = borderRadiusPx; - mInvalidateViewCallback = invalidateViewCallback; - mViewScaleTargetProvider = viewScaleTargetProvider; + mBorderAnimationParams = borderAnimationParams; mAppearanceDurationMs = appearanceDurationMs; mDisappearanceDurationMs = disappearanceDurationMs; mInterpolator = interpolator; @@ -128,15 +105,11 @@ public final class BorderAnimator { private void updateOutline() { float interpolatedProgress = mInterpolator.getInterpolation( mBorderAnimationProgress.value); - float borderWidth = mBorderWidthPx * interpolatedProgress; - // Outset the border by half the width to create an outwards-growth animation - mAlignmentAdjustment = (-borderWidth / 2f) - // Inset the border if we are scaling the container up - + (mViewScaleTargetProvider == null ? 0 : mBorderWidthPx); + mBorderAnimationParams.setProgress(interpolatedProgress); mBorderPaint.setAlpha(Math.round(255 * interpolatedProgress)); - mBorderPaint.setStrokeWidth(borderWidth); - mInvalidateViewCallback.run(); + mBorderPaint.setStrokeWidth(mBorderAnimationParams.getBorderWidth()); + mBorderAnimationParams.mTargetView.invalidate(); } /** @@ -146,16 +119,14 @@ public final class BorderAnimator { * calling super. */ public void drawBorder(Canvas canvas) { - // Increase the radius if we are scaling the container up - float radiusAdjustment = mViewScaleTargetProvider == null - ? -mAlignmentAdjustment : mAlignmentAdjustment; + float alignmentAdjustment = mBorderAnimationParams.getAlignmentAdjustment(); canvas.drawRoundRect( - /* left= */ mBorderBounds.left + mAlignmentAdjustment, - /* top= */ mBorderBounds.top + mAlignmentAdjustment, - /* right= */ mBorderBounds.right - mAlignmentAdjustment, - /* bottom= */ mBorderBounds.bottom - mAlignmentAdjustment, - /* rx= */ mBorderRadiusPx + radiusAdjustment, - /* ry= */ mBorderRadiusPx + radiusAdjustment, + /* left= */ mBorderAnimationParams.mBorderBounds.left + alignmentAdjustment, + /* top= */ mBorderAnimationParams.mBorderBounds.top + alignmentAdjustment, + /* right= */ mBorderAnimationParams.mBorderBounds.right - alignmentAdjustment, + /* bottom= */ mBorderAnimationParams.mBorderBounds.bottom - alignmentAdjustment, + /* rx= */ mBorderRadiusPx + mBorderAnimationParams.getRadiusAdjustment(), + /* ry= */ mBorderRadiusPx + mBorderAnimationParams.getRadiusAdjustment(), /* paint= */ mBorderPaint); } @@ -164,7 +135,6 @@ public final class BorderAnimator { */ @NonNull public Animator buildAnimator(boolean isAppearing) { - mBorderBoundsBuilder.updateBorderBounds(mBorderBounds); mRunningBorderAnimation = mBorderAnimationProgress.animateToValue(isAppearing ? 1f : 0f); mRunningBorderAnimation.setDuration( isAppearing ? mAppearanceDurationMs : mDisappearanceDurationMs); @@ -172,7 +142,7 @@ public final class BorderAnimator { mRunningBorderAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { - setViewScales(); + mBorderAnimationParams.onShowBorder(); } }); mRunningBorderAnimation.addListener( @@ -181,7 +151,7 @@ public final class BorderAnimator { if (isAppearing) { return; } - resetViewScales(); + mBorderAnimationParams.onHideBorder(); })); return mRunningBorderAnimation; @@ -196,56 +166,15 @@ public final class BorderAnimator { if (mRunningBorderAnimation != null) { mRunningBorderAnimation.end(); } - mBorderBoundsBuilder.updateBorderBounds(mBorderBounds); if (visible) { - setViewScales(); + mBorderAnimationParams.onShowBorder(); } mBorderAnimationProgress.updateValue(visible ? 1f : 0f); if (!visible) { - resetViewScales(); + mBorderAnimationParams.onHideBorder(); } } - private void setViewScales() { - if (mViewScaleTargetProvider == null) { - return; - } - View container = mViewScaleTargetProvider.getContainerView(); - float width = container.getWidth(); - float height = container.getHeight(); - // scale up just enough to make room for the border - float scaleX = 1f + ((2 * mBorderWidthPx) / width); - float scaleY = 1f + ((2 * mBorderWidthPx) / height); - - container.setPivotX(width / 2); - container.setPivotY(height / 2); - container.setScaleX(scaleX); - container.setScaleY(scaleY); - - View contentView = mViewScaleTargetProvider.getContentView(); - contentView.setPivotX(contentView.getWidth() / 2f); - contentView.setPivotY(contentView.getHeight() / 2f); - contentView.setScaleX(1f / scaleX); - contentView.setScaleY(1f / scaleY); - } - - private void resetViewScales() { - if (mViewScaleTargetProvider == null) { - return; - } - View container = mViewScaleTargetProvider.getContainerView(); - container.setPivotX(container.getWidth()); - container.setPivotY(container.getHeight()); - container.setScaleX(1f); - container.setScaleY(1f); - - View contentView = mViewScaleTargetProvider.getContentView(); - contentView.setPivotX(contentView.getWidth() / 2f); - contentView.setPivotY(contentView.getHeight() / 2f); - contentView.setScaleX(1f); - contentView.setScaleY(1f); - } - /** * Callback to update the border bounds when building this animation. */ @@ -258,23 +187,166 @@ public final class BorderAnimator { } /** - * Provider for scaling target views for the beginning and end of this animation. + * Params for handling different target view layout situation. */ - public interface ViewScaleTargetProvider { + private abstract static class BorderAnimationParams { + + @NonNull private final Rect mBorderBounds = new Rect(); + @NonNull private final BorderBoundsBuilder mBoundsBuilder; + + @NonNull final View mTargetView; + @Px final int mBorderWidthPx; + + private float mAnimationProgress = 0f; + @Nullable private View.OnLayoutChangeListener mLayoutChangeListener; /** - * Returns the content view's container. This view will be scaled up to make room for the - * border. + * @param borderWidthPx the width of the border, in pixels + * @param boundsBuilder callback to update the border bounds + * @param targetView the view that will be drawing the border */ - @NonNull - View getContainerView(); + private BorderAnimationParams( + @Px int borderWidthPx, + @NonNull BorderBoundsBuilder boundsBuilder, + @NonNull View targetView) { + mBorderWidthPx = borderWidthPx; + mBoundsBuilder = boundsBuilder; + mTargetView = targetView; + } + + private void setProgress(float progress) { + mAnimationProgress = progress; + } + + private float getBorderWidth() { + return mBorderWidthPx * mAnimationProgress; + } + + float getAlignmentAdjustment() { + // Outset the border by half the width to create an outwards-growth animation + return (-getBorderWidth() / 2f) + getAlignmentAdjustmentInset(); + } + + + void onShowBorder() { + if (mLayoutChangeListener == null) { + mLayoutChangeListener = + (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { + onShowBorder(); + mTargetView.invalidate(); + }; + mTargetView.addOnLayoutChangeListener(mLayoutChangeListener); + } + mBoundsBuilder.updateBorderBounds(mBorderBounds); + } + + void onHideBorder() { + if (mLayoutChangeListener != null) { + mTargetView.removeOnLayoutChangeListener(mLayoutChangeListener); + mLayoutChangeListener = null; + } + } + + abstract int getAlignmentAdjustmentInset(); + + abstract float getRadiusAdjustment(); + } + + /** + * Use an instance of this {@link BorderAnimationParams} if the border can be drawn outside the + * target view's bounds without any additional logic. + */ + public static final class SimpleParams extends BorderAnimationParams { + + public SimpleParams( + @Px int borderWidthPx, + @NonNull BorderBoundsBuilder boundsBuilder, + @NonNull View targetView) { + super(borderWidthPx, boundsBuilder, targetView); + } + + @Override + int getAlignmentAdjustmentInset() { + return 0; + } + + @Override + float getRadiusAdjustment() { + return -getAlignmentAdjustment(); + } + } + + /** + * Use an instance of this {@link BorderAnimationParams} if the border would other be clipped by + * the target view's bound. + *

+ * Note: using these params will set the scales and pivots of the + * container and content views, however will only reset the scales back to 1. + */ + public static final class ScalingParams extends BorderAnimationParams { + + @NonNull private final View mContentView; /** - * Returns the content view. This view will be scaled down reciprocally to the container's - * up-scaling to maintain its original size. This should be the view containing all of the - * content being surrounded by the border. + * @param targetView the view that will be drawing the border. this view will be scaled up + * to make room for the border + * @param contentView the view around which the border will be drawn. this view will be + * scaled down reciprocally to keep its original size and location. */ - @NonNull - View getContentView(); + public ScalingParams( + @Px int borderWidthPx, + @NonNull BorderBoundsBuilder boundsBuilder, + @NonNull View targetView, + @NonNull View contentView) { + super(borderWidthPx, boundsBuilder, targetView); + mContentView = contentView; + } + + @Override + void onShowBorder() { + super.onShowBorder(); + float width = mTargetView.getWidth(); + float height = mTargetView.getHeight(); + // Scale up just enough to make room for the border. Fail fast and fix the scaling + // onLayout. + float scaleX = width == 0 ? 1f : 1f + ((2 * mBorderWidthPx) / width); + float scaleY = height == 0 ? 1f : 1f + ((2 * mBorderWidthPx) / height); + + mTargetView.setPivotX(width / 2); + mTargetView.setPivotY(height / 2); + mTargetView.setScaleX(scaleX); + mTargetView.setScaleY(scaleY); + + mContentView.setPivotX(mContentView.getWidth() / 2f); + mContentView.setPivotY(mContentView.getHeight() / 2f); + mContentView.setScaleX(1f / scaleX); + mContentView.setScaleY(1f / scaleY); + } + + @Override + void onHideBorder() { + super.onHideBorder(); + mTargetView.setPivotX(mTargetView.getWidth()); + mTargetView.setPivotY(mTargetView.getHeight()); + mTargetView.setScaleX(1f); + mTargetView.setScaleY(1f); + + mContentView.setPivotX(mContentView.getWidth() / 2f); + mContentView.setPivotY(mContentView.getHeight() / 2f); + mContentView.setScaleX(1f); + mContentView.setScaleY(1f); + } + + @Override + int getAlignmentAdjustmentInset() { + // Inset the border since we are scaling the container up + return mBorderWidthPx; + } + + @Override + float getRadiusAdjustment() { + // Increase the radius since we are scaling the container up + return getAlignmentAdjustment(); + } } } diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index c47c946a35..6e7b6dce62 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -445,13 +445,14 @@ public class TaskView extends FrameLayout implements Reusable { mBorderAnimator = !keyboardFocusHighlightEnabled ? null : new BorderAnimator( - /* borderBoundsBuilder= */ this::updateBorderBounds, - /* borderWidthPx= */ context.getResources().getDimensionPixelSize( - R.dimen.keyboard_quick_switch_border_width), /* borderRadiusPx= */ (int) mCurrentFullscreenParams.mCornerRadius, /* borderColor= */ ta.getColor( R.styleable.TaskView_borderColor, DEFAULT_BORDER_COLOR), - /* invalidateViewCallback= */ TaskView.this::invalidate); + /* borderAnimationParams= */ new BorderAnimator.SimpleParams( + /* borderWidthPx= */ context.getResources().getDimensionPixelSize( + R.dimen.keyboard_quick_switch_border_width), + /* boundsBuilder= */ this::updateBorderBounds, + /* targetView= */ this)); ta.recycle(); } From 0f54a897bb965d239898c561129e96f25dc88d0b Mon Sep 17 00:00:00 2001 From: Anushree Ganjam Date: Fri, 19 May 2023 20:51:19 +0000 Subject: [PATCH 08/11] Add AGA_SESSION_SUMMARY_LOG for session summary log debugging. adb shell setprop log.tag.AGASessionSummaryLog V Bug: 283829335 Test: Manual Flag: NA Change-Id: I90da76f1db1a103e49171bbc7499cd79606d3fcf --- src/com/android/launcher3/util/LogConfig.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/com/android/launcher3/util/LogConfig.java b/src/com/android/launcher3/util/LogConfig.java index 04f83b9707..e5bbcb1923 100644 --- a/src/com/android/launcher3/util/LogConfig.java +++ b/src/com/android/launcher3/util/LogConfig.java @@ -60,4 +60,9 @@ public class LogConfig { * When turned on, we enable Gms Play related logging. */ public static final String GMS_PLAY = "GmsPlay"; + + /** + * When turned on, we enable AGA related session summary logging. + */ + public static final String AGA_SESSION_SUMMARY_LOG = "AGASessionSummaryLog"; } From 108ae1657bad0cb9695e55f1c9252a7d6d1355f3 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Mon, 22 May 2023 17:37:06 -0700 Subject: [PATCH 09/11] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: Iec51ecd0cd0bfbb9d45f8cdf6034b25f32238da8 --- quickstep/res/values-pt/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml index 2bc1399f80..dec96e9a41 100644 --- a/quickstep/res/values-pt/strings.xml +++ b/quickstep/res/values-pt/strings.xml @@ -23,7 +23,7 @@ "Forma livre" "Nenhum item recente" "Configurações de uso do app" - "Limpar tudo" + "Remover tudo" "Apps recentes" "Tarefa encerrada" "%1$s, %2$s" From cc9674053464196520c60934ace8508b6cbb0560 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Tue, 23 May 2023 06:14:54 +0000 Subject: [PATCH 10/11] Removing legacy launcher winscope tracing for tests Bug: 279924453 Test: Presubmit Change-Id: I9ed7c3669dad5c20d0fa760b2fe2a50308f10be8 --- .../launcher3/util/rule/FailureWatcher.java | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java index 19e7b13e33..7ca6a06ed2 100644 --- a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java +++ b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java @@ -2,7 +2,6 @@ package com.android.launcher3.util.rule; import static androidx.test.InstrumentationRegistry.getInstrumentation; -import android.content.Context; import android.os.FileUtils; import android.os.ParcelFileDescriptor.AutoCloseInputStream; import android.util.Log; @@ -54,27 +53,9 @@ public class FailureWatcher extends TestWatcher { return new Statement() { @Override public void evaluate() throws Throwable { - boolean success = false; try { - mDevice.executeShellCommand("cmd statusbar tracing start"); FailureWatcher.super.apply(base, description).evaluate(); - success = true; } finally { - // Save artifact for Launcher Winscope trace. - mDevice.executeShellCommand("cmd statusbar tracing stop"); - final Context nexusLauncherContext = - getInstrumentation().getTargetContext() - .createPackageContext("com.google.android.apps.nexuslauncher", - 0); - final File launcherTrace = - new File(nexusLauncherContext.getFilesDir(), "launcher_trace.pb"); - if (success) { - mDevice.executeShellCommand("rm " + launcherTrace); - } else { - mDevice.executeShellCommand("mv " + launcherTrace + " " - + diagFile(description, "LauncherWinscope", "pb")); - } - // Detect touch events coming from physical screen. if (mLauncher.hadNontestEvents()) { throw new AssertionError( From 1f10e53ba2e9b416fe1f905498cc3095055fb98e Mon Sep 17 00:00:00 2001 From: Thales Lima Date: Wed, 3 May 2023 18:34:36 +0100 Subject: [PATCH 11/11] Create TAPL test for taskbar in overview Fix: 269985301 Test: TaplTestsQuickstep Flag: none Change-Id: Iea0311bcba54882f7f2cf5d35cd98a538ae85855 --- .../android/quickstep/TaplTestsQuickstep.java | 49 +++++++++ .../android/launcher3/tapl/BaseOverview.java | 100 +++++++++++++++--- .../tapl/LauncherInstrumentation.java | 32 ++++-- .../android/launcher3/tapl/OverviewTask.java | 4 + .../com/android/launcher3/tapl/Taskbar.java | 30 ++++++ 5 files changed, 195 insertions(+), 20 deletions(-) diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java index c39d095068..00b72b1692 100644 --- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java +++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java @@ -425,6 +425,55 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest { 0, getTaskCount(launcher))); } + @Test + @PortraitLandscape + public void testOverviewDeadzones() throws Exception { + startTestAppsWithCheck(); + + Overview overview = mLauncher.goHome().switchToOverview(); + assertTrue("Launcher internal state should be Overview", + isInState(() -> LauncherState.OVERVIEW)); + executeOnLauncher( + launcher -> assertTrue("Should have at least 3 tasks", + getTaskCount(launcher) >= 3)); + + // It should not dismiss overview when tapping between tasks + overview.touchBetweenTasks(); + overview = mLauncher.getOverview(); + assertTrue("Launcher internal state should be Overview", + isInState(() -> LauncherState.OVERVIEW)); + + // Dismiss when tapping to the right of the focused task + overview.touchOutsideFirstTask(); + assertTrue("Launcher internal state should be Home", + isInState(() -> LauncherState.NORMAL)); + } + + @Test + @PortraitLandscape + public void testTaskbarDeadzonesForTablet() throws Exception { + assumeTrue(mLauncher.isTablet()); + + startTestAppsWithCheck(); + + Overview overview = mLauncher.goHome().switchToOverview(); + assertTrue("Launcher internal state should be Overview", + isInState(() -> LauncherState.OVERVIEW)); + executeOnLauncher( + launcher -> assertTrue("Should have at least 3 tasks", + getTaskCount(launcher) >= 3)); + + // On persistent taskbar, it should not dismiss when tapping the taskbar + overview.touchTaskbarBottomCorner(/* tapRight= */ false); + assertTrue("Launcher internal state should be Overview", + isInState(() -> LauncherState.OVERVIEW)); + + // On persistent taskbar, it should not dismiss when tapping the taskbar + overview.touchTaskbarBottomCorner(/* tapRight= */ true); + assertTrue("Launcher internal state should be Overview", + isInState(() -> LauncherState.OVERVIEW)); + } + @Test @ScreenRecord // b/242163205 public void testDisableRotationCheckForPhone() throws Exception { diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java index afeb8d782b..2c3c02827d 100644 --- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java +++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java @@ -71,6 +71,44 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer { } } + /** + * Flings backward (right) and waits the fling's end. + */ + public void flingBackward() { + try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) { + flingBackwardImpl(); + } + } + + private void flingBackwardImpl() { + try (LauncherInstrumentation.Closable c = + mLauncher.addContextLayer("want to fling backward in overview")) { + LauncherInstrumentation.log("Overview.flingBackward before fling"); + final UiObject2 overview = verifyActiveContainer(); + final int rightMargin = + mLauncher.getTargetInsets().right + mLauncher.getEdgeSensitivityWidth(); + mLauncher.scroll( + overview, Direction.RIGHT, new Rect(0, 0, rightMargin + 1, 0), 20, false); + try (LauncherInstrumentation.Closable c2 = + mLauncher.addContextLayer("flung backwards")) { + verifyActiveContainer(); + verifyActionsViewVisibility(); + } + } + } + + private OverviewTask flingToFirstTask() { + OverviewTask currentTask = getCurrentTask(); + + while (mLauncher.getRealDisplaySize().x - currentTask.getUiObject().getVisibleBounds().right + <= mLauncher.getOverviewPageSpacing()) { + flingBackwardImpl(); + currentTask = getCurrentTask(); + } + + return currentTask; + } + /** * Dismissed all tasks by scrolling to Clear-all button and pressing it. */ @@ -94,23 +132,57 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer { } /** - * Flings backward (right) and waits the fling's end. + * Touch to the right of current task. This should dismiss overview and go back to Workspace. */ - public void flingBackward() { + public Workspace touchOutsideFirstTask() { try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); - LauncherInstrumentation.Closable c = - mLauncher.addContextLayer("want to fling backward in overview")) { - LauncherInstrumentation.log("Overview.flingBackward before fling"); - final UiObject2 overview = verifyActiveContainer(); - final int rightMargin = - mLauncher.getTargetInsets().right + mLauncher.getEdgeSensitivityWidth(); - mLauncher.scroll( - overview, Direction.RIGHT, new Rect(0, 0, rightMargin + 1, 0), 20, false); - try (LauncherInstrumentation.Closable c2 = - mLauncher.addContextLayer("flung backwards")) { - verifyActiveContainer(); - verifyActionsViewVisibility(); + LauncherInstrumentation.Closable c = mLauncher.addContextLayer( + "touching outside the focused task")) { + + if (getTaskCount() < 2) { + throw new IllegalStateException( + "Need to have at least 2 tasks"); } + + OverviewTask currentTask = flingToFirstTask(); + + mLauncher.touchOutsideContainer(currentTask.getUiObject(), + /* tapRight= */ true, + /* halfwayToEdge= */ false); + + return new Workspace(mLauncher); + } + } + + /** + * Touch between two tasks + */ + public void touchBetweenTasks() { + try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); + LauncherInstrumentation.Closable c = mLauncher.addContextLayer( + "touching outside the focused task")) { + if (getTaskCount() < 2) { + throw new IllegalStateException( + "Need to have at least 2 tasks"); + } + + OverviewTask currentTask = flingToFirstTask(); + + mLauncher.touchOutsideContainer(currentTask.getUiObject(), + /* tapRight= */ false, + /* halfwayToEdge= */ false); + } + } + + /** + * Touch either on the right or the left corner of the screen, 1 pixel from the bottom and + * from the sides. + */ + public void touchTaskbarBottomCorner(boolean tapRight) { + try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) { + Taskbar taskbar = new Taskbar(mLauncher); + taskbar.touchBottomCorner(tapRight); + verifyActiveContainer(); } } diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index 80fded5872..2adfc98e6d 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -2014,21 +2014,41 @@ public final class LauncherInstrumentation { } /** - * Taps outside container to dismiss. + * Taps outside container to dismiss, centered vertically and halfway to the edge of the screen. * * @param container container to be dismissed * @param tapRight tap on the right of the container if true, or left otherwise */ void touchOutsideContainer(UiObject2 container, boolean tapRight) { + touchOutsideContainer(container, tapRight, true); + } + + /** + * Taps outside the container, to the right or left, and centered vertically. + * + * @param tapRight if true touches to the right of the container, otherwise touches on left + * @param halfwayToEdge if true touches halfway to the screen edge, if false touches 1 px from + * container + */ + void touchOutsideContainer(UiObject2 container, boolean tapRight, boolean halfwayToEdge) { try (LauncherInstrumentation.Closable c = addContextLayer( "want to tap outside container on the " + (tapRight ? "right" : "left"))) { Rect containerBounds = getVisibleBounds(container); + + int x; + if (halfwayToEdge) { + x = tapRight + ? (containerBounds.right + getRealDisplaySize().x) / 2 + : containerBounds.left / 2; + } else { + x = tapRight + ? containerBounds.right + 1 + : containerBounds.left - 1; + } + int y = containerBounds.top + containerBounds.height() / 2; + final long downTime = SystemClock.uptimeMillis(); - final Point tapTarget = new Point( - tapRight - ? (containerBounds.right + getRealDisplaySize().x) / 2 - : containerBounds.left / 2, - containerBounds.top + 1); + final Point tapTarget = new Point(x, y); sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, tapTarget, LauncherInstrumentation.GestureScope.INSIDE); sendPointer(downTime, downTime, MotionEvent.ACTION_UP, tapTarget, diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java index 90f3d13a5d..39b93b4b59 100644 --- a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java +++ b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java @@ -71,6 +71,10 @@ public final class OverviewTask { return mTask.getVisibleBounds().exactCenterX(); } + UiObject2 getUiObject() { + return mTask; + } + /** * Dismisses the task by swiping up. */ diff --git a/tests/tapl/com/android/launcher3/tapl/Taskbar.java b/tests/tapl/com/android/launcher3/tapl/Taskbar.java index 6ca7f4bf79..051630e185 100644 --- a/tests/tapl/com/android/launcher3/tapl/Taskbar.java +++ b/tests/tapl/com/android/launcher3/tapl/Taskbar.java @@ -20,6 +20,7 @@ import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_DISABLE_ import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_ENABLE_MANUAL_TASKBAR_STASHING; import android.graphics.Point; +import android.graphics.Rect; import android.os.SystemClock; import android.text.TextUtils; import android.view.MotionEvent; @@ -122,4 +123,33 @@ public final class Taskbar { // Look for an icon with no text return By.clazz(TextView.class).text(""); } + + private Rect getVisibleBounds() { + return mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID).getVisibleBounds(); + } + + /** + * Touch either on the right or the left corner of the screen, 1 pixel from the bottom and + * from the sides. + */ + void touchBottomCorner(boolean tapRight) { + try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( + "want to tap bottom corner on the " + (tapRight ? "right" : "left"))) { + final long downTime = SystemClock.uptimeMillis(); + final Point tapTarget = new Point( + tapRight + ? + getVisibleBounds().right + - mLauncher.getTargetInsets().right + - 1 + : getVisibleBounds().left + + 1, + mLauncher.getRealDisplaySize().y - 1); + + mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, tapTarget, + LauncherInstrumentation.GestureScope.INSIDE); + mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP, tapTarget, + LauncherInstrumentation.GestureScope.INSIDE); + } + } }