diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java index 764b0d3c7b..829e072a52 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -128,7 +128,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController { @Override protected boolean isTaskbarTouchable() { - return !isAnimatingToLauncher() && !mControllers.taskbarStashController.isStashed(); + return !isAnimatingToLauncher(); } private boolean isAnimatingToLauncher() { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java index b7c5db2f17..567a0c765a 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java @@ -135,8 +135,9 @@ public class TaskbarDragLayerController { } else if (!mControllers.uiController.isTaskbarTouchable()) { // Let touches pass through us. insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION); - } else if (mControllers.taskbarViewController.areIconsVisible()) { - // Buttons are visible, take over the full taskbar area + } else if (mControllers.taskbarViewController.areIconsVisible() + || AbstractFloatingView.getOpenView(mActivity, TYPE_ALL) != null) { + // Taskbar has some touchable elements, take over the full taskbar area insetsInfo.setTouchableInsets(mActivity.isTaskbarWindowFullscreen() ? TOUCHABLE_INSETS_FRAME : TOUCHABLE_INSETS_CONTENT); } else { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java index 453bf1cabd..2e9d8bcd0c 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java @@ -24,6 +24,7 @@ import static com.android.launcher3.util.DisplayController.CHANGE_SUPPORTED_BOUN import android.content.ComponentCallbacks; import android.content.Context; +import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.hardware.display.DisplayManager; @@ -41,6 +42,7 @@ import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.DisplayController.Info; import com.android.launcher3.util.SettingsCache; +import com.android.launcher3.util.SimpleBroadcastReceiver; import com.android.quickstep.SysUINavigationMode; import com.android.quickstep.SysUINavigationMode.Mode; import com.android.quickstep.SystemUiProxy; @@ -62,6 +64,7 @@ public class TaskbarManager implements DisplayController.DisplayInfoChangeListen private final TaskbarNavButtonController mNavButtonController; private final SettingsCache.OnChangeListener mUserSetupCompleteListener; private final ComponentCallbacks mComponentCallbacks; + private final SimpleBroadcastReceiver mShutdownReceiver; // The source for this provider is set when Launcher is available private final ScopedUnfoldTransitionProgressProvider mUnfoldProgressProvider = @@ -103,12 +106,14 @@ public class TaskbarManager implements DisplayController.DisplayInfoChangeListen @Override public void onLowMemory() { } }; + mShutdownReceiver = new SimpleBroadcastReceiver(i -> destroyExistingTaskbar()); mDisplayController.addChangeListener(this); mSysUINavigationMode.addModeChangeListener(this); SettingsCache.INSTANCE.get(mContext).register(USER_SETUP_COMPLETE_URI, mUserSetupCompleteListener); mContext.registerComponentCallbacks(mComponentCallbacks); + mShutdownReceiver.register(mContext, Intent.ACTION_SHUTDOWN); recreateTaskbar(); } @@ -231,6 +236,7 @@ public class TaskbarManager implements DisplayController.DisplayInfoChangeListen SettingsCache.INSTANCE.get(mContext).unregister(USER_SETUP_COMPLETE_URI, mUserSetupCompleteListener); mContext.unregisterComponentCallbacks(mComponentCallbacks); + mContext.unregisterReceiver(mShutdownReceiver); } public @Nullable TaskbarActivityContext getCurrentActivityContext() { diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 1e841da40b..fff89156cd 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -270,7 +270,7 @@ public abstract class AbsSwipeUpHandler, TaskAnimationManager taskAnimationManager, GestureState gestureState, long touchTimeMs, boolean continuingLastGesture, InputConsumerController inputConsumer) { - super(context, deviceState, gestureState, new TransformParams()); + super(context, deviceState, gestureState); mActivityInterface = gestureState.getActivityInterface(); mActivityInitListener = mActivityInterface.createActivityInitListener(this::onActivityInit); mInputConsumerProxy = diff --git a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java index ebe46fecab..d1880189cc 100644 --- a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java +++ b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java @@ -80,7 +80,7 @@ public abstract class SwipeUpAnimationLogic implements protected boolean mIsSwipeForStagedSplit; public SwipeUpAnimationLogic(Context context, RecentsAnimationDeviceState deviceState, - GestureState gestureState, TransformParams transformParams) { + GestureState gestureState) { mContext = context; mDeviceState = deviceState; mGestureState = gestureState; diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java index 1f75936dd4..ce8047ec9e 100644 --- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java +++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java @@ -50,6 +50,7 @@ import com.android.quickstep.AnimatedFloat; import com.android.quickstep.GestureState; import com.android.quickstep.OverviewComponentObserver; import com.android.quickstep.RecentsAnimationDeviceState; +import com.android.quickstep.RemoteTargetGluer; import com.android.quickstep.SwipeUpAnimationLogic; import com.android.quickstep.SwipeUpAnimationLogic.RunningWindowAnim; import com.android.quickstep.util.AppCloseConfig; @@ -254,7 +255,9 @@ abstract class SwipeUpGestureTutorialController extends TutorialController { ViewSwipeUpAnimation(Context context, RecentsAnimationDeviceState deviceState, GestureState gestureState) { - super(context, deviceState, gestureState, new FakeTransformParams()); + super(context, deviceState, gestureState); + mRemoteTargetHandles[0] = new RemoteTargetGluer.RemoteTargetHandle( + mRemoteTargetHandles[0].getTaskViewSimulator(), new FakeTransformParams()); } void initDp(DeviceProfile dp) { diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java index 85627191c0..16303f3a02 100644 --- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java +++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java @@ -31,6 +31,7 @@ public class GroupedTaskView extends TaskView { private Task mSecondaryTask; private TaskThumbnailView mSnapshotView2; private CancellableTask mThumbnailLoadRequest2; + private SplitConfigurationOptions.StagedSplitBounds mSplitBoundsConfig; public GroupedTaskView(Context context) { super(context); @@ -57,7 +58,7 @@ public class GroupedTaskView extends TaskView { mTaskIdContainer[1] = secondary.key.id; mTaskIdAttributeContainer[1] = new TaskIdAttributeContainer(secondary, mSnapshotView2); mSnapshotView2.bind(secondary); - adjustThumbnailBoundsForSplit(splitBoundsConfig, orientedState); + mSplitBoundsConfig = splitBoundsConfig; } @Override @@ -121,6 +122,21 @@ public class GroupedTaskView extends TaskView { public void onRecycle() { super.onRecycle(); mSnapshotView2.setThumbnail(mSecondaryTask, null); + mSplitBoundsConfig = null; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + setMeasuredDimension(widthSize, heightSize); + if (mSplitBoundsConfig == null || mSnapshotView == null || mSnapshotView2 == null) { + return; + } + getPagedOrientationHandler().measureGroupedTaskViewThumbnailBounds(mSnapshotView, + mSnapshotView2, widthSize, heightSize, mSplitBoundsConfig, + mActivity.getDeviceProfile()); } @Override @@ -128,16 +144,4 @@ public class GroupedTaskView extends TaskView { super.setOverlayEnabled(overlayEnabled); mSnapshotView2.setOverlayEnabled(overlayEnabled); } - - private void adjustThumbnailBoundsForSplit( - SplitConfigurationOptions.StagedSplitBounds splitBoundsConfig, - RecentsOrientedState orientedState) { - if (splitBoundsConfig == null) { - return; - } - - orientedState.getOrientationHandler().setGroupedTaskViewThumbnailBounds( - mSnapshotView, mSnapshotView2, this, splitBoundsConfig, - mActivity.getDeviceProfile()); - } } diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index dd470e87d0..3ed7b066fd 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -3150,7 +3150,7 @@ public abstract class RecentsView 1 ); } diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java index 895ca08510..2ac6cea636 100644 --- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java +++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java @@ -408,22 +408,30 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { } @Override - public void setGroupedTaskViewThumbnailBounds(View mSnapshotView, View mSnapshotView2, - View taskParent, SplitConfigurationOptions.StagedSplitBounds splitBoundsConfig, - DeviceProfile dp) { + public void measureGroupedTaskViewThumbnailBounds(View primarySnapshot, View secondarySnapshot, + int parentWidth, int parentHeight, + SplitConfigurationOptions.StagedSplitBounds splitBoundsConfig, DeviceProfile dp) { int spaceAboveSnapshot = dp.overviewTaskThumbnailTopMarginPx; - int totalThumbnailHeight = taskParent.getHeight() - spaceAboveSnapshot; - int totalThumbnailWidth = taskParent.getWidth(); + int totalThumbnailHeight = parentHeight - spaceAboveSnapshot; int dividerBar = splitBoundsConfig.visualDividerBounds.width(); - ViewGroup.LayoutParams primaryLp = mSnapshotView.getLayoutParams(); - ViewGroup.LayoutParams secondaryLp = mSnapshotView2.getLayoutParams(); + int primarySnapshotHeight; + int primarySnapshotWidth; + int secondarySnapshotHeight; + int secondarySnapshotWidth; - primaryLp.width = totalThumbnailWidth; - primaryLp.height = (int) (totalThumbnailHeight * splitBoundsConfig.leftTaskPercent); + primarySnapshotWidth = parentWidth; + primarySnapshotHeight = (int) (totalThumbnailHeight * splitBoundsConfig.leftTaskPercent); - secondaryLp.width = totalThumbnailWidth; - secondaryLp.height = totalThumbnailHeight - primaryLp.height - dividerBar; - mSnapshotView2.setTranslationY(primaryLp.height + spaceAboveSnapshot + dividerBar); + secondarySnapshotWidth = parentWidth; + secondarySnapshotHeight = totalThumbnailHeight - primarySnapshotHeight - dividerBar; + secondarySnapshot.setTranslationY(primarySnapshotHeight + spaceAboveSnapshot + dividerBar); + primarySnapshot.measure( + View.MeasureSpec.makeMeasureSpec(primarySnapshotWidth, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(primarySnapshotHeight, View.MeasureSpec.EXACTLY)); + secondarySnapshot.measure( + View.MeasureSpec.makeMeasureSpec(secondarySnapshotWidth, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(secondarySnapshotHeight, + View.MeasureSpec.EXACTLY)); } @Override diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java index b34a81eaa0..b119e2c0a9 100644 --- a/src/com/android/launcher3/touch/PagedOrientationHandler.java +++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java @@ -162,7 +162,8 @@ public interface PagedOrientationHandler { SplitConfigurationOptions.StagedSplitBounds splitInfo, @SplitConfigurationOptions.StagePosition int desiredStagePosition); - void setGroupedTaskViewThumbnailBounds(View mSnapshot1, View mSnapshot2, View taskParent, + void measureGroupedTaskViewThumbnailBounds(View primarySnapshot, View secondarySnapshot, + int parentWidth, int parentHeight, SplitConfigurationOptions.StagedSplitBounds splitBoundsConfig, DeviceProfile dp); // Overview TaskMenuView methods diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java index f1fd439a06..99ad050b01 100644 --- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java +++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java @@ -35,7 +35,6 @@ import android.view.MotionEvent; import android.view.Surface; import android.view.VelocityTracker; import android.view.View; -import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.widget.LinearLayout; @@ -513,35 +512,46 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { } @Override - public void setGroupedTaskViewThumbnailBounds(View mSnapshotView, View mSnapshotView2, - View taskParent, SplitConfigurationOptions.StagedSplitBounds splitBoundsConfig, - DeviceProfile dp) { + public void measureGroupedTaskViewThumbnailBounds(View primarySnapshot, View secondarySnapshot, + int parentWidth, int parentHeight, + SplitConfigurationOptions.StagedSplitBounds splitBoundsConfig, DeviceProfile dp) { int spaceAboveSnapshot = dp.overviewTaskThumbnailTopMarginPx; - int totalThumbnailHeight = taskParent.getHeight() - spaceAboveSnapshot; - int totalThumbnailWidth = taskParent.getWidth(); - int dividerBar = (dp.isLandscape ? - splitBoundsConfig.visualDividerBounds.width() : - splitBoundsConfig.visualDividerBounds.height()); - ViewGroup.LayoutParams primaryLp = mSnapshotView.getLayoutParams(); - ViewGroup.LayoutParams secondaryLp = mSnapshotView2.getLayoutParams(); - + int totalThumbnailHeight = parentHeight - spaceAboveSnapshot; + int dividerBar = (splitBoundsConfig.appsStackedVertically ? + splitBoundsConfig.visualDividerBounds.height() : + splitBoundsConfig.visualDividerBounds.width()); + int primarySnapshotHeight; + int primarySnapshotWidth; + int secondarySnapshotHeight; + int secondarySnapshotWidth; + float taskPercent = splitBoundsConfig.appsStackedVertically ? + splitBoundsConfig.topTaskPercent : splitBoundsConfig.leftTaskPercent; if (dp.isLandscape) { - primaryLp.height = totalThumbnailHeight; - primaryLp.width = (int) (totalThumbnailWidth * splitBoundsConfig.leftTaskPercent); + primarySnapshotHeight = totalThumbnailHeight; + primarySnapshotWidth = (int) (parentWidth * taskPercent); - secondaryLp.height = totalThumbnailHeight; - secondaryLp.width = totalThumbnailWidth - primaryLp.width - dividerBar; - mSnapshotView2.setTranslationX(primaryLp.width + dividerBar); - mSnapshotView2.setTranslationY(spaceAboveSnapshot); + secondarySnapshotHeight = totalThumbnailHeight; + secondarySnapshotWidth = parentWidth - primarySnapshotWidth - dividerBar; + int translationX = primarySnapshotWidth + dividerBar; + secondarySnapshot.setTranslationX(translationX); + secondarySnapshot.setTranslationY(spaceAboveSnapshot); } else { - primaryLp.width = totalThumbnailWidth; - primaryLp.height = (int) (totalThumbnailHeight * splitBoundsConfig.topTaskPercent); + primarySnapshotWidth = parentWidth; + primarySnapshotHeight = (int) (totalThumbnailHeight * taskPercent); - secondaryLp.width = totalThumbnailWidth; - secondaryLp.height = totalThumbnailHeight - primaryLp.height - dividerBar; - mSnapshotView2.setTranslationY(primaryLp.height + spaceAboveSnapshot + dividerBar); - mSnapshotView2.setTranslationX(0); + secondarySnapshotWidth = parentWidth; + secondarySnapshotHeight = totalThumbnailHeight - primarySnapshotHeight - dividerBar; + int translationY = primarySnapshotHeight + spaceAboveSnapshot + dividerBar; + secondarySnapshot.setTranslationY(translationY); + secondarySnapshot.setTranslationX(0); } + primarySnapshot.measure( + View.MeasureSpec.makeMeasureSpec(primarySnapshotWidth, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(primarySnapshotHeight, View.MeasureSpec.EXACTLY)); + secondarySnapshot.measure( + View.MeasureSpec.makeMeasureSpec(secondarySnapshotWidth, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(secondarySnapshotHeight, + View.MeasureSpec.EXACTLY)); } @Override diff --git a/src/com/android/launcher3/util/SplitConfigurationOptions.java b/src/com/android/launcher3/util/SplitConfigurationOptions.java index 5093d85535..0b083e3af4 100644 --- a/src/com/android/launcher3/util/SplitConfigurationOptions.java +++ b/src/com/android/launcher3/util/SplitConfigurationOptions.java @@ -93,7 +93,13 @@ public final class SplitConfigurationOptions { // This class is orientation-agnostic, so we compute both for later use public final float topTaskPercent; public final float leftTaskPercent; - + /** + * If {@code true}, that means at the time of creation of this object, the + * split-screened apps were vertically stacked. This is useful in scenarios like + * rotation where the bounds won't change, but this variable can indicate what orientation + * the bounds were originally in + */ + public final boolean appsStackedVertically; public StagedSplitBounds(Rect leftTopBounds, Rect rightBottomBounds) { this.leftTopBounds = leftTopBounds; @@ -103,10 +109,12 @@ public final class SplitConfigurationOptions { // vertical apps, horizontal divider this.visualDividerBounds = new Rect(leftTopBounds.left, leftTopBounds.bottom, leftTopBounds.right, rightBottomBounds.top); + appsStackedVertically = true; } else { // horizontal apps, vertical divider this.visualDividerBounds = new Rect(leftTopBounds.right, leftTopBounds.top, rightBottomBounds.left, leftTopBounds.bottom); + appsStackedVertically = false; } leftTaskPercent = this.leftTopBounds.width() / (float) rightBottomBounds.right; diff --git a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java index f9a9997e99..65aaa24527 100644 --- a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java +++ b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java @@ -2,6 +2,7 @@ package com.android.launcher3.util.rule; import static androidx.test.InstrumentationRegistry.getInstrumentation; +import android.content.Context; import android.os.FileUtils; import android.os.ParcelFileDescriptor.AutoCloseInputStream; import android.util.Log; @@ -45,11 +46,30 @@ public class FailureWatcher extends TestWatcher { return new Statement() { @Override public void evaluate() throws Throwable { + boolean success = false; try { Log.d("b/196820244", "Before evaluate"); + mDevice.executeShellCommand("cmd statusbar tracing start"); FailureWatcher.super.apply(base, description).evaluate(); Log.d("b/196820244", "After evaluate"); + success = true; } finally { + // Save artifact for Launcher Winscope trace. + mDevice.executeShellCommand("cmd statusbar tracing stop"); + final Context nexusLauncherContext = + getInstrumentation().getTargetContext() + .createPackageContext("com.google.android.apps.nexuslauncher", + 0); + final File launcherTrace = + new File(nexusLauncherContext.getFilesDir(), "launcher_trace.pb"); + if (success) { + mDevice.executeShellCommand("rm " + launcherTrace); + } else { + mDevice.executeShellCommand("mv " + launcherTrace + " " + + diagFile(description, "LauncherWinscope", "pb")); + } + + // Detect touch events coming from physical screen. if (mLauncher.hadNontestEvents()) { throw new AssertionError( "Launcher received events not sent by the test. This may mean " diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index 98d081b70a..ea8a295b83 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -1559,10 +1559,12 @@ public final class LauncherInstrumentation { } float getWindowCornerRadius() { + // TODO(b/197326121): Check if the touch is overlapping with the corners by offsetting + final float tmpBuffer = 100f; final Resources resources = getResources(); if (!supportsRoundedCornersOnWindows(resources)) { Log.d(TAG, "No rounded corners"); - return 0f; + return tmpBuffer; } // Radius that should be used in case top or bottom aren't defined. @@ -1581,7 +1583,7 @@ public final class LauncherInstrumentation { // Always use the smallest radius to make sure the rounded corners will // completely cover the display. Log.d(TAG, "Rounded corners top: " + topRadius + " bottom: " + bottomRadius); - return Math.max(topRadius, bottomRadius); + return Math.max(topRadius, bottomRadius) + tmpBuffer; } private static boolean supportsRoundedCornersOnWindows(Resources resources) {