From 2461d61e14f245546effa00f76d49c3a17d2af0f Mon Sep 17 00:00:00 2001 From: Perumaal S Date: Mon, 3 Jun 2019 10:21:47 -0700 Subject: [PATCH 01/29] Re-enable chips in qt-r1-dev Fixes: 134164918 Change-Id: Ib5441a40ad8043afbe32d6c4c40808676cdcdb20 --- src/com/android/launcher3/config/BaseFlags.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/launcher3/config/BaseFlags.java b/src/com/android/launcher3/config/BaseFlags.java index 7e20d11c2b..54d0db1006 100644 --- a/src/com/android/launcher3/config/BaseFlags.java +++ b/src/com/android/launcher3/config/BaseFlags.java @@ -105,7 +105,7 @@ abstract class BaseFlags { "ENABLE_QUICKSTEP_LIVE_TILE", false, "Enable live tile in Quickstep overview"); public static final TogglableFlag ENABLE_HINTS_IN_OVERVIEW = new TogglableFlag( - "ENABLE_HINTS_IN_OVERVIEW", false, + "ENABLE_HINTS_IN_OVERVIEW", true, "Show chip hints and gleams on the overview screen"); public static final TogglableFlag FAKE_LANDSCAPE_UI = new TogglableFlag( From f3231f417db08185ec204b247d331dba6a9b0383 Mon Sep 17 00:00:00 2001 From: Zak Cohen Date: Mon, 3 Jun 2019 14:58:18 -0700 Subject: [PATCH 02/29] Remove unused hints code. This layout is handled by the provider of the hints now. Test: manual Change-Id: Ifc0db2395a7503b1b03dcb796961ef6647c0413b --- .../RecentsViewStateController.java | 18 ----- .../com/android/quickstep/hints/HintUtil.java | 78 ------------------- .../com/android/quickstep/hints/HintView.java | 71 ----------------- .../hints/ProactiveHintsContainer.java | 55 ------------- .../hints/UiHintListenerConstants.java | 28 ------- .../quickstep/hints/UiInterfaceConstants.java | 34 -------- .../quickstep/views/LauncherRecentsView.java | 65 ---------------- res/layout/launcher.xml | 5 -- res/layout/proactive_hints_container.xml | 20 ----- res/values/dimens.xml | 5 -- src/com/android/launcher3/DeviceProfile.java | 7 -- 11 files changed, 386 deletions(-) delete mode 100644 quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintUtil.java delete mode 100644 quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintView.java delete mode 100644 quickstep/recents_ui_overrides/src/com/android/quickstep/hints/ProactiveHintsContainer.java delete mode 100644 quickstep/recents_ui_overrides/src/com/android/quickstep/hints/UiHintListenerConstants.java delete mode 100644 quickstep/recents_ui_overrides/src/com/android/quickstep/hints/UiInterfaceConstants.java delete mode 100644 res/layout/proactive_hints_container.xml diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java index 1d36d1aae8..b5d84247a8 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java @@ -32,7 +32,6 @@ import com.android.launcher3.LauncherState; import com.android.launcher3.LauncherStateManager.AnimationConfig; import com.android.launcher3.anim.AnimatorSetBuilder; import com.android.launcher3.anim.PropertySetter; -import com.android.quickstep.hints.ProactiveHintsContainer; import com.android.quickstep.views.ClearAllButton; import com.android.quickstep.views.LauncherRecentsView; import com.android.quickstep.views.RecentsView; @@ -55,14 +54,6 @@ public final class RecentsViewStateController extends if (state.overviewUi) { mRecentsView.updateEmptyMessage(); mRecentsView.resetTaskVisuals(); - mRecentsView.setHintVisibility(1f); - } else { - mRecentsView.setHintVisibility(0f); - ProactiveHintsContainer - proactiveHintsContainer = mRecentsView.getProactiveHintsContainer(); - if (proactiveHintsContainer != null) { - proactiveHintsContainer.removeAllViews(); - } } setAlphas(PropertySetter.NO_ANIM_PROPERTY_SETTER, state.getVisibleElements(mLauncher)); mRecentsView.setFullscreenProgress(state.getOverviewFullscreenProgress()); @@ -75,14 +66,6 @@ public final class RecentsViewStateController extends if (!toState.overviewUi) { builder.addOnFinishRunnable(mRecentsView::resetTaskVisuals); - mRecentsView.setHintVisibility(0f); - builder.addOnFinishRunnable(() -> { - ProactiveHintsContainer - proactiveHintsContainer = mRecentsView.getProactiveHintsContainer(); - if (proactiveHintsContainer != null) { - proactiveHintsContainer.removeAllViews(); - } - }); } if (toState.overviewUi) { @@ -94,7 +77,6 @@ public final class RecentsViewStateController extends updateAnim.setDuration(config.duration); builder.play(updateAnim); mRecentsView.updateEmptyMessage(); - builder.addOnFinishRunnable(() -> mRecentsView.setHintVisibility(1f)); } PropertySetter propertySetter = config.getPropertySetter(builder); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintUtil.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintUtil.java deleted file mode 100644 index f2d40ecc4d..0000000000 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintUtil.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.quickstep.hints; - -import android.app.PendingIntent; -import android.graphics.drawable.Icon; -import android.os.Bundle; - -public final class HintUtil { - - public static final String ID_KEY = "id"; - public static final String ICON_KEY = "icon"; - public static final String TEXT_KEY = "text"; - public static final String TAP_ACTION_KEY = "tap_action"; - - private HintUtil() {} - - public static Bundle makeHint(String id, Icon icon, CharSequence text) { - Bundle hint = new Bundle(); - hint.putString(ID_KEY, id); - hint.putParcelable(ICON_KEY, icon); - hint.putCharSequence(TEXT_KEY, text); - return hint; - } - - public static Bundle makeHint(Icon icon, CharSequence text, PendingIntent tapAction) { - Bundle hint = new Bundle(); - hint.putParcelable(ICON_KEY, icon); - hint.putCharSequence(TEXT_KEY, text); - hint.putParcelable(TAP_ACTION_KEY, tapAction); - return hint; - } - - public static String getId(Bundle hint) { - String id = hint.getString(ID_KEY); - if (id == null) { - throw new IllegalArgumentException("Hint does not contain an ID"); - } - return id; - } - - public static Icon getIcon(Bundle hint) { - Icon icon = hint.getParcelable(ICON_KEY); - if (icon == null) { - throw new IllegalArgumentException("Hint does not contain an icon"); - } - return icon; - } - - public static CharSequence getText(Bundle hint) { - CharSequence text = hint.getCharSequence(TEXT_KEY); - if (text == null) { - throw new IllegalArgumentException("Hint does not contain text"); - } - return text; - } - - public static PendingIntent getTapAction(Bundle hint) { - PendingIntent tapAction = hint.getParcelable(TAP_ACTION_KEY); - if (tapAction == null) { - throw new IllegalArgumentException("Hint does not contain a tap action"); - } - return tapAction; - } -} diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintView.java deleted file mode 100644 index 5399cc4efc..0000000000 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/HintView.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.quickstep.hints; - -import static com.android.quickstep.hints.HintUtil.getIcon; -import static com.android.quickstep.hints.HintUtil.getText; - -import android.content.Context; -import android.graphics.drawable.Icon; -import android.os.Bundle; -import android.util.AttributeSet; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import androidx.annotation.Nullable; - -import com.android.launcher3.R; - -public class HintView extends LinearLayout { - private ImageView mIconView; - private TextView mLabelView; - - public HintView(Context context) { - super(context); - } - - public HintView(Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - } - - public HintView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - public HintView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - public void setHint(Bundle hint) { - mLabelView.setText(getText(hint)); - - Icon icon = getIcon(hint); - if (icon == null) { - mIconView.setVisibility(GONE); - } else { - mIconView.setImageIcon(icon); - mIconView.setVisibility(VISIBLE); - } - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mIconView = findViewById(R.id.icon); - mLabelView = findViewById(R.id.label); - } -} diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/ProactiveHintsContainer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/ProactiveHintsContainer.java deleted file mode 100644 index 74a48517b2..0000000000 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/ProactiveHintsContainer.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.android.quickstep.hints; - -import android.content.Context; -import android.util.AttributeSet; -import android.util.FloatProperty; -import android.view.View; -import android.widget.FrameLayout; - -public class ProactiveHintsContainer extends FrameLayout { - - public static final FloatProperty HINT_VISIBILITY = - new FloatProperty("hint_visibility") { - @Override - public void setValue(ProactiveHintsContainer proactiveHintsContainer, float v) { - proactiveHintsContainer.setHintVisibility(v); - } - - @Override - public Float get(ProactiveHintsContainer proactiveHintsContainer) { - return proactiveHintsContainer.mHintVisibility; - } - }; - - private float mHintVisibility; - - public ProactiveHintsContainer(Context context) { - super(context); - } - - public ProactiveHintsContainer(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public ProactiveHintsContainer(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - public ProactiveHintsContainer(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - public void setView(View v) { - removeAllViews(); - addView(v); - } - - public void setHintVisibility(float v) { - if (v == 1) { - setVisibility(VISIBLE); - } else { - setVisibility(GONE); - } - mHintVisibility = v; - } -} diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/UiHintListenerConstants.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/UiHintListenerConstants.java deleted file mode 100644 index 420033dd61..0000000000 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/UiHintListenerConstants.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.quickstep.hints; - -public final class UiHintListenerConstants { - - private UiHintListenerConstants() {} - - // Operations - public static final int ON_HINTS_RETURNED_CODE = 5; - - // Keys - public static final String SESSION_ID_KEY = "session_id"; - public static final String HINTS_KEY = "hints"; -} diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/UiInterfaceConstants.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/UiInterfaceConstants.java deleted file mode 100644 index 01406130fb..0000000000 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/hints/UiInterfaceConstants.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.quickstep.hints; - -public final class UiInterfaceConstants { - - private UiInterfaceConstants() {} - - // Operations - public static final int ON_HINT_TAP_CODE = 4; - - public static final int REQUEST_HINTS_CODE = 7; - - // Keys - public static final String SESSION_ID_KEY = "session_id"; - public static final String HINT_ID_KEY = "hint_id"; - public static final String WIDTH_PX_KEY = "width_px"; - public static final String HEIGHT_PX_KEY = "height_px"; - public static final String HINT_SPACE_WIDTH_PX_KEY = "hint_space_width_px"; - public static final String HINT_SPACE_HEIGHT_PX_KEY = "hint_space_height_px"; -} diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java index deedd21adb..3b23bd1095 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java @@ -30,13 +30,10 @@ import android.annotation.TargetApi; import android.content.Context; import android.graphics.Canvas; import android.graphics.Rect; -import android.graphics.RectF; import android.os.Build; import android.util.AttributeSet; import android.view.View; -import androidx.annotation.Nullable; - import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; @@ -44,11 +41,8 @@ import com.android.launcher3.R; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.appprediction.PredictionUiStateManager; import com.android.launcher3.appprediction.PredictionUiStateManager.Client; -import com.android.launcher3.util.PendingAnimation; -import com.android.launcher3.views.BaseDragLayer; import com.android.launcher3.views.ScrimView; import com.android.quickstep.SysUINavigationMode; -import com.android.quickstep.hints.ProactiveHintsContainer; import com.android.quickstep.util.ClipAnimationHelper; import com.android.quickstep.util.ClipAnimationHelper.TransformParams; import com.android.quickstep.util.LayoutUtils; @@ -60,8 +54,6 @@ import com.android.quickstep.util.LayoutUtils; public class LauncherRecentsView extends RecentsView { private final TransformParams mTransformParams = new TransformParams(); - private final int mChipOverhang; - @Nullable private ProactiveHintsContainer mProactiveHintsContainer; public LauncherRecentsView(Context context) { this(context, null); @@ -74,16 +66,6 @@ public class LauncherRecentsView extends RecentsView { public LauncherRecentsView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setContentAlpha(0); - mChipOverhang = (int) context.getResources().getDimension(R.dimen.chip_hint_overhang); - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - View hintContainer = mActivity.findViewById(R.id.hints); - mProactiveHintsContainer = - hintContainer instanceof ProactiveHintsContainer - ? (ProactiveHintsContainer) hintContainer : null; } @Override @@ -102,11 +84,6 @@ public class LauncherRecentsView extends RecentsView { } } - @Nullable - public ProactiveHintsContainer getProactiveHintsContainer() { - return mProactiveHintsContainer; - } - @Override public void draw(Canvas canvas) { maybeDrawEmptyMessage(canvas); @@ -160,23 +137,6 @@ public class LauncherRecentsView extends RecentsView { @Override protected void getTaskSize(DeviceProfile dp, Rect outRect) { LayoutUtils.calculateLauncherTaskSize(getContext(), dp, outRect); - if (mProactiveHintsContainer != null) { - BaseDragLayer.LayoutParams params = (BaseDragLayer.LayoutParams) mProactiveHintsContainer.getLayoutParams(); - params.bottomMargin = getHeight() - outRect.bottom - mChipOverhang; - params.width = outRect.width(); - } - } - - @Override - public PendingAnimation createTaskLauncherAnimation(TaskView tv, long duration) { - PendingAnimation anim = super.createTaskLauncherAnimation(tv, duration); - - if (mProactiveHintsContainer != null) { - anim.anim.play(ObjectAnimator.ofFloat( - mProactiveHintsContainer, ProactiveHintsContainer.HINT_VISIBILITY, 0)); - } - - return anim; } @Override @@ -194,31 +154,6 @@ public class LauncherRecentsView extends RecentsView { } } - @Override - public PendingAnimation createTaskDismissAnimation(TaskView taskView, boolean animateTaskView, - boolean shouldRemoveTask, long duration) { - PendingAnimation anim = super.createTaskDismissAnimation(taskView, animateTaskView, - shouldRemoveTask, duration); - - if (mProactiveHintsContainer != null) { - anim.anim.play(ObjectAnimator.ofFloat( - mProactiveHintsContainer, ProactiveHintsContainer.HINT_VISIBILITY, 0)); - anim.addEndListener(onEndListener -> { - if (!onEndListener.isSuccess) { - mProactiveHintsContainer.setHintVisibility(1); - } - }); - } - - return anim; - } - - public void setHintVisibility(float v) { - if (mProactiveHintsContainer != null) { - mProactiveHintsContainer.setHintVisibility(v); - } - } - @Override protected void onTaskLaunched(boolean success) { if (success) { diff --git a/res/layout/launcher.xml b/res/layout/launcher.xml index 9cab9c2a5e..cca899bda8 100644 --- a/res/layout/launcher.xml +++ b/res/layout/launcher.xml @@ -48,11 +48,6 @@ layout="@layout/overview_panel" android:visibility="gone" /> - - - - \ No newline at end of file diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 0da56dafb9..4bcb8a7f43 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -232,11 +232,6 @@ 12sp 14sp - - 26dp - 194dp - 15dp - 8dp diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index c1f898c5d0..883e8c642b 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -99,10 +99,6 @@ public class DeviceProfile { public int folderChildTextSizePx; public int folderChildDrawablePaddingPx; - // Hints - public int chipHintHeightPx; - public int chipHintBottomMarginPx; - // Hotseat public int hotseatCellHeightPx; // In portrait: size = height, in landscape: size = width @@ -200,9 +196,6 @@ public class DeviceProfile { workspaceCellPaddingXPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_padding_x); - chipHintHeightPx = res.getDimensionPixelSize(R.dimen.chip_hint_height); - chipHintBottomMarginPx = res.getDimensionPixelSize(R.dimen.chip_hint_bottom_margin); - hotseatBarTopPaddingPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_top_padding); hotseatBarBottomPaddingPx = (isTallDevice ? 0 From d4c90e12e9b6b61d3c0374ee5899425c84ffe65b Mon Sep 17 00:00:00 2001 From: vadimt Date: Tue, 4 Jun 2019 13:59:43 -0700 Subject: [PATCH 03/29] Freezing all apps updates during certain tests This CL adds a very low risk because most (but not all) changes affect only Launcher behavior during the test. This should fix a lab-only flake when all apps keeps changing while the test is working with it. Example: test figures out which icon to click, by the moment it clicks there, there is another icon there, or the icon is under the search box, and clicking opens IME. Switching test devices to airplane mode didn't help. The earlier change that prevents popup menu cancellation is not general enough. Now the tests are given an API to explicitly freeze and unfreeze all-apps, which should be a final solution. Bug: 132900132 Bug: 133765434 Change-Id: I8b81cc9be004482beb6cdcdd05406e2d9b4c7629 --- src/com/android/launcher3/Launcher.java | 6 +- .../allapps/AllAppsContainerView.java | 5 +- .../launcher3/allapps/AllAppsStore.java | 31 ++-- .../testing/TestInformationHandler.java | 30 ++++ .../launcher3/testing/TestProtocol.java | 5 + .../launcher3/ui/TaplTestsLauncher3.java | 170 +++++++++++------- .../com/android/launcher3/tapl/AllApps.java | 22 +++ .../tapl/LauncherInstrumentation.java | 6 + 8 files changed, 194 insertions(+), 81 deletions(-) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 855535b0f3..67086a578d 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -80,6 +80,7 @@ import android.widget.Toast; import com.android.launcher3.DropTarget.DragObject; import com.android.launcher3.accessibility.LauncherAccessibilityDelegate; import com.android.launcher3.allapps.AllAppsContainerView; +import com.android.launcher3.allapps.AllAppsStore; import com.android.launcher3.allapps.AllAppsTransitionController; import com.android.launcher3.allapps.DiscoveryBounce; import com.android.launcher3.anim.PropertyListBuilder; @@ -2238,8 +2239,9 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, } mPendingExecutor = executor; if (!isInState(ALL_APPS)) { - mAppsView.getAppsStore().setDeferUpdates(true); - mPendingExecutor.execute(() -> mAppsView.getAppsStore().setDeferUpdates(false)); + mAppsView.getAppsStore().enableDeferUpdates(AllAppsStore.DEFER_UPDATES_NEXT_DRAW); + mPendingExecutor.execute(() -> mAppsView.getAppsStore().disableDeferUpdates( + AllAppsStore.DEFER_UPDATES_NEXT_DRAW)); } executor.attachTo(this); diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index 0d43e214ef..d68ff4451d 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -628,11 +628,12 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo final boolean result = super.dispatchTouchEvent(ev); switch (ev.getActionMasked()) { case MotionEvent.ACTION_DOWN: - if (result) mAllAppsStore.setDeferUpdates(true); + if (result) mAllAppsStore.enableDeferUpdates( + AllAppsStore.DEFER_UPDATES_USER_INTERACTION); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: - mAllAppsStore.setDeferUpdates(false); + mAllAppsStore.disableDeferUpdates(AllAppsStore.DEFER_UPDATES_USER_INTERACTION); break; } return result; diff --git a/src/com/android/launcher3/allapps/AllAppsStore.java b/src/com/android/launcher3/allapps/AllAppsStore.java index 8e7fec863b..160042e692 100644 --- a/src/com/android/launcher3/allapps/AllAppsStore.java +++ b/src/com/android/launcher3/allapps/AllAppsStore.java @@ -29,7 +29,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; -import java.util.Set; import java.util.function.Consumer; import java.util.function.Predicate; @@ -38,12 +37,19 @@ import java.util.function.Predicate; */ public class AllAppsStore { + // Defer updates flag used to defer all apps updates to the next draw. + public static final int DEFER_UPDATES_NEXT_DRAW = 1 << 0; + // Defer updates flag used to defer all apps updates while the user interacts with all apps. + public static final int DEFER_UPDATES_USER_INTERACTION = 1 << 1; + // Defer updates flag used to defer all apps updates by a test's request. + public static final int DEFER_UPDATES_TEST = 1 << 2; + private PackageUserKey mTempKey = new PackageUserKey(null, null); private final HashMap mComponentToAppMap = new HashMap<>(); private final List mUpdateListeners = new ArrayList<>(); private final ArrayList mIconContainers = new ArrayList<>(); - private boolean mDeferUpdates = false; + private int mDeferUpdatesFlags = 0; private boolean mUpdatePending = false; public Collection getApps() { @@ -62,17 +68,22 @@ public class AllAppsStore { return mComponentToAppMap.get(key); } - public void setDeferUpdates(boolean deferUpdates) { - if (mDeferUpdates != deferUpdates) { - mDeferUpdates = deferUpdates; + public void enableDeferUpdates(int flag) { + mDeferUpdatesFlags |= flag; + } - if (!mDeferUpdates && mUpdatePending) { - notifyUpdate(); - mUpdatePending = false; - } + public void disableDeferUpdates(int flag) { + mDeferUpdatesFlags &= ~flag; + if (mDeferUpdatesFlags == 0 && mUpdatePending) { + notifyUpdate(); + mUpdatePending = false; } } + public int getDeferUpdatesFlags() { + return mDeferUpdatesFlags; + } + /** * Adds or updates existing apps in the list */ @@ -95,7 +106,7 @@ public class AllAppsStore { private void notifyUpdate() { - if (mDeferUpdates) { + if (mDeferUpdatesFlags != 0) { mUpdatePending = true; return; } diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java index b8476aa1da..d2e196138c 100644 --- a/src/com/android/launcher3/testing/TestInformationHandler.java +++ b/src/com/android/launcher3/testing/TestInformationHandler.java @@ -23,9 +23,13 @@ import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherState; +import com.android.launcher3.MainThreadExecutor; import com.android.launcher3.R; +import com.android.launcher3.allapps.AllAppsStore; import com.android.launcher3.util.ResourceBasedOverride; +import java.util.concurrent.ExecutionException; + public class TestInformationHandler implements ResourceBasedOverride { public static TestInformationHandler newInstance(Context context) { @@ -77,6 +81,32 @@ public class TestInformationHandler implements ResourceBasedOverride { case TestProtocol.REQUEST_DISABLE_DEBUG_TRACING: TestProtocol.sDebugTracing = false; break; + + case TestProtocol.REQUEST_FREEZE_APP_LIST: + new MainThreadExecutor().execute(() -> + mLauncher.getAppsView().getAppsStore().enableDeferUpdates( + AllAppsStore.DEFER_UPDATES_TEST)); + break; + + case TestProtocol.REQUEST_UNFREEZE_APP_LIST: + new MainThreadExecutor().execute(() -> + mLauncher.getAppsView().getAppsStore().disableDeferUpdates( + AllAppsStore.DEFER_UPDATES_TEST)); + break; + + case TestProtocol.REQUEST_APP_LIST_FREEZE_FLAGS: { + try { + final int deferUpdatesFlags = new MainThreadExecutor().submit(() -> + mLauncher.getAppsView().getAppsStore().getDeferUpdatesFlags()).get(); + response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, + deferUpdatesFlags); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + break; + } } return response; } diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java index 99efb22cf1..e60b665eaa 100644 --- a/src/com/android/launcher3/testing/TestProtocol.java +++ b/src/com/android/launcher3/testing/TestProtocol.java @@ -57,6 +57,7 @@ public final class TestProtocol { } public static final String TEST_INFO_RESPONSE_FIELD = "response"; + public static final String REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT = "home-to-overview-swipe-height"; public static final String REQUEST_BACKGROUND_TO_OVERVIEW_SWIPE_HEIGHT = @@ -65,6 +66,10 @@ public final class TestProtocol { "all-apps-to-overview-swipe-height"; public static final String REQUEST_HOME_TO_ALL_APPS_SWIPE_HEIGHT = "home-to-all-apps-swipe-height"; + public static final String REQUEST_FREEZE_APP_LIST = "freeze-app-list"; + public static final String REQUEST_UNFREEZE_APP_LIST = "unfreeze-app-list"; + public static final String REQUEST_APP_LIST_FREEZE_FLAGS = "app-list-freeze-flags"; + public static boolean sDebugTracing = false; public static final String REQUEST_ENABLE_DEBUG_TRACING = "enable-debug-tracing"; public static final String REQUEST_DISABLE_DEBUG_TRACING = "disable-debug-tracing"; diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java index 4f8b87c519..d171004fc1 100644 --- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java +++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java @@ -108,47 +108,63 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { @Test @Ignore public void testPressHomeOnAllAppsContextMenu() throws Exception { - mLauncher.getWorkspace().switchToAllApps().getAppIcon("TestActivity7").openMenu(); + final AllApps allApps = mLauncher.getWorkspace().switchToAllApps(); + allApps.freeze(); + try { + allApps.getAppIcon("TestActivity7").openMenu(); + } finally { + allApps.unfreeze(); + } mLauncher.pressHome(); } public static void runAllAppsTest(AbstractLauncherUiTest test, AllApps allApps) { - assertNotNull("allApps parameter is null", allApps); + allApps.freeze(); + try { + assertNotNull("allApps parameter is null", allApps); - assertTrue( - "Launcher internal state is not All Apps", test.isInState(LauncherState.ALL_APPS)); + assertTrue( + "Launcher internal state is not All Apps", + test.isInState(LauncherState.ALL_APPS)); - // Test flinging forward and backward. - test.executeOnLauncher(launcher -> assertEquals( - "All Apps started in already scrolled state", 0, test.getAllAppsScroll(launcher))); + // Test flinging forward and backward. + test.executeOnLauncher(launcher -> assertEquals( + "All Apps started in already scrolled state", 0, + test.getAllAppsScroll(launcher))); - allApps.flingForward(); - assertTrue("Launcher internal state is not All Apps", - test.isInState(LauncherState.ALL_APPS)); - final Integer flingForwardY = test.getFromLauncher( - launcher -> test.getAllAppsScroll(launcher)); - test.executeOnLauncher( - launcher -> assertTrue("flingForward() didn't scroll App Apps", flingForwardY > 0)); + allApps.flingForward(); + assertTrue("Launcher internal state is not All Apps", + test.isInState(LauncherState.ALL_APPS)); + final Integer flingForwardY = test.getFromLauncher( + launcher -> test.getAllAppsScroll(launcher)); + test.executeOnLauncher( + launcher -> assertTrue("flingForward() didn't scroll App Apps", + flingForwardY > 0)); - allApps.flingBackward(); - assertTrue( - "Launcher internal state is not All Apps", test.isInState(LauncherState.ALL_APPS)); - final Integer flingBackwardY = test.getFromLauncher( - launcher -> test.getAllAppsScroll(launcher)); - test.executeOnLauncher(launcher -> assertTrue("flingBackward() didn't scroll App Apps", - flingBackwardY < flingForwardY)); + allApps.flingBackward(); + assertTrue( + "Launcher internal state is not All Apps", + test.isInState(LauncherState.ALL_APPS)); + final Integer flingBackwardY = test.getFromLauncher( + launcher -> test.getAllAppsScroll(launcher)); + test.executeOnLauncher(launcher -> assertTrue("flingBackward() didn't scroll App Apps", + flingBackwardY < flingForwardY)); - // Test scrolling down to YouTube. - assertNotNull("All apps: can't fine YouTube", allApps.getAppIcon("YouTube")); - // Test scrolling up to Camera. - assertNotNull("All apps: can't fine Camera", allApps.getAppIcon("Camera")); - // Test failing to find a non-existing app. - final AllApps allAppsFinal = allApps; - expectFail("All apps: could find a non-existing app", - () -> allAppsFinal.getAppIcon("NO APP")); + // Test scrolling down to YouTube. + assertNotNull("All apps: can't fine YouTube", allApps.getAppIcon("YouTube")); + // Test scrolling up to Camera. + assertNotNull("All apps: can't fine Camera", allApps.getAppIcon("Camera")); + // Test failing to find a non-existing app. + final AllApps allAppsFinal = allApps; + expectFail("All apps: could find a non-existing app", + () -> allAppsFinal.getAppIcon("NO APP")); - assertTrue( - "Launcher internal state is not All Apps", test.isInState(LauncherState.ALL_APPS)); + assertTrue( + "Launcher internal state is not All Apps", + test.isInState(LauncherState.ALL_APPS)); + } finally { + allApps.unfreeze(); + } } @Test @@ -199,12 +215,17 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { } public static void runIconLaunchFromAllAppsTest(AbstractLauncherUiTest test, AllApps allApps) { - final AppIcon app = allApps.getAppIcon("TestActivity7"); - assertNotNull("AppIcon.launch returned null", app.launch(getAppPackageName())); - test.executeOnLauncher(launcher -> assertTrue( - "Launcher activity is the top activity; expecting another activity to be the top " - + "one", - test.isInBackground(launcher))); + allApps.freeze(); + try { + final AppIcon app = allApps.getAppIcon("TestActivity7"); + assertNotNull("AppIcon.launch returned null", app.launch(getAppPackageName())); + test.executeOnLauncher(launcher -> assertTrue( + "Launcher activity is the top activity; expecting another activity to be the top " + + "one", + test.isInBackground(launcher))); + } finally { + allApps.unfreeze(); + } } @Test @@ -260,20 +281,23 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { public void testLaunchMenuItem() throws Exception { if (!TestHelpers.isInLauncherProcess()) return; - final AppIconMenu menu = mLauncher. + final AllApps allApps = mLauncher. getWorkspace(). - switchToAllApps(). - getAppIcon(APP_NAME). - openMenu(); + switchToAllApps(); + allApps.freeze(); + try { + final AppIconMenu menu = allApps. + getAppIcon(APP_NAME). + openMenu(); - executeOnLauncher( - launcher -> assertTrue("Launcher internal state didn't switch to Showing Menu", - isOptionsPopupVisible(launcher))); + executeOnLauncher( + launcher -> assertTrue("Launcher internal state didn't switch to Showing Menu", + isOptionsPopupVisible(launcher))); - final AppIconMenuItem menuItem = menu.getMenuItem(1); - final String itemName = menuItem.getText(); - - menuItem.launch(getAppPackageName()); + menu.getMenuItem(1).launch(getAppPackageName()); + } finally { + allApps.unfreeze(); + } } @Test @@ -282,12 +306,18 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { // 1. Open all apps and wait for load complete. // 2. Drag icon to homescreen. // 3. Verify that the icon works on homescreen. - mLauncher.getWorkspace(). - switchToAllApps(). - getAppIcon(APP_NAME). - dragToWorkspace(). - getWorkspaceAppIcon(APP_NAME). - launch(getAppPackageName()); + final AllApps allApps = mLauncher.getWorkspace(). + switchToAllApps(); + allApps.freeze(); + try { + allApps. + getAppIcon(APP_NAME). + dragToWorkspace(). + getWorkspaceAppIcon(APP_NAME). + launch(getAppPackageName()); + } finally { + allApps.unfreeze(); + } executeOnLauncher(launcher -> assertTrue( "Launcher activity is the top activity; expecting another activity to be the top " + "one", @@ -302,21 +332,27 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { // 1. Open all apps and wait for load complete. // 2. Find the app and long press it to show shortcuts. // 3. Press icon center until shortcuts appear - final AppIconMenuItem menuItem = mLauncher. + final AllApps allApps = mLauncher. getWorkspace(). - switchToAllApps(). - getAppIcon(APP_NAME). - openMenu(). - getMenuItem(0); - final String shortcutName = menuItem.getText(); + switchToAllApps(); + allApps.freeze(); + try { + final AppIconMenuItem menuItem = allApps. + getAppIcon(APP_NAME). + openMenu(). + getMenuItem(0); + final String shortcutName = menuItem.getText(); - // 4. Drag the first shortcut to the home screen. - // 5. Verify that the shortcut works on home screen - // (the app opens and has the same text as the shortcut). - menuItem. - dragToWorkspace(). - getWorkspaceAppIcon(shortcutName). - launch(getAppPackageName()); + // 4. Drag the first shortcut to the home screen. + // 5. Verify that the shortcut works on home screen + // (the app opens and has the same text as the shortcut). + menuItem. + dragToWorkspace(). + getWorkspaceAppIcon(shortcutName). + launch(getAppPackageName()); + } finally { + allApps.unfreeze(); + } } public static String getAppPackageName() { diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java index d03035a871..21d763e30e 100644 --- a/tests/tapl/com/android/launcher3/tapl/AllApps.java +++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java @@ -48,6 +48,7 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { "apps_list_view"); // Wait for the recycler to populate. mLauncher.waitForObjectInContainer(appListRecycler, By.clazz(TextView.class)); + verifyNotFrozen("All apps freeze flags upon opening all apps"); } @Override @@ -210,4 +211,25 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { verifyActiveContainer(); } } + + /** + * Freezes updating app list upon app install/uninstall/update. + */ + public void freeze() { + mLauncher.getTestInfo(TestProtocol.REQUEST_FREEZE_APP_LIST); + } + + /** + * Resumes updating app list upon app install/uninstall/update. + */ + public void unfreeze() { + mLauncher.getTestInfo(TestProtocol.REQUEST_UNFREEZE_APP_LIST); + verifyNotFrozen("All apps freeze flags upon unfreezing"); + } + + private void verifyNotFrozen(String message) { + mLauncher.assertEquals(message, 0, mLauncher.getTestInfo( + TestProtocol.REQUEST_APP_LIST_FREEZE_FLAGS). + getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD)); + } } diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index e45fca8c0f..8ebe525657 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -292,6 +292,12 @@ public final class LauncherInstrumentation { } } + void assertEquals(String message, long expected, long actual) { + if (expected != actual) { + fail(message + " expected: " + expected + " but was: " + actual); + } + } + void assertNotEquals(String message, int unexpected, int actual) { if (unexpected == actual) { failEquals(message, actual); From f1128d9f5efb051cd5c068e42304e240bb29063e Mon Sep 17 00:00:00 2001 From: Zak Cohen Date: Wed, 5 Jun 2019 16:01:16 -0700 Subject: [PATCH 04/29] Task footer - use temporary motion for show and hide. Bug: 125844074 Test: manual Change-Id: I9a26760f4bd976d0c3475db1322ee0da639d8209 --- .../src/com/android/quickstep/views/TaskView.java | 2 ++ quickstep/res/layout/task.xml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java index bf3e91ff68..726d798747 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java @@ -498,6 +498,8 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { mSnapshotView.setDimAlpha(curveInterpolation * MAX_PAGE_SCRIM_ALPHA); setCurveScale(getCurveScaleForCurveInterpolation(curveInterpolation)); + float fade = Utilities.boundToRange(1.0f - 2 * scrollState.linearInterpolation, 0f, 1f); + mTaskFooterContainer.setAlpha(fade); if (mMenuView != null) { mMenuView.setPosition(getX() - getRecentsView().getScrollX(), getY()); mMenuView.setScaleX(getScaleX()); diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml index 18691889ff..6a595a16e5 100644 --- a/quickstep/res/layout/task.xml +++ b/quickstep/res/layout/task.xml @@ -40,6 +40,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" + android:animateLayoutChanges="true" + android:forceHasOverlappingRendering="true" android:layout_gravity="bottom|center_horizontal"> Date: Fri, 7 Jun 2019 14:14:50 -0700 Subject: [PATCH 05/29] Removing unused method Change-Id: I25016d58b130e99c8983af48fde32e05bf6c66b1 --- .../inputconsumers/OverviewInputConsumer.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java index 4851e67e9d..56db2095fe 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java @@ -27,7 +27,6 @@ import androidx.annotation.Nullable; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.Utilities; import com.android.launcher3.views.BaseDragLayer; -import com.android.quickstep.ActivityControlHelper; import com.android.quickstep.OverviewCallbacks; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.InputMonitorCompat; @@ -114,13 +113,4 @@ public class OverviewInputConsumer mActivity.dispatchKeyEvent(ev); } } - - public static InputConsumer newInstanceWithinActivityBounds( - ActivityControlHelper activityHelper) { - BaseDraggingActivity activity = activityHelper.getCreatedActivity(); - if (activity == null) { - return InputConsumer.NO_OP; - } - return new OverviewInputConsumer(activity, null, true); - } } \ No newline at end of file From 34b2f03b308a7e3afcebe6e57d929d2950461b3c Mon Sep 17 00:00:00 2001 From: vadimt Date: Mon, 10 Jun 2019 11:26:37 -0700 Subject: [PATCH 06/29] More tracing for b/133009122 Bug: 133009122 Change-Id: I09a95b88ea55e1759151b2bcd5ede0c1efa38e7e --- .../android/launcher3/dragndrop/BaseItemDragListener.java | 4 ++++ .../android/launcher3/popup/PopupContainerWithArrow.java | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java index e204c63017..c719c1c986 100644 --- a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java +++ b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java @@ -37,6 +37,7 @@ import com.android.launcher3.DropTarget.DragObject; import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.states.InternalStateHandler; +import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.widget.PendingItemDragHelper; import java.util.UUID; @@ -136,6 +137,9 @@ public abstract class BaseItemDragListener extends InternalStateHandler implemen @Override public boolean shouldStartDrag(double distanceDragged) { + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.NO_DRAG_TAG, "BIDL.shouldStartDrag"); + } // Stay in pre-drag mode, if workspace is locked. return !mLauncher.isWorkspaceLocked(); } diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java index 7b14fa2491..9719a1892f 100644 --- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java +++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java @@ -36,6 +36,7 @@ import android.os.Build; import android.os.Handler; import android.os.Looper; import android.util.AttributeSet; +import android.util.Log; import android.util.Pair; import android.view.MotionEvent; import android.view.View; @@ -67,6 +68,7 @@ import com.android.launcher3.popup.PopupDataProvider.PopupDataChangeListener; import com.android.launcher3.shortcuts.DeepShortcutManager; import com.android.launcher3.shortcuts.DeepShortcutView; import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider; +import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.touch.ItemClickHandler; import com.android.launcher3.touch.ItemLongClickListener; import com.android.launcher3.util.PackageUserKey; @@ -447,6 +449,11 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource, @Override public boolean shouldStartDrag(double distanceDragged) { + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.NO_DRAG_TAG, + "createPreDragCondition().shouldStartDrag " + distanceDragged + ", " + + mStartDragThreshold); + } return distanceDragged > mStartDragThreshold; } From 76ba0a328da7229cb123a9aa983a0b180c2c110e Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Mon, 10 Jun 2019 11:56:11 -0700 Subject: [PATCH 07/29] Saving instance state so that widget cache is updated properly before rebind List widgets use a static cache which is initialized as part of saveInstanceState. Calling this ensures that no extra binder calls are made on rotation Bug: 134707989 Change-Id: I8d4450134168bd412ba2911c57354a603868bc47 --- src/com/android/launcher3/Launcher.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 57a9b161f9..9db2ec0476 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -465,6 +465,9 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, reapplyUi(); mDragLayer.recreateControllers(); + // Calling onSaveInstanceState ensures that static cache used by listWidgets is + // initialized properly. + onSaveInstanceState(new Bundle()); // TODO: We can probably avoid rebind when only screen size changed. rebindModel(); } From 915fd75faede1b5cb2f5ef4a60b8b2bdae41f979 Mon Sep 17 00:00:00 2001 From: vadimt Date: Mon, 10 Jun 2019 12:24:10 -0700 Subject: [PATCH 08/29] Not assuming that the activity is Launcher for the fallback recents Bug: 134919468 Change-Id: Ibb3b11a5bf57848212c806f2023e4cf43c8a862b --- .../android/quickstep/views/DigitalWellBeingToast.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java index 204dd56872..5aab944a32 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java @@ -37,7 +37,7 @@ import android.widget.TextView; import androidx.annotation.StringRes; -import com.android.launcher3.Launcher; +import com.android.launcher3.BaseActivity; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.userevent.nano.LauncherLogProto; @@ -187,12 +187,12 @@ public final class DigitalWellBeingToast extends LinearLayout { mTask.getTopComponent().getPackageName()).addFlags( Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); try { - final Launcher launcher = Launcher.getLauncher(getContext()); + final BaseActivity activity = BaseActivity.fromContext(getContext()); final ActivityOptions options = ActivityOptions.makeScaleUpAnimation( this, 0, 0, getWidth(), getHeight()); - launcher.startActivity(intent, options.toBundle()); - launcher.getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.Touch.TAP, + activity.startActivity(intent, options.toBundle()); + activity.getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.Touch.TAP, LauncherLogProto.ControlType.APP_USAGE_SETTINGS, this); } catch (ActivityNotFoundException e) { Log.e(TAG, "Failed to open app usage settings for task " From 8758311c2af2da1a78332f187d1461804d92a6ed Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Mon, 10 Jun 2019 14:20:58 -0700 Subject: [PATCH 09/29] Defer listening for notification changes until resume Bug: 134964922 Test: Take a systrace while swiping up, ensure there are no resource icon loads other than the icon for the current app while launcher is starting Change-Id: I469a2089df02434918125b005cd795f5514ec389 --- src/com/android/launcher3/Launcher.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 57a9b161f9..ca410aa4d6 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -888,7 +888,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, mLauncherCallbacks.onStart(); } mAppWidgetHost.setListenIfResumed(true); - NotificationListener.setNotificationsChangedListener(mPopupDataProvider); RaceConditionTracker.onEvent(ON_START_EVT, EXIT); } @@ -908,6 +907,9 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, // Refresh shortcuts if the permission changed. mModel.refreshShortcutsIfRequired(); + // Set the notification listener and fetch updated notifications when we resume + NotificationListener.setNotificationsChangedListener(mPopupDataProvider); + DiscoveryBounce.showForHomeIfNeeded(this); if (mPendingActivityRequestCode != -1 && isInState(NORMAL)) { From fa37c529e1f3587a4fe8362a0c66daa639d372a3 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Mon, 3 Jun 2019 10:21:20 -0700 Subject: [PATCH 10/29] Translate recents when attaching to app window instead of fading When attaching recents, translate it offscreen and use a spring to pull it into position. When detaching, use the same spring to pull it back offscreen. Bug: 129985827 Change-Id: I05339e2ec0932070365023bfafc83cbf2a4e178e --- .../LauncherActivityControllerHelper.java | 98 +++++++++++++++---- .../WindowTransformSwipeHandler.java | 30 +++--- .../android/quickstep/views/RecentsView.java | 10 ++ .../quickstep/ActivityControlHelper.java | 1 + 4 files changed, 106 insertions(+), 33 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java index 1b82bcb578..7809e454a5 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java @@ -16,16 +16,23 @@ package com.android.quickstep; import static android.view.View.TRANSLATION_Y; + import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.LauncherState.BACKGROUND_APP; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; +import static com.android.launcher3.LauncherStateManager.ANIM_ALL; import static com.android.launcher3.allapps.AllAppsTransitionController.SPRING_DAMPING_RATIO; import static com.android.launcher3.allapps.AllAppsTransitionController.SPRING_STIFFNESS; +import static com.android.launcher3.anim.Interpolators.ACCEL_2; import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL; +import static com.android.launcher3.anim.Interpolators.INSTANT; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.quickstep.WindowTransformSwipeHandler.RECENTS_ATTACH_DURATION; +import static androidx.dynamicanimation.animation.SpringForce.DAMPING_RATIO_LOW_BOUNCY; +import static androidx.dynamicanimation.animation.SpringForce.STIFFNESS_LOW; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; @@ -44,14 +51,18 @@ import android.view.animation.Interpolator; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.UiThread; +import androidx.dynamicanimation.animation.SpringAnimation; +import androidx.dynamicanimation.animation.SpringForce; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherInitListenerEx; import com.android.launcher3.LauncherState; +import com.android.launcher3.LauncherStateManager; import com.android.launcher3.allapps.DiscoveryBounce; import com.android.launcher3.anim.AnimatorPlaybackController; +import com.android.launcher3.anim.AnimatorSetBuilder; import com.android.launcher3.anim.SpringObjectAnimator; import com.android.launcher3.compat.AccessibilityManagerCompat; import com.android.launcher3.testing.TestProtocol; @@ -99,6 +110,13 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe DiscoveryBounce.showForOverviewIfNeeded(activity); } + @Override + public void onSwipeUpToHomeComplete(Launcher activity) { + // Ensure recents is at the correct position for NORMAL state. For example, when we detach + // recents, we assume the first task is invisible, making translation off by one task. + activity.getStateManager().reapplyState(); + } + @Override public void onAssistantVisibilityChanged(float visibility) { Launcher launcher = getCreatedActivity(); @@ -156,18 +174,23 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe public AnimatorPlaybackController createActivityAnimationToHome() { // Return an empty APC here since we have an non-user controlled animation to home. long accuracy = 2 * Math.max(dp.widthPx, dp.heightPx); - AnimatorSet as = new AnimatorSet(); - as.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(Animator animation) { - activity.getStateManager().goToState(NORMAL, false); - } - }); - return AnimatorPlaybackController.wrap(as, accuracy); + return activity.getStateManager().createAnimationToNewWorkspace(NORMAL, accuracy, + 0 /* animComponents */); } @Override public void playAtomicAnimation(float velocity) { + // Setup workspace with 0 duration to prepare for our staggered animation. + LauncherStateManager stateManager = activity.getStateManager(); + AnimatorSetBuilder builder = new AnimatorSetBuilder(); + // setRecentsAttachedToAppWindow() will animate recents out. + builder.addFlag(AnimatorSetBuilder.FLAG_DONT_ANIMATE_OVERVIEW); + stateManager.createAtomicAnimation(BACKGROUND_APP, NORMAL, builder, ANIM_ALL, 0); + builder.build().start(); + + // Stop scrolling so that it doesn't interfere with the translation offscreen. + recentsView.getScroller().forceFinished(true); + new StaggeredWorkspaceAnim(activity, workspaceView, velocity).start(); } }; @@ -201,7 +224,8 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe return new AnimationFactory() { private Animator mShelfAnim; private ShelfAnimState mShelfState; - private Animator mAttachToWindowAnim; + private Animator mAttachToWindowFadeAnim; + private SpringAnimation mAttachToWindowTranslationXAnim; private boolean mIsAttachedToWindow; @Override @@ -267,20 +291,60 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe return; } mIsAttachedToWindow = attached; - if (mAttachToWindowAnim != null) { - mAttachToWindowAnim.cancel(); + if (mAttachToWindowFadeAnim != null) { + mAttachToWindowFadeAnim.cancel(); } - mAttachToWindowAnim = ObjectAnimator.ofFloat(activity.getOverviewPanel(), + RecentsView recentsView = activity.getOverviewPanel(); + mAttachToWindowFadeAnim = ObjectAnimator.ofFloat(recentsView, RecentsView.CONTENT_ALPHA, attached ? 1 : 0); - mAttachToWindowAnim.addListener(new AnimatorListenerAdapter() { + + int runningTaskIndex = recentsView.getRunningTaskIndex(); + if (runningTaskIndex == 0) { + // If we are on the first task (we haven't quick switched), translate recents in + // from the side. Calculate the start translation based on current scale/scroll. + float currScale = recentsView.getScaleX(); + float scrollOffsetX = recentsView.getScrollOffset(); + + float offscreenX = NORMAL.getOverviewScaleAndTranslation(activity).translationX; + // The first task is hidden, so offset by its width. + int firstTaskWidth = recentsView.getTaskViewAt(0).getWidth(); + offscreenX -= (firstTaskWidth + recentsView.getPageSpacing()) * currScale; + // Offset since scale pushes tasks outwards. + offscreenX += firstTaskWidth * (currScale - 1) / 2; + offscreenX = Math.max(0, offscreenX); + if (recentsView.isRtl()) { + offscreenX = -offscreenX; + } + + float fromTranslationX = attached ? offscreenX - scrollOffsetX : 0; + float toTranslationX = attached ? 0 : offscreenX - scrollOffsetX; + if (mAttachToWindowTranslationXAnim == null) { + mAttachToWindowTranslationXAnim = new SpringAnimation(recentsView, + SpringAnimation.TRANSLATION_X).setSpring(new SpringForce() + .setDampingRatio(DAMPING_RATIO_LOW_BOUNCY) + .setStiffness(STIFFNESS_LOW)); + } + if (!recentsView.isShown() && animate) { + recentsView.setTranslationX(fromTranslationX); + mAttachToWindowTranslationXAnim.setStartValue(fromTranslationX); + } + mAttachToWindowTranslationXAnim.animateToFinalPosition(toTranslationX); + if (!animate && mAttachToWindowTranslationXAnim.canSkipToEnd()) { + mAttachToWindowTranslationXAnim.skipToEnd(); + } + + mAttachToWindowFadeAnim.setInterpolator(attached ? INSTANT : ACCEL_2); + } else { + mAttachToWindowFadeAnim.setInterpolator(ACCEL_DEACCEL); + } + mAttachToWindowFadeAnim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - mAttachToWindowAnim = null; + mAttachToWindowFadeAnim = null; } }); - mAttachToWindowAnim.setInterpolator(ACCEL_DEACCEL); - mAttachToWindowAnim.setDuration(animate ? RECENTS_ATTACH_DURATION : 0); - mAttachToWindowAnim.start(); + mAttachToWindowFadeAnim.setDuration(animate ? RECENTS_ATTACH_DURATION : 0); + mAttachToWindowFadeAnim.start(); } }; } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java index c7841d98e3..7d17f85f69 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -21,7 +21,6 @@ import static com.android.launcher3.Utilities.SINGLE_FRAME_MS; import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.anim.Interpolators.ACCEL_1_5; import static com.android.launcher3.anim.Interpolators.DEACCEL; -import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; @@ -218,7 +217,7 @@ public class WindowTransformSwipeHandler Math.min(1 / MIN_PROGRESS_FOR_OVERVIEW, 1 / (1 - MIN_PROGRESS_FOR_OVERVIEW)); private static final String SCREENSHOT_CAPTURED_EVT = "ScreenshotCaptured"; - private static final long SHELF_ANIM_DURATION = 120; + private static final long SHELF_ANIM_DURATION = 240; public static final long RECENTS_ATTACH_DURATION = 300; // Start resisting when swiping past this factor of mTransitionDragLength. @@ -602,7 +601,7 @@ public class WindowTransformSwipeHandler } public void onMotionPauseChanged(boolean isPaused) { - setShelfState(isPaused ? PEEK : HIDE, FAST_OUT_SLOW_IN, SHELF_ANIM_DURATION); + setShelfState(isPaused ? PEEK : HIDE, OVERSHOOT_1_2, SHELF_ANIM_DURATION); } public void maybeUpdateRecentsAttachedState() { @@ -625,7 +624,10 @@ public class WindowTransformSwipeHandler : mRecentsAnimationWrapper.targetSet.findTask(mRunningTaskId); final boolean recentsAttachedToAppWindow; int runningTaskIndex = mRecentsView.getRunningTaskIndex(); - if (mContinuingLastGesture) { + if (mGestureEndTarget != null) { + recentsAttachedToAppWindow = mGestureEndTarget.recentsAttachedToAppWindow; + } else if (mContinuingLastGesture + && mRecentsView.getRunningTaskIndex() != mRecentsView.getNextPage()) { recentsAttachedToAppWindow = true; animate = false; } else if (runningTaskTarget != null && isNotInRecents(runningTaskTarget)) { @@ -633,17 +635,16 @@ public class WindowTransformSwipeHandler recentsAttachedToAppWindow = true; animate = false; } else { - if (mGestureEndTarget != null) { - recentsAttachedToAppWindow = mGestureEndTarget.recentsAttachedToAppWindow; - } else { - recentsAttachedToAppWindow = mIsShelfPeeking || mIsLikelyToStartNewTask; - } + recentsAttachedToAppWindow = mIsShelfPeeking || mIsLikelyToStartNewTask; if (animate) { // Only animate if an adjacent task view is visible on screen. TaskView adjacentTask1 = mRecentsView.getTaskViewAt(runningTaskIndex + 1); TaskView adjacentTask2 = mRecentsView.getTaskViewAt(runningTaskIndex - 1); + float prevTranslationX = mRecentsView.getTranslationX(); + mRecentsView.setTranslationX(0); animate = (adjacentTask1 != null && adjacentTask1.getGlobalVisibleRect(TEMP_RECT)) || (adjacentTask2 != null && adjacentTask2.getGlobalVisibleRect(TEMP_RECT)); + mRecentsView.setTranslationX(prevTranslationX); } } mAnimationFactory.setRecentsAttachedToAppWindow(recentsAttachedToAppWindow, animate); @@ -701,13 +702,7 @@ public class WindowTransformSwipeHandler SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController(); if (controller != null) { - float offsetX = 0; - if (mRecentsView != null) { - int startScroll = mRecentsView.getScrollForPage(mRecentsView.indexOfChild( - mRecentsView.getRunningTaskView())); - offsetX = startScroll - mRecentsView.getScrollX(); - offsetX *= mRecentsView.getScaleX(); - } + float offsetX = mRecentsView == null ? 0 : mRecentsView.getScrollOffset(); float offsetScale = getTaskCurveScaleForOffsetX(offsetX, mClipAnimationHelper.getTargetRect().width()); mTransformParams.setProgress(shift).setOffsetX(offsetX).setOffsetScale(offsetScale); @@ -1217,6 +1212,9 @@ public class WindowTransformSwipeHandler if (mRecentsView != null) { mRecentsView.post(mRecentsView::resetTaskVisuals); } + // Make sure recents is in its final state + maybeUpdateRecentsAttachedState(false); + mActivityControlHelper.onSwipeUpToHomeComplete(mActivity); } }); return anim; diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index e38a315f8a..90e123e847 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -1676,6 +1676,16 @@ public abstract class RecentsView extends PagedView impl return mClearAllButton; } + /** + * @return How many pixels the running task is offset on the x-axis due to the current scrollX. + */ + public float getScrollOffset() { + int startScroll = getScrollForPage(getRunningTaskIndex()); + int offsetX = startScroll - getScrollX(); + offsetX *= getScaleX(); + return offsetX; + } + public Consumer getEventDispatcher(RotationMode rotationMode) { if (rotationMode.isTransposed) { Matrix transform = new Matrix(); diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java index b17d8d69c7..dcc1ace883 100644 --- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java +++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java @@ -53,6 +53,7 @@ public interface ActivityControlHelper { void onSwipeUpToRecentsComplete(T activity); + default void onSwipeUpToHomeComplete(T activity) { } void onAssistantVisibilityChanged(float visibility); @NonNull HomeAnimationFactory prepareHomeUI(T activity); From c026bf2f95a39cb3f6f074b7ea4a110adcadfb39 Mon Sep 17 00:00:00 2001 From: vadimt Date: Mon, 10 Jun 2019 15:36:30 -0700 Subject: [PATCH 11/29] Making sure that we drag icon far enough to cross the threshold Tests dragged icon from all apps to workspace by dragging it to the center of the screen. If the icon is close enough to the center, this may not trigger the dragging condition. Fixing by dragging far enough. Bug: 133009122 Change-Id: I68127714ab3694f2639b4acf530e2736ca4dbdf3 --- tests/tapl/com/android/launcher3/tapl/Launchable.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java index 5190f001a7..d4bdafa764 100644 --- a/tests/tapl/com/android/launcher3/tapl/Launchable.java +++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java @@ -20,7 +20,6 @@ import android.graphics.Point; import androidx.test.uiautomator.By; import androidx.test.uiautomator.BySelector; -import androidx.test.uiautomator.UiDevice; import androidx.test.uiautomator.UiObject2; import androidx.test.uiautomator.Until; @@ -70,11 +69,16 @@ abstract class Launchable { * Drags an object to the center of homescreen. */ public Workspace dragToWorkspace() { - final UiDevice device = mLauncher.getDevice(); + final Point launchableCenter = getObject().getVisibleCenter(); + final Point displaySize = mLauncher.getRealDisplaySize(); + final int width = displaySize.x / 2; Workspace.dragIconToWorkspace( mLauncher, this, - new Point(device.getDisplayWidth() / 2, device.getDisplayHeight() / 2), + new Point( + launchableCenter.x >= width ? + launchableCenter.x - width / 2 : launchableCenter.x + width / 2, + displaySize.y / 2), getLongPressIndicator()); try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( "dragged launchable to workspace")) { From 47860cf593c231dd10b7ae9912ef75ce4f614702 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Mon, 10 Jun 2019 16:00:36 -0700 Subject: [PATCH 12/29] Fixing some thread errors in TouchInteractionService Accessing internal objects only on the main thread and after the user has been unlocked. Bug: 134971634 Change-Id: Iaf6a1e3ab9417836c5d34673997b0a03a76862c1 --- .../quickstep/TouchInteractionService.java | 66 +++++++++---------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java index dc354404af..4a40c64f99 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -27,7 +27,6 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_N import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING; -import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED; import android.annotation.TargetApi; @@ -61,6 +60,7 @@ import android.view.Surface; import android.view.WindowManager; import androidx.annotation.BinderThread; +import androidx.annotation.UiThread; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.MainThreadExecutor; @@ -94,7 +94,6 @@ import com.android.systemui.shared.system.SystemGestureExclusionListenerCompat; import java.io.FileDescriptor; import java.io.PrintWriter; -import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; @@ -146,10 +145,7 @@ public class TouchInteractionService extends Service implements mISystemUiProxy = ISystemUiProxy.Stub .asInterface(bundle.getBinder(KEY_EXTRA_SYSUI_PROXY)); MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::initInputMonitor); - runWhenUserUnlocked(() -> { - mRecentsModel.setSystemUiProxy(mISystemUiProxy); - mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy); - }); + MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::onSystemUiProxySet); } @Override @@ -182,16 +178,9 @@ public class TouchInteractionService extends Service implements @Override public void onAssistantVisibilityChanged(float visibility) { - if (mOverviewComponentObserver == null) { - // Save the visibility to be applied when the user is unlocked - mPendingAssistantVisibility = visibility; - return; - } - - MAIN_THREAD_EXECUTOR.execute(() -> { - mOverviewComponentObserver.getActivityControlHelper() - .onAssistantVisibilityChanged(visibility); - }); + mLastAssistantVisibility = visibility; + MAIN_THREAD_EXECUTOR.execute( + TouchInteractionService.this::onAssistantVisibilityChanged); } public void onBackAction(boolean completed, int downX, int downY, boolean isButton, @@ -208,8 +197,7 @@ public class TouchInteractionService extends Service implements public void onSystemUiStateChanged(int stateFlags) { mSystemUiStateFlags = stateFlags; - mOverviewInteractionState.setSystemUiStateFlags(stateFlags); - mOverviewComponentObserver.onSystemUiStateChanged(stateFlags); + MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::onSystemUiFlagsChanged); } /** Deprecated methods **/ @@ -248,11 +236,10 @@ public class TouchInteractionService extends Service implements private InputConsumerController mInputConsumer; private SwipeSharedState mSwipeSharedState; private boolean mAssistantAvailable; - private float mPendingAssistantVisibility = 0; + private float mLastAssistantVisibility = 0; private @SystemUiStateFlags int mSystemUiStateFlags; private boolean mIsUserUnlocked; - private List mOnUserUnlockedCallbacks; private BroadcastReceiver mUserUnlockedReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -286,7 +273,6 @@ public class TouchInteractionService extends Service implements // Everything else should be initialized in initWhenUserUnlocked() below. mKM = getSystemService(KeyguardManager.class); mMainChoreographer = Choreographer.getInstance(); - mOnUserUnlockedCallbacks = new ArrayList<>(); if (UserManagerCompat.getInstance(this).isUserUnlocked(Process.myUserHandle())) { initWhenUserUnlocked(); @@ -413,13 +399,9 @@ public class TouchInteractionService extends Service implements } private void initWhenUserUnlocked() { - mIsUserUnlocked = true; - mAM = ActivityManagerWrapper.getInstance(); mRecentsModel = RecentsModel.INSTANCE.get(this); mOverviewComponentObserver = new OverviewComponentObserver(this); - mOverviewComponentObserver.getActivityControlHelper().onAssistantVisibilityChanged( - mPendingAssistantVisibility); mOverviewCommandHelper = new OverviewCommandHelper(this, mOverviewComponentObserver); mOverviewInteractionState = OverviewInteractionState.INSTANCE.get(this); @@ -427,12 +409,12 @@ public class TouchInteractionService extends Service implements mTaskOverlayFactory = TaskOverlayFactory.INSTANCE.get(this); mSwipeSharedState = new SwipeSharedState(mOverviewComponentObserver); mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer(); - mInputConsumer.registerInputConsumer(); + mIsUserUnlocked = true; - for (Runnable callback : mOnUserUnlockedCallbacks) { - callback.run(); - } - mOnUserUnlockedCallbacks.clear(); + mInputConsumer.registerInputConsumer(); + onSystemUiProxySet(); + onSystemUiFlagsChanged(); + onAssistantVisibilityChanged(); // Temporarily disable model preload // new ModelPreload().start(this); @@ -440,11 +422,27 @@ public class TouchInteractionService extends Service implements Utilities.unregisterReceiverSafely(this, mUserUnlockedReceiver); } - private void runWhenUserUnlocked(Runnable callback) { + @UiThread + private void onSystemUiProxySet() { if (mIsUserUnlocked) { - callback.run(); - } else { - mOnUserUnlockedCallbacks.add(callback); + mRecentsModel.setSystemUiProxy(mISystemUiProxy); + mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy); + } + } + + @UiThread + private void onSystemUiFlagsChanged() { + if (mIsUserUnlocked) { + mOverviewInteractionState.setSystemUiStateFlags(mSystemUiStateFlags); + mOverviewComponentObserver.onSystemUiStateChanged(mSystemUiStateFlags); + } + } + + @UiThread + private void onAssistantVisibilityChanged() { + if (mIsUserUnlocked) { + mOverviewComponentObserver.getActivityControlHelper().onAssistantVisibilityChanged( + mLastAssistantVisibility); } } From 8f9cf2f38fb3ae3a6401e1a7a121f98a529a4c9a Mon Sep 17 00:00:00 2001 From: vadimt Date: Mon, 10 Jun 2019 18:01:58 -0700 Subject: [PATCH 13/29] Calling sendStateEventToTest() from a place guaranteed to be called See discussion in the bug Bug: 133867119 Change-Id: Id162cfa3b0a0aafe17dd9b41e2c4b5d02c411830 --- .../android/quickstep/LauncherActivityControllerHelper.java | 3 --- src/com/android/launcher3/LauncherStateManager.java | 3 +++ .../launcher3/touch/AbstractStateChangeTouchController.java | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java index 7809e454a5..fd4cdfe009 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java @@ -64,7 +64,6 @@ import com.android.launcher3.allapps.DiscoveryBounce; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.AnimatorSetBuilder; import com.android.launcher3.anim.SpringObjectAnimator; -import com.android.launcher3.compat.AccessibilityManagerCompat; import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.views.FloatingIconView; @@ -219,8 +218,6 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe // Optimization, hide the all apps view to prevent layout while initializing activity.getAppsView().getContentView().setVisibility(View.GONE); - AccessibilityManagerCompat.sendStateEventToTest(activity, fromState.ordinal); - return new AnimationFactory() { private Animator mShelfAnim; private ShelfAnimState mShelfState; diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java index fe6b522970..8b03691c81 100644 --- a/src/com/android/launcher3/LauncherStateManager.java +++ b/src/com/android/launcher3/LauncherStateManager.java @@ -49,6 +49,7 @@ import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.AnimatorSetBuilder; import com.android.launcher3.anim.PropertySetter; import com.android.launcher3.anim.PropertySetter.AnimatedPropertySetter; +import com.android.launcher3.compat.AccessibilityManagerCompat; import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.uioverrides.UiFactory; @@ -496,6 +497,8 @@ public class LauncherStateManager { for (int i = mListeners.size() - 1; i >= 0; i--) { mListeners.get(i).onStateTransitionComplete(state); } + + AccessibilityManagerCompat.sendStateEventToTest(mLauncher, state.ordinal); } public void onWindowFocusChanged() { diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java index 4e5f7a59a9..6f53140eab 100644 --- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java +++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java @@ -43,7 +43,6 @@ import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.AnimatorSetBuilder; -import com.android.launcher3.compat.AccessibilityManagerCompat; import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; @@ -541,7 +540,6 @@ public abstract class AbstractStateChangeTouchController android.util.Log.e( TestProtocol.NO_ALLAPPS_EVENT_TAG, "onSwipeInteractionCompleted 2"); } - AccessibilityManagerCompat.sendStateEventToTest(mLauncher, targetState.ordinal); } } From f0d2e0064e3c49f3e4922bd952718c6ca242f790 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Tue, 11 Jun 2019 11:44:34 -0700 Subject: [PATCH 14/29] Fix potential NPE in BackgroundAppState Bug: 134559760 Change-Id: I08be7563ec8306ede6c0c7e62b0b5fc0a7c5f998 --- .../launcher3/uioverrides/states/BackgroundAppState.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java index f1d6450a5f..1c66968582 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java @@ -64,10 +64,12 @@ public class BackgroundAppState extends OverviewState { public ScaleAndTranslation getOverviewScaleAndTranslation(Launcher launcher) { // Initialize the recents view scale to what it would be when starting swipe up RecentsView recentsView = launcher.getOverviewPanel(); - if (recentsView.getTaskViewCount() == 0) { + int taskCount = recentsView.getTaskViewCount(); + if (taskCount == 0) { return super.getOverviewScaleAndTranslation(launcher); } - TaskView dummyTask = recentsView.getTaskViewAt(recentsView.getCurrentPage()); + TaskView dummyTask = recentsView.getTaskViewAt(Math.max(taskCount - 1, + recentsView.getCurrentPage())); return recentsView.getTempClipAnimationHelper().updateForFullscreenOverview(dummyTask) .getScaleAndTranslation(); } From 87cfe640c251d540750bdc3d4eee79c082ff5f0d Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Tue, 11 Jun 2019 12:56:39 -0700 Subject: [PATCH 15/29] Fix state/anim clobbering when touching down during recents animation Addresses 2 problems: - Set mLauncherTransitionController = null after ending it, to prevent a subsequent end from re-setting OVERVIEW state. - Cancel the shelf animation so that it doesn't clobber the animation to all apps (for instance). Bug: 134309036 Bug: 134309189 Change-Id: I019084a1ba38c6208a6256843cb5c4b6dbb4a662 --- .../com/android/quickstep/WindowTransformSwipeHandler.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java index 7d17f85f69..edeae81165 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -868,9 +868,7 @@ public class WindowTransformSwipeHandler @UiThread private InputConsumer createNewInputProxyHandler() { endRunningWindowAnim(); - if (mLauncherTransitionController != null) { - mLauncherTransitionController.getAnimationPlayer().end(); - } + endLauncherTransitionController(); if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) { // Hide the task view, if not already hidden setTargetAlphaProvider(WindowTransformSwipeHandler::getHiddenTargetAlpha); @@ -1312,6 +1310,7 @@ public class WindowTransformSwipeHandler } private void endLauncherTransitionController() { + setShelfState(ShelfAnimState.CANCEL, LINEAR, 0); if (mLauncherTransitionController != null) { mLauncherTransitionController.getAnimationPlayer().end(); mLauncherTransitionController = null; From 6594390a79bb00227370fd8ac03ff0228696805e Mon Sep 17 00:00:00 2001 From: Tracy Zhou Date: Tue, 11 Jun 2019 13:42:25 -0700 Subject: [PATCH 16/29] Check if RecentsView is null before setting live tile icon. Fixes: 134969824 Test: N/A Change-Id: Ibd6d8ec729c6809d385ea5f0153ae7ff376801b9 --- .../android/quickstep/TouchInteractionService.java | 12 ++++++++++++ .../src/com/android/quickstep/views/TaskView.java | 8 ++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java index 4a40c64f99..30178a685a 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -17,7 +17,12 @@ package com.android.quickstep; import static android.view.MotionEvent.ACTION_DOWN; +import static com.android.launcher3.config.FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM; +import static com.android.launcher3.config.FeatureFlags.APPLY_CONFIG_AT_RUNTIME; +import static com.android.launcher3.config.FeatureFlags.ENABLE_HINTS_IN_OVERVIEW; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; +import static com.android.launcher3.config.FeatureFlags.FAKE_LANDSCAPE_UI; +import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS; import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_INPUT_MONITOR; import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE; @@ -664,6 +669,13 @@ public class TouchInteractionService extends Service implements mSwipeSharedState.dump(" ", pw); } pw.println(" mConsumer=" + mConsumer.getName()); + pw.println("FeatureFlags:"); + pw.println(" APPLY_CONFIG_AT_RUNTIME=" + APPLY_CONFIG_AT_RUNTIME.get()); + pw.println(" QUICKSTEP_SPRINGS=" + QUICKSTEP_SPRINGS.get()); + pw.println(" ADAPTIVE_ICON_WINDOW_ANIM=" + ADAPTIVE_ICON_WINDOW_ANIM.get()); + pw.println(" ENABLE_QUICKSTEP_LIVE_TILE=" + ENABLE_QUICKSTEP_LIVE_TILE.get()); + pw.println(" ENABLE_HINTS_IN_OVERVIEW=" + ENABLE_HINTS_IN_OVERVIEW.get()); + pw.println(" FAKE_LANDSCAPE_UI=" + FAKE_LANDSCAPE_UI.get()); TOUCH_INTERACTION_LOG.dump("", pw); } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java index bf3e91ff68..e0a4bcad84 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java @@ -353,14 +353,15 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { mIconLoadRequest = iconCache.updateIconInBackground(mTask, (task) -> { setIcon(task.icon); - if (isRunningTask()) { + if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isRunningTask()) { getRecentsView().updateLiveTileIcon(task.icon); } mDigitalWellBeingToast.initialize( mTask, contentDescription -> { setContentDescription(contentDescription); - if (mDigitalWellBeingToast.getVisibility() == VISIBLE) { + if (mDigitalWellBeingToast.getVisibility() == VISIBLE + && getRecentsView() != null) { getRecentsView().onDigitalWellbeingToastShown(); } }); @@ -716,6 +717,9 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { } public boolean isRunningTask() { + if (getRecentsView() == null) { + return false; + } return this == getRecentsView().getRunningTaskView(); } From 0bdd28e2044b8123f5f5139f9914c56298fe6d62 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Tue, 11 Jun 2019 14:35:53 -0700 Subject: [PATCH 17/29] Fix double swipe on nav bar from an app Use normal OverviewInputConsumer instead of OverviewWithoutFocusInputConsumer if we are animating to launcher. This allows launcher to properly handle a second swipe in the nav region. Test: enable 2-button mode, double swipe up on nav bar to all apps Bug: 135050372 Change-Id: I0b96f6236bed4f9ac3284a921e4259e1b0d00c75 --- .../src/com/android/quickstep/TouchInteractionService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java index 4a40c64f99..d84adabe14 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -614,7 +614,7 @@ public class TouchInteractionService extends Service implements return InputConsumer.NO_OP; } - if (activity.getRootView().hasWindowFocus()) { + if (activity.getRootView().hasWindowFocus() || mSwipeSharedState.goingToLauncher) { return new OverviewInputConsumer(activity, mInputMonitorCompat, false /* startingInActivityBounds */); } else { From 91683e2bc87af332e75372d37b8c4eed15f940dd Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Tue, 11 Jun 2019 15:25:54 -0700 Subject: [PATCH 18/29] Tweak spring stiffness/damping for attaching recents Bug: 129985827 Change-Id: Ife70528a3cdc101260df3425ec0501b318d558e7 --- .../quickstep/LauncherActivityControllerHelper.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java index 7809e454a5..bb5efd008f 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java @@ -30,9 +30,6 @@ import static com.android.launcher3.anim.Interpolators.INSTANT; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.quickstep.WindowTransformSwipeHandler.RECENTS_ATTACH_DURATION; -import static androidx.dynamicanimation.animation.SpringForce.DAMPING_RATIO_LOW_BOUNCY; -import static androidx.dynamicanimation.animation.SpringForce.STIFFNESS_LOW; - import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; @@ -321,8 +318,8 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe if (mAttachToWindowTranslationXAnim == null) { mAttachToWindowTranslationXAnim = new SpringAnimation(recentsView, SpringAnimation.TRANSLATION_X).setSpring(new SpringForce() - .setDampingRatio(DAMPING_RATIO_LOW_BOUNCY) - .setStiffness(STIFFNESS_LOW)); + .setDampingRatio(0.8f) + .setStiffness(250)); } if (!recentsView.isShown() && animate) { recentsView.setTranslationX(fromTranslationX); From a36c8004edb2f2af1d896aae03d4fb55734e0205 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Tue, 11 Jun 2019 16:15:54 -0700 Subject: [PATCH 19/29] Reset the overview sysui state when returning to the previous task - Otherwise, it gets stuck until the next time launcher pauses/task launch Bug: 135008910 Change-Id: Ia0696d764522e36a4064583cb82003c1e9c0cb7a --- src/com/android/launcher3/BaseActivity.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java index 424ffde1ff..64550560ff 100644 --- a/src/com/android/launcher3/BaseActivity.java +++ b/src/com/android/launcher3/BaseActivity.java @@ -175,6 +175,10 @@ public abstract class BaseActivity extends Activity mActivityFlags &= ~ACTIVITY_STATE_STARTED & ~ACTIVITY_STATE_USER_ACTIVE; mForceInvisible = 0; super.onStop(); + + // Reset the overridden sysui flags used for the task-swipe launch animation, this is a + // catch all for if we do not get resumed (and therefore not paused below) + getSystemUiController().updateUiState(UI_STATE_OVERVIEW, 0); } @Override From a0f9110e5200f0d00114b8657d42fff074563d47 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 12 Jun 2019 00:17:53 -0700 Subject: [PATCH 20/29] Adding support for custom callback when starting ProxyActivity Bug: 133443741 Change-Id: Ifd6a289b7f49d52efe0767b600cecc2b460a87fc --- .../launcher3/proxy/StartActivityParams.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/quickstep/src/com/android/launcher3/proxy/StartActivityParams.java b/quickstep/src/com/android/launcher3/proxy/StartActivityParams.java index 1e8bd933f9..bee8bb8132 100644 --- a/quickstep/src/com/android/launcher3/proxy/StartActivityParams.java +++ b/quickstep/src/com/android/launcher3/proxy/StartActivityParams.java @@ -31,7 +31,7 @@ public class StartActivityParams implements Parcelable { private static final String TAG = "StartActivityParams"; - private final PendingIntent mCallback; + private final PendingIntent mPICallback; public final int requestCode; public Intent intent; @@ -44,13 +44,17 @@ public class StartActivityParams implements Parcelable { public Bundle options; public StartActivityParams(Activity activity, int requestCode) { - mCallback = activity.createPendingResult(requestCode, new Intent(), - PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT); + this(activity.createPendingResult(requestCode, new Intent(), + PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT), requestCode); + } + + public StartActivityParams(PendingIntent pendingIntent, int requestCode) { + this.mPICallback = pendingIntent; this.requestCode = requestCode; } private StartActivityParams(Parcel parcel) { - mCallback = parcel.readTypedObject(PendingIntent.CREATOR); + mPICallback = parcel.readTypedObject(PendingIntent.CREATOR); requestCode = parcel.readInt(); intent = parcel.readTypedObject(Intent.CREATOR); @@ -70,7 +74,7 @@ public class StartActivityParams implements Parcelable { @Override public void writeToParcel(Parcel parcel, int flags) { - parcel.writeTypedObject(mCallback, flags); + parcel.writeTypedObject(mPICallback, flags); parcel.writeInt(requestCode); parcel.writeTypedObject(intent, flags); @@ -84,7 +88,9 @@ public class StartActivityParams implements Parcelable { public void deliverResult(Context context, int resultCode, Intent data) { try { - mCallback.send(context, resultCode, data); + if (mPICallback != null) { + mPICallback.send(context, resultCode, data); + } } catch (CanceledException e) { Log.e(TAG, "Unable to send back result", e); } From a327e6a3d12d689abd5a2fa014fdfa60249eb4c7 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 12 Jun 2019 07:41:14 -0700 Subject: [PATCH 21/29] Initializing ActivityManagerWrapper before device unlock Bug: 134406364 Change-Id: I30339c3790efeaa60db7ea3cbae76d97474c16cc --- .../src/com/android/quickstep/TouchInteractionService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java index 30178a685a..a952db94ec 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -278,6 +278,7 @@ public class TouchInteractionService extends Service implements // Everything else should be initialized in initWhenUserUnlocked() below. mKM = getSystemService(KeyguardManager.class); mMainChoreographer = Choreographer.getInstance(); + mAM = ActivityManagerWrapper.getInstance(); if (UserManagerCompat.getInstance(this).isUserUnlocked(Process.myUserHandle())) { initWhenUserUnlocked(); @@ -404,7 +405,6 @@ public class TouchInteractionService extends Service implements } private void initWhenUserUnlocked() { - mAM = ActivityManagerWrapper.getInstance(); mRecentsModel = RecentsModel.INSTANCE.get(this); mOverviewComponentObserver = new OverviewComponentObserver(this); From a029a8b2d59a12720c09f778bb69d49d0d2cc7e2 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Mon, 10 Jun 2019 16:03:53 -0700 Subject: [PATCH 22/29] Bypass systemstate check when using shared state System state can change using the interaction, for eg: an app can enter immersive mode in the middle of quickswitch. Ignore such changes to prevent system gestures getting blocked by an app > Fixing nullpointer in device locked consumer construction when user is not locked yet > Creating a fallback resetGesture input consumer, which cancels any pending transition in case we missed to cancel it Bug: 134091263 Bug: 134406364 Change-Id: Iafc4e53691f50862b013ad9c4023839044cf1d72 --- .../android/quickstep/SwipeSharedState.java | 22 ++++++--- .../quickstep/TouchInteractionService.java | 27 ++++++----- .../inputconsumers/InputConsumer.java | 39 +++++++++------- .../ResetGestureInputConsumer.java | 45 +++++++++++++++++++ .../util/RecentsAnimationListenerSet.java | 22 ++++++--- .../util/SwipeAnimationTargetSet.java | 5 ++- 6 files changed, 121 insertions(+), 39 deletions(-) create mode 100644 quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java index 5a039cd905..6689ce3d78 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java @@ -15,8 +15,11 @@ */ package com.android.quickstep; +import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR; + import android.util.Log; +import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.util.Preconditions; import com.android.quickstep.util.RecentsAnimationListenerSet; @@ -29,7 +32,7 @@ import java.io.PrintWriter; */ public class SwipeSharedState implements SwipeAnimationListener { - private final OverviewComponentObserver mOverviewComponentObserver; + private OverviewComponentObserver mOverviewComponentObserver; private RecentsAnimationListenerSet mRecentsAnimationListener; private SwipeAnimationTargetSet mLastAnimationTarget; @@ -42,8 +45,8 @@ public class SwipeSharedState implements SwipeAnimationListener { public boolean recentsAnimationFinishInterrupted; public int nextRunningTaskId = -1; - public SwipeSharedState(OverviewComponentObserver overviewComponentObserver) { - mOverviewComponentObserver = overviewComponentObserver; + public void setOverviewComponentObserver(OverviewComponentObserver observer) { + mOverviewComponentObserver = observer; } @Override @@ -72,6 +75,12 @@ public class SwipeSharedState implements SwipeAnimationListener { private void clearListenerState() { if (mRecentsAnimationListener != null) { mRecentsAnimationListener.removeListener(this); + mRecentsAnimationListener.cancelListener(); + if (mLastAnimationRunning && mLastAnimationTarget != null) { + Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), + mLastAnimationTarget::cancelAnimation); + mLastAnimationTarget = null; + } } mRecentsAnimationListener = null; clearAnimationTarget(); @@ -98,9 +107,10 @@ public class SwipeSharedState implements SwipeAnimationListener { } clearListenerState(); - mRecentsAnimationListener = new RecentsAnimationListenerSet(mOverviewComponentObserver - .getActivityControlHelper().shouldMinimizeSplitScreen(), - this::onSwipeAnimationFinished); + boolean shouldMinimiseSplitScreen = mOverviewComponentObserver == null ? false + : mOverviewComponentObserver.getActivityControlHelper().shouldMinimizeSplitScreen(); + mRecentsAnimationListener = new RecentsAnimationListenerSet( + shouldMinimiseSplitScreen, this::onSwipeAnimationFinished); mRecentsAnimationListener.addListener(this); return mRecentsAnimationListener; } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java index 4a40c64f99..a3aeac3611 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -81,6 +81,7 @@ import com.android.quickstep.inputconsumers.InputConsumer; import com.android.quickstep.inputconsumers.OtherActivityInputConsumer; import com.android.quickstep.inputconsumers.OverviewInputConsumer; import com.android.quickstep.inputconsumers.OverviewWithoutFocusInputConsumer; +import com.android.quickstep.inputconsumers.ResetGestureInputConsumer; import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer; import com.android.systemui.shared.recents.IOverviewProxy; import com.android.systemui.shared.recents.ISystemUiProxy; @@ -224,6 +225,10 @@ public class TouchInteractionService extends Service implements return sConnected; } + private final SwipeSharedState mSwipeSharedState = new SwipeSharedState(); + private final InputConsumer mResetGestureInputConsumer = + new ResetGestureInputConsumer(mSwipeSharedState); + private KeyguardManager mKM; private ActivityManagerWrapper mAM; private RecentsModel mRecentsModel; @@ -234,7 +239,6 @@ public class TouchInteractionService extends Service implements private OverviewCallbacks mOverviewCallbacks; private TaskOverlayFactory mTaskOverlayFactory; private InputConsumerController mInputConsumer; - private SwipeSharedState mSwipeSharedState; private boolean mAssistantAvailable; private float mLastAssistantVisibility = 0; private @SystemUiStateFlags int mSystemUiStateFlags; @@ -407,10 +411,10 @@ public class TouchInteractionService extends Service implements mOverviewInteractionState = OverviewInteractionState.INSTANCE.get(this); mOverviewCallbacks = OverviewCallbacks.get(this); mTaskOverlayFactory = TaskOverlayFactory.INSTANCE.get(this); - mSwipeSharedState = new SwipeSharedState(mOverviewComponentObserver); mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer(); mIsUserUnlocked = true; + mSwipeSharedState.setOverviewComponentObserver(mOverviewComponentObserver); mInputConsumer.registerInputConsumer(); onSystemUiProxySet(); onSystemUiFlagsChanged(); @@ -508,12 +512,14 @@ public class TouchInteractionService extends Service implements // launched while device is locked even after exiting direct boot mode (e.g. camera). return createDeviceLockedInputConsumer(mAM.getRunningTask(0)); } else { - return InputConsumer.NO_OP; + return mResetGestureInputConsumer; } } - InputConsumer base = isInValidSystemUiState - ? newBaseConsumer(useSharedState, event) : InputConsumer.NO_OP; + // When using sharedState, bypass systemState check as this is a followup gesture and the + // first gesture started in a valid system state. + InputConsumer base = isInValidSystemUiState || useSharedState + ? newBaseConsumer(useSharedState, event) : mResetGestureInputConsumer; if (mMode == Mode.NO_BUTTON) { final ActivityControlHelper activityControl = mOverviewComponentObserver.getActivityControlHelper(); @@ -558,7 +564,7 @@ public class TouchInteractionService extends Service implements if (runningTaskInfo == null && !mSwipeSharedState.goingToLauncher && !mSwipeSharedState.recentsAnimationFinishInterrupted) { - return InputConsumer.NO_OP; + return mResetGestureInputConsumer; } else if (mSwipeSharedState.recentsAnimationFinishInterrupted) { // If the finish animation was interrupted, then continue using the other activity input // consumer but with the next task as the running task @@ -571,7 +577,7 @@ public class TouchInteractionService extends Service implements return createOverviewInputConsumer(event); } else if (mGestureBlockingActivity != null && runningTaskInfo != null && mGestureBlockingActivity.equals(runningTaskInfo.topActivity)) { - return InputConsumer.NO_OP; + return mResetGestureInputConsumer; } else { return createOtherActivityInputConsumer(event, runningTaskInfo); } @@ -602,7 +608,7 @@ public class TouchInteractionService extends Service implements return new DeviceLockedInputConsumer(this, mSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion, taskInfo.taskId); } else { - return InputConsumer.NO_OP; + return mResetGestureInputConsumer; } } @@ -611,7 +617,7 @@ public class TouchInteractionService extends Service implements mOverviewComponentObserver.getActivityControlHelper(); BaseDraggingActivity activity = activityControl.getCreatedActivity(); if (activity == null) { - return InputConsumer.NO_OP; + return mResetGestureInputConsumer; } if (activity.getRootView().hasWindowFocus()) { @@ -628,7 +634,8 @@ public class TouchInteractionService extends Service implements */ private void onConsumerInactive(InputConsumer caller) { if (mConsumer == caller) { - mConsumer = InputConsumer.NO_OP; + mConsumer = mResetGestureInputConsumer; + mUncheckedConsumer = mConsumer; } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java index 489eb278fd..a1e5d47a53 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java @@ -32,6 +32,19 @@ public interface InputConsumer { int TYPE_ACCESSIBILITY = 1 << 5; int TYPE_SCREEN_PINNED = 1 << 6; int TYPE_OVERVIEW_WITHOUT_FOCUS = 1 << 7; + int TYPE_RESET_GESTURE = 1 << 8; + + String[] NAMES = new String[] { + "TYPE_NO_OP", // 0 + "TYPE_OVERVIEW", // 1 + "TYPE_OTHER_ACTIVITY", // 2 + "TYPE_ASSISTANT", // 3 + "TYPE_DEVICE_LOCKED", // 4 + "TYPE_ACCESSIBILITY", // 5 + "TYPE_SCREEN_PINNED", // 6 + "TYPE_OVERVIEW_WITHOUT_FOCUS", // 7 + "TYPE_RESET_GESTURE", // 8 + }; InputConsumer NO_OP = () -> TYPE_NO_OP; @@ -66,23 +79,15 @@ public interface InputConsumer { } default String getName() { - switch (getType()) { - case TYPE_OVERVIEW: - return "OVERVIEW"; - case TYPE_OTHER_ACTIVITY: - return "OTHER_ACTIVITY"; - case TYPE_ASSISTANT: - return "ASSISTANT"; - case TYPE_DEVICE_LOCKED: - return "DEVICE_LOCKED"; - case TYPE_ACCESSIBILITY: - return "ACCESSIBILITY"; - case TYPE_SCREEN_PINNED: - return "SCREEN_PINNED"; - case TYPE_OVERVIEW_WITHOUT_FOCUS: - return "TYPE_OVERVIEW_WITHOUT_FOCUS"; - default: - return "NO_OP"; + String name = ""; + for (int i = 0; i < NAMES.length; i++) { + if ((getType() & (1 << i)) != 0) { + if (name.length() > 0) { + name += ":"; + } + name += NAMES[i]; + } } + return name; } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java new file mode 100644 index 0000000000..56cba2192a --- /dev/null +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.quickstep.inputconsumers; + +import android.view.MotionEvent; + +import com.android.quickstep.SwipeSharedState; + +/** + * A NO_OP input consumer which also resets any pending gesture + */ +public class ResetGestureInputConsumer implements InputConsumer { + + private final SwipeSharedState mSwipeSharedState; + + public ResetGestureInputConsumer(SwipeSharedState swipeSharedState) { + mSwipeSharedState = swipeSharedState; + } + + @Override + public int getType() { + return TYPE_RESET_GESTURE; + } + + @Override + public void onMotionEvent(MotionEvent ev) { + if (ev.getAction() == MotionEvent.ACTION_DOWN + && mSwipeSharedState.getActiveListener() != null) { + mSwipeSharedState.clearAllState(); + } + } +} diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java index 94e704a716..83601e6175 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java @@ -49,6 +49,8 @@ public class RecentsAnimationListenerSet implements RecentsAnimationListener { private final Consumer mOnFinishListener; private RecentsAnimationControllerCompat mController; + private boolean mCancelled; + public RecentsAnimationListenerSet(boolean shouldMinimizeSplitScreen, Consumer onFinishListener) { mShouldMinimizeSplitScreen = shouldMinimizeSplitScreen; @@ -75,11 +77,16 @@ public class RecentsAnimationListenerSet implements RecentsAnimationListener { SwipeAnimationTargetSet targetSet = new SwipeAnimationTargetSet(controller, targets, homeContentInsets, minimizedHomeBounds, mShouldMinimizeSplitScreen, mOnFinishListener); - Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), () -> { - for (SwipeAnimationListener listener : getListeners()) { - listener.onRecentsAnimationStart(targetSet); - } - }); + + if (mCancelled) { + targetSet.cancelAnimation(); + } else { + Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), () -> { + for (SwipeAnimationListener listener : getListeners()) { + listener.onRecentsAnimationStart(targetSet); + } + }); + } } @Override @@ -99,4 +106,9 @@ public class RecentsAnimationListenerSet implements RecentsAnimationListener { private SwipeAnimationListener[] getListeners() { return mListeners.toArray(new SwipeAnimationListener[mListeners.size()]); } + + public void cancelListener() { + mCancelled = true; + onAnimationCanceled(false); + } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java index f5a9e8a058..df9efa2477 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java @@ -36,7 +36,6 @@ public class SwipeAnimationTargetSet extends RemoteAnimationTargetSet { private final boolean mShouldMinimizeSplitScreen; private final Consumer mOnFinishListener; - public final RecentsAnimationControllerCompat controller; public final Rect homeContentInsets; public final Rect minimizedHomeBounds; @@ -103,6 +102,10 @@ public class SwipeAnimationTargetSet extends RemoteAnimationTargetSet { return controller != null ? controller.screenshotTask(taskId) : null; } + public void cancelAnimation() { + finishController(false /* toRecents */, null, false /* sendUserLeaveHint */); + } + public interface SwipeAnimationListener { void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet); From d0308dbd144fb6714c59cfa41caa4fdfe7896045 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 12 Jun 2019 09:10:31 -0700 Subject: [PATCH 23/29] Resetting taskView alpha to proper value onAnimationEnd Bug: 135114549 Change-Id: I4effc4c9d8e6c03e41c8f06c441477076ce7a622 --- .../src/com/android/quickstep/views/RecentsView.java | 4 ++-- .../src/com/android/quickstep/views/TaskView.java | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index 90e123e847..f66e401f9a 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -892,7 +892,7 @@ public abstract class RecentsView extends PagedView impl mRunningTaskTileHidden = isHidden; TaskView runningTask = getRunningTaskView(); if (runningTask != null) { - runningTask.setAlpha(isHidden ? 0 : mContentAlpha); + runningTask.setStableAlpha(isHidden ? 0 : mContentAlpha); } } @@ -1294,7 +1294,7 @@ public abstract class RecentsView extends PagedView impl for (int i = getTaskViewCount() - 1; i >= 0; i--) { TaskView child = getTaskViewAt(i); if (!mRunningTaskTileHidden || child.getTask().key.id != mRunningTaskId) { - getChildAt(i).setAlpha(alpha); + child.setStableAlpha(alpha); } } mClearAllButton.setContentAlpha(mContentAlpha); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java index e0a4bcad84..354241b0cd 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java @@ -163,6 +163,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { private ObjectAnimator mIconAndDimAnimator; private float mIconScaleAnimStartProgress = 0; private float mFocusTransitionProgress = 1; + private float mStableAlpha = 1; private boolean mShowScreenshot; @@ -469,7 +470,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { setTranslationX(0f); setTranslationY(0f); setTranslationZ(0); - setAlpha(1f); + setAlpha(mStableAlpha); setIconScaleAndDim(1); } @@ -478,6 +479,11 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { setFullscreenProgress(0); } + public void setStableAlpha(float parentAlpha) { + mStableAlpha = parentAlpha; + setAlpha(mStableAlpha); + } + @Override public void onRecycle() { resetViewTransforms(); From c8502c1df5c236fa2ab58b5618bfc2c18cb84d37 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Mon, 10 Jun 2019 12:14:47 -0700 Subject: [PATCH 24/29] Do not rebind when when deviceProfile has not changed This avoids UI flicker when using fakeLandscape UI during swipe-up animation Bug: 131360075 Change-Id: I651e0acb79b54be66b93c746eed6e9b099f2f767 --- src/com/android/launcher3/Launcher.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 2c9a37a65c..4e905c7265 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -461,6 +461,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, private void onIdpChanged(InvariantDeviceProfile idp) { mUserEventDispatcher = null; + DeviceProfile oldWallpaperProfile = getWallpaperDeviceProfile(); initDeviceProfile(idp); dispatchDeviceProfileChanged(); reapplyUi(); @@ -469,8 +470,9 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, // Calling onSaveInstanceState ensures that static cache used by listWidgets is // initialized properly. onSaveInstanceState(new Bundle()); - // TODO: We can probably avoid rebind when only screen size changed. - rebindModel(); + if (oldWallpaperProfile != getWallpaperDeviceProfile()) { + rebindModel(); + } } public void onAssistantVisibilityChanged(float visibility) { From 022b18263468282979e84fd8864bee4f67919f2d Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 12 Jun 2019 08:44:09 -0700 Subject: [PATCH 25/29] Updating consumed insets when dispatching to child views Bug: 134963243 Change-Id: I4fa072128398cfd22b906037c6c444495781c9d0 --- .../android/launcher3/LauncherRootView.java | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java index 49b380b41f..f964b8d9ee 100644 --- a/src/com/android/launcher3/LauncherRootView.java +++ b/src/com/android/launcher3/LauncherRootView.java @@ -8,18 +8,22 @@ import android.app.ActivityManager; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Insets; import android.graphics.Paint; import android.graphics.Rect; import android.os.Build; import android.util.AttributeSet; import android.view.View; import android.view.ViewDebug; +import android.view.WindowInsets; import java.util.Collections; import java.util.List; public class LauncherRootView extends InsettableFrameLayout { + private final Rect mTempRect = new Rect(); + private final Launcher mLauncher; private final Paint mOpaquePaint; @@ -56,9 +60,7 @@ public class LauncherRootView extends InsettableFrameLayout { super.onFinishInflate(); } - @TargetApi(23) - @Override - protected boolean fitSystemWindows(Rect insets) { + private void handleSystemWindowInsets(Rect insets) { mConsumedInsets.setEmpty(); boolean drawInsetBar = false; if (mLauncher.isInMultiWindowMode() @@ -66,13 +68,13 @@ public class LauncherRootView extends InsettableFrameLayout { mConsumedInsets.left = insets.left; mConsumedInsets.right = insets.right; mConsumedInsets.bottom = insets.bottom; - insets = new Rect(0, insets.top, 0, 0); + insets.set(0, insets.top, 0, 0); drawInsetBar = true; } else if ((insets.right > 0 || insets.left > 0) && getContext().getSystemService(ActivityManager.class).isLowRamDevice()) { mConsumedInsets.left = insets.left; mConsumedInsets.right = insets.right; - insets = new Rect(0, insets.top, 0, insets.bottom); + insets.set(0, insets.top, 0, insets.bottom); drawInsetBar = true; } @@ -99,8 +101,19 @@ public class LauncherRootView extends InsettableFrameLayout { if (resetState) { mLauncher.getStateManager().reapplyState(true /* cancelCurrentAnimation */); } + } - return false; // Let children get the full insets + @Override + public WindowInsets onApplyWindowInsets(WindowInsets insets) { + mTempRect.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), + insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom()); + handleSystemWindowInsets(mTempRect); + if (Utilities.ATLEAST_Q) { + return insets.inset(mConsumedInsets.left, mConsumedInsets.top, + mConsumedInsets.right, mConsumedInsets.bottom); + } else { + return insets.replaceSystemWindowInsets(mTempRect); + } } @Override From e8836dc0823a4b7115f2bc7b5f93c4d6b8cc9f7a Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Tue, 11 Jun 2019 18:31:15 -0700 Subject: [PATCH 26/29] Gracefully handle failed task launches during quick switch When quick switching from home or overview, go to OverviewState if the task launch failed. Otherwise we get stuck in BackgroundAppState. Bug: 135038270 Change-Id: I42785c261cef0df95666bc106ec5ca6ef0553cc7 --- .../quickstep/GoActivityControlHelper.java | 5 +++++ .../uioverrides/states/QuickSwitchState.java | 12 +++++++++++- .../FallbackActivityControllerHelper.java | 6 ++++++ .../LauncherActivityControllerHelper.java | 5 +++++ .../quickstep/WindowTransformSwipeHandler.java | 15 ++++++++++++++- .../android/quickstep/ActivityControlHelper.java | 2 ++ 6 files changed, 43 insertions(+), 2 deletions(-) diff --git a/go/quickstep/src/com/android/quickstep/GoActivityControlHelper.java b/go/quickstep/src/com/android/quickstep/GoActivityControlHelper.java index 2db8b39d94..274a347cbb 100644 --- a/go/quickstep/src/com/android/quickstep/GoActivityControlHelper.java +++ b/go/quickstep/src/com/android/quickstep/GoActivityControlHelper.java @@ -61,4 +61,9 @@ public abstract class GoActivityControlHelper im // Go does not support live tiles. return false; } + + @Override + public void onLaunchTaskFailed(T activity) { + // Go does not support gestures from one task to another. + } } diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java index ed511f5f2f..cdc271fdd3 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java @@ -15,6 +15,9 @@ */ package com.android.launcher3.uioverrides.states; +import android.os.Handler; +import android.os.Looper; + import com.android.launcher3.Launcher; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.quickstep.views.RecentsView; @@ -27,6 +30,8 @@ import com.android.quickstep.views.TaskView; */ public class QuickSwitchState extends BackgroundAppState { + private static final String TAG = "QuickSwitchState"; + public QuickSwitchState(int id) { super(id, LauncherLogProto.ContainerType.APP); } @@ -48,7 +53,12 @@ public class QuickSwitchState extends BackgroundAppState { public void onStateTransitionEnd(Launcher launcher) { TaskView tasktolaunch = launcher.getOverviewPanel().getTaskViewAt(0); if (tasktolaunch != null) { - tasktolaunch.launchTask(false); + tasktolaunch.launchTask(false, success -> { + if (!success) { + launcher.getStateManager().goToState(OVERVIEW); + tasktolaunch.notifyTaskLaunchFailed(TAG); + } + }, new Handler(Looper.getMainLooper())); } else { launcher.getStateManager().goToState(NORMAL); } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java index 2c42fd63a6..4ae6d87b8d 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java @@ -224,4 +224,10 @@ public final class FallbackActivityControllerHelper implements public boolean isInLiveTileMode() { return false; } + + @Override + public void onLaunchTaskFailed(RecentsActivity activity) { + // TODO: probably go back to overview instead. + activity.getOverviewPanel().startHome(); + } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java index 7809e454a5..5449b47e0d 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java @@ -512,4 +512,9 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe return launcher != null && launcher.getStateManager().getState() == OVERVIEW && launcher.isStarted(); } + + @Override + public void onLaunchTaskFailed(Launcher launcher) { + launcher.getStateManager().goToState(OVERVIEW); + } } \ No newline at end of file diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java index 7d17f85f69..06abb80188 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -746,6 +746,9 @@ public class WindowTransformSwipeHandler ? 0 : (progress - mShiftAtGestureStart) / (1 - mShiftAtGestureStart)); } + /** + * @param windowProgress 0 == app, 1 == overview + */ private void updateSysUiFlags(float windowProgress) { if (mRecentsView != null) { TaskView centermostTask = mRecentsView.getTaskViewAt(mRecentsView @@ -1249,7 +1252,17 @@ public class WindowTransformSwipeHandler if (!mCanceled) { TaskView nextTask = mRecentsView.getTaskView(taskId); if (nextTask != null) { - nextTask.launchTask(false /* animate */, true /* freezeTaskList */); + nextTask.launchTask(false /* animate */, true /* freezeTaskList */, + success -> { + if (!success) { + // We couldn't launch the task, so take user to overview so they can + // decide what to do instead of staying in this broken state. + endLauncherTransitionController(); + mActivityControlHelper.onLaunchTaskFailed(mActivity); + nextTask.notifyTaskLaunchFailed(TAG); + updateSysUiFlags(1 /* windowProgress == overview */); + } + }, mMainThreadHandler); doLogGesture(NEW_TASK); } reset(); diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java index dcc1ace883..8675c3e02e 100644 --- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java +++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java @@ -93,6 +93,8 @@ public interface ActivityControlHelper { boolean isInLiveTileMode(); + void onLaunchTaskFailed(T activity); + interface ActivityInitListener { void register(); From 87fbd33a3702bc77a68a824dd1e36d4010574767 Mon Sep 17 00:00:00 2001 From: vadimt Date: Wed, 12 Jun 2019 15:26:27 -0700 Subject: [PATCH 27/29] Not using settings app in tests Change-Id: I7542dab07a0d5a76cc90f4b5eee0d376b5d8ca11 --- .../tests/src/com/android/quickstep/FallbackRecentsTest.java | 3 ++- tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java index 20fdff2c55..013591171c 100644 --- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java +++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java @@ -22,6 +22,7 @@ import static androidx.test.InstrumentationRegistry.getInstrumentation; import static com.android.launcher3.tapl.LauncherInstrumentation.WAIT_TIME_MS; import static com.android.launcher3.tapl.TestHelpers.getHomeIntentInPackage; import static com.android.launcher3.tapl.TestHelpers.getLauncherInMyProcess; +import static com.android.launcher3.ui.AbstractLauncherUiTest.resolveSystemApp; import static com.android.launcher3.util.rule.ShellCommandRule.disableHeadsUpNotification; import static com.android.launcher3.util.rule.ShellCommandRule.getLauncherCommand; import static com.android.quickstep.NavigationModeSwitchRule.Mode.THREE_BUTTON; @@ -108,7 +109,7 @@ public class FallbackRecentsTest { @NavigationModeSwitch(mode = THREE_BUTTON) @Test public void goToOverviewFromApp() { - startAppFast("com.android.settings"); + startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR)); mLauncher.getBackground().switchToOverview(); } diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index 64fe2d7d79..abc93cd4b7 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -395,7 +395,7 @@ public abstract class AbstractLauncherUiTest { DEFAULT_UI_TIMEOUT)); } - protected static String resolveSystemApp(String category) { + public static String resolveSystemApp(String category) { return getInstrumentation().getContext().getPackageManager().resolveActivity( new Intent(Intent.ACTION_MAIN).addCategory(category), PackageManager.MATCH_SYSTEM_ONLY). From 16284b956c6f185c1b3d65d9cfcdaeecd8a455ac Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 12 Jun 2019 15:27:33 -0700 Subject: [PATCH 28/29] Fading out the home surface if home and recents are shown in separate surface Bug: 134725160 Change-Id: Ia4c5e0eefc4d8b869840645f403d943831c471f1 --- .../src/com/android/quickstep/util/ClipAnimationHelper.java | 6 +++++- .../android/quickstep/util/RemoteAnimationTargetSet.java | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java index aca23e4e40..de671e04aa 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java @@ -192,6 +192,7 @@ public class ClipAnimationHelper { float cornerRadius = 0f; float scale = Math.max(params.currentRect.width(), mTargetRect.width()) / crop.width(); if (app.mode == targetSet.targetMode) { + alpha = mTaskAlphaCallback.apply(app, params.targetAlpha); if (app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) { mTmpMatrix.setRectToRect(mSourceRect, params.currentRect, ScaleToFit.FILL); mTmpMatrix.postTranslate(app.position.x, app.position.y); @@ -208,8 +209,11 @@ public class ClipAnimationHelper { } mCurrentCornerRadius = cornerRadius; } + } else if (targetSet.hasRecents) { + // If home has a different target then recents, reverse anim the + // home target. + alpha = 1 - (progress * params.targetAlpha); } - alpha = mTaskAlphaCallback.apply(app, params.targetAlpha); } else if (ENABLE_QUICKSTEP_LIVE_TILE.get() && launcherOnTop) { crop = null; layer = Integer.MAX_VALUE; diff --git a/quickstep/src/com/android/quickstep/util/RemoteAnimationTargetSet.java b/quickstep/src/com/android/quickstep/util/RemoteAnimationTargetSet.java index 0df4e947d3..1229293e6e 100644 --- a/quickstep/src/com/android/quickstep/util/RemoteAnimationTargetSet.java +++ b/quickstep/src/com/android/quickstep/util/RemoteAnimationTargetSet.java @@ -33,20 +33,26 @@ public class RemoteAnimationTargetSet { public final RemoteAnimationTargetCompat[] unfilteredApps; public final RemoteAnimationTargetCompat[] apps; public final int targetMode; + public final boolean hasRecents; public RemoteAnimationTargetSet(RemoteAnimationTargetCompat[] apps, int targetMode) { ArrayList filteredApps = new ArrayList<>(); + boolean hasRecents = false; if (apps != null) { for (RemoteAnimationTargetCompat target : apps) { if (target.mode == targetMode) { filteredApps.add(target); } + + hasRecents |= target.activityType == + RemoteAnimationTargetCompat.ACTIVITY_TYPE_RECENTS; } } this.unfilteredApps = apps; this.apps = filteredApps.toArray(new RemoteAnimationTargetCompat[filteredApps.size()]); this.targetMode = targetMode; + this.hasRecents = hasRecents; } public RemoteAnimationTargetCompat findTask(int taskId) { From 3827b3afd391fc91161b2aee3c45f1f57a48556b Mon Sep 17 00:00:00 2001 From: Zak Cohen Date: Wed, 12 Jun 2019 15:40:54 -0700 Subject: [PATCH 29/29] Expose getTaskView to Overlays. Test: Manual Change-Id: Ie8583606e65f9a77536de4a7cbd1aa3d88e81e1e --- .../src/com/android/quickstep/TaskOverlayFactory.java | 3 ++- .../src/com/android/quickstep/views/TaskThumbnailView.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java index 5104fb8801..b90f6c2b17 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java @@ -24,6 +24,7 @@ import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.R; import com.android.launcher3.util.MainThreadInitializedObject; import com.android.launcher3.util.ResourceBasedOverride; +import com.android.quickstep.views.TaskThumbnailView; import com.android.quickstep.views.TaskView; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; @@ -62,7 +63,7 @@ public class TaskOverlayFactory implements ResourceBasedOverride { return shortcuts; } - public TaskOverlay createOverlay(View thumbnailView) { + public TaskOverlay createOverlay(TaskThumbnailView thumbnailView) { return new TaskOverlay(); } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java index 8b8240d0a5..6f10b42fba 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java @@ -252,7 +252,7 @@ public class TaskThumbnailView extends View { } } - protected TaskView getTaskView() { + public TaskView getTaskView() { return (TaskView) getParent(); }