Merge "[Work] Fix work apps showing in personal tab" into sc-v2-dev
diff --git a/quickstep/res/layout/taskbar.xml b/quickstep/res/layout/taskbar.xml
index b4c168c..83ad9f3 100644
--- a/quickstep/res/layout/taskbar.xml
+++ b/quickstep/res/layout/taskbar.xml
@@ -52,6 +52,7 @@
android:orientation="horizontal"
android:paddingLeft="@dimen/taskbar_nav_buttons_spacing"
android:paddingRight="@dimen/taskbar_nav_buttons_spacing"
+ android:layout_marginEnd="@dimen/taskbar_contextual_button_margin"
android:gravity="center_vertical"
android:layout_gravity="end"/>
diff --git a/quickstep/res/layout/taskbar_contextual_button.xml b/quickstep/res/layout/taskbar_contextual_button.xml
new file mode 100644
index 0000000..cbbbfab
--- /dev/null
+++ b/quickstep/res/layout/taskbar_contextual_button.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<ImageView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="@dimen/taskbar_contextual_buttons_size"
+ android:layout_height="@dimen/taskbar_contextual_buttons_size"
+ android:layout_marginTop="@dimen/taskbar_contextual_button_margin"
+ android:paddingStart="@dimen/taskbar_nav_buttons_spacing"
+ android:background="@drawable/taskbar_icon_click_feedback_roundrect"
+ android:scaleType="center"/>
\ No newline at end of file
diff --git a/quickstep/res/layout/taskbar_nav_button.xml b/quickstep/res/layout/taskbar_nav_button.xml
index 985f928..4ffb8d8 100644
--- a/quickstep/res/layout/taskbar_nav_button.xml
+++ b/quickstep/res/layout/taskbar_nav_button.xml
@@ -1,4 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/taskbar_nav_buttons_size"
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index e7de0ac..c649082 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -163,6 +163,8 @@
<dimen name="taskbar_folder_margin">16dp</dimen>
<dimen name="taskbar_nav_buttons_spacing">16dp</dimen>
<dimen name="taskbar_nav_buttons_size">48dp</dimen>
+ <dimen name="taskbar_contextual_button_margin">16dp</dimen>
+ <dimen name="taskbar_contextual_buttons_size">35dp</dimen>
<dimen name="taskbar_stashed_size">24dp</dimen>
<dimen name="taskbar_stashed_handle_width">220dp</dimen>
<dimen name="taskbar_stashed_handle_height">6dp</dimen>
diff --git a/quickstep/robolectric_tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java b/quickstep/robolectric_tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
deleted file mode 100644
index fd93d98..0000000
--- a/quickstep/robolectric_tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep.util;
-
-import static android.view.Display.DEFAULT_DISPLAY;
-
-import static org.mockito.Mockito.mock;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.hardware.display.DisplayManager;
-import android.view.Surface;
-import android.view.SurfaceControl;
-
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.shadows.LShadowDisplay;
-import com.android.launcher3.util.DisplayController;
-import com.android.quickstep.LauncherActivityInterface;
-import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
-
-import org.hamcrest.Description;
-import org.hamcrest.TypeSafeMatcher;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.LooperMode;
-import org.robolectric.annotation.LooperMode.Mode;
-import org.robolectric.shadow.api.Shadow;
-import org.robolectric.shadows.ShadowDisplayManager;
-
-@RunWith(RobolectricTestRunner.class)
-@LooperMode(Mode.PAUSED)
-public class TaskViewSimulatorTest {
-
- @Test
- public void taskProperlyScaled_portrait_noRotation_sameInsets1() {
- new TaskMatrixVerifier()
- .withLauncherSize(1200, 2450)
- .withInsets(new Rect(0, 80, 0, 120))
- .verifyNoTransforms();
- }
-
- @Test
- public void taskProperlyScaled_portrait_noRotation_sameInsets2() {
- new TaskMatrixVerifier()
- .withLauncherSize(1200, 2450)
- .withInsets(new Rect(55, 80, 55, 120))
- .verifyNoTransforms();
- }
-
- @Test
- public void taskProperlyScaled_landscape_noRotation_sameInsets1() {
- new TaskMatrixVerifier()
- .withLauncherSize(2450, 1250)
- .withInsets(new Rect(0, 80, 0, 40))
- .verifyNoTransforms();
- }
-
- @Test
- public void taskProperlyScaled_landscape_noRotation_sameInsets2() {
- new TaskMatrixVerifier()
- .withLauncherSize(2450, 1250)
- .withInsets(new Rect(0, 80, 120, 0))
- .verifyNoTransforms();
- }
-
- @Test
- public void taskProperlyScaled_landscape_noRotation_sameInsets3() {
- new TaskMatrixVerifier()
- .withLauncherSize(2450, 1250)
- .withInsets(new Rect(55, 80, 55, 120))
- .verifyNoTransforms();
- }
-
- @Test
- public void taskProperlyScaled_landscape_rotated() {
- new TaskMatrixVerifier()
- .withLauncherSize(1200, 2450)
- .withInsets(new Rect(0, 80, 0, 120))
- .withAppBounds(
- new Rect(0, 0, 2450, 1200),
- new Rect(0, 80, 0, 120),
- Surface.ROTATION_90)
- .verifyNoTransforms();
- }
-
- private static class TaskMatrixVerifier extends TransformParams {
-
- private final Context mContext = RuntimeEnvironment.application;
-
- private Rect mAppBounds = new Rect();
- private Rect mLauncherInsets = new Rect();
-
- private Rect mAppInsets;
-
- private int mAppRotation = -1;
- private DeviceProfile mDeviceProfile;
-
- TaskMatrixVerifier withLauncherSize(int width, int height) {
- ShadowDisplayManager.changeDisplay(DEFAULT_DISPLAY,
- String.format("w%sdp-h%sdp-mdpi", width, height));
- if (mAppBounds.isEmpty()) {
- mAppBounds.set(0, 0, width, height);
- }
- return this;
- }
-
- TaskMatrixVerifier withInsets(Rect insets) {
- LShadowDisplay shadowDisplay = Shadow.extract(
- mContext.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY));
- shadowDisplay.setInsets(insets);
- mLauncherInsets.set(insets);
- return this;
- }
-
- TaskMatrixVerifier withAppBounds(Rect bounds, Rect insets, int appRotation) {
- mAppBounds.set(bounds);
- mAppInsets = insets;
- mAppRotation = appRotation;
- return this;
- }
-
- void verifyNoTransforms() {
- mDeviceProfile = InvariantDeviceProfile.INSTANCE.get(mContext)
- .getDeviceProfile(mContext);
- mDeviceProfile.updateInsets(mLauncherInsets);
-
- TaskViewSimulator tvs = new TaskViewSimulator(mContext,
- LauncherActivityInterface.INSTANCE);
- tvs.setDp(mDeviceProfile);
-
- int launcherRotation = DisplayController.INSTANCE.get(mContext).getInfo().rotation;
- if (mAppRotation < 0) {
- mAppRotation = launcherRotation;
- }
- tvs.getOrientationState().update(launcherRotation, mAppRotation);
- if (mAppInsets == null) {
- mAppInsets = new Rect(mLauncherInsets);
- }
- tvs.setPreviewBounds(mAppBounds, mAppInsets);
-
- tvs.fullScreenProgress.value = 1;
- tvs.recentsViewScale.value = tvs.getFullScreenScale();
- tvs.apply(this);
- }
-
- @Override
- public SurfaceParams[] createSurfaceParams(BuilderProxy proxy) {
- SurfaceParams.Builder builder = new SurfaceParams.Builder((SurfaceControl) null);
- proxy.onBuildTargetParams(builder, mock(RemoteAnimationTargetCompat.class), this);
- return new SurfaceParams[] {builder.build()};
- }
-
- @Override
- public void applySurfaceParams(SurfaceParams[] params) {
- // Verify that the task position remains the same
- RectF newAppBounds = new RectF(mAppBounds);
- params[0].matrix.mapRect(newAppBounds);
- Assert.assertThat(newAppBounds, new AlmostSame(mAppBounds));
-
- System.err.println("Bounds mapped: " + mAppBounds + " => " + newAppBounds);
- }
- }
-
- private static class AlmostSame extends TypeSafeMatcher<RectF> {
-
- // Allow 1px error margin to account for float to int conversions
- private final float mError = 1f;
- private final Rect mExpected;
-
- AlmostSame(Rect expected) {
- mExpected = expected;
- }
-
- @Override
- protected boolean matchesSafely(RectF item) {
- return Math.abs(item.left - mExpected.left) < mError
- && Math.abs(item.top - mExpected.top) < mError
- && Math.abs(item.right - mExpected.right) < mError
- && Math.abs(item.bottom - mExpected.bottom) < mError;
- }
-
- @Override
- public void describeTo(Description description) {
- description.appendValue(mExpected);
- }
- }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 046ee6f..79bea03 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -34,6 +34,7 @@
import android.animation.ObjectAnimator;
import android.annotation.DrawableRes;
import android.annotation.IdRes;
+import android.annotation.LayoutRes;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.Region.Op;
@@ -123,21 +124,16 @@
.getProperty(ALPHA_INDEX_IME),
flags -> (flags & FLAG_IME_VISIBLE) == 0, MultiValueAlpha.VALUE, 1, 0));
+ boolean isThreeButtonNav = mContext.isThreeButtonNav();
// IME switcher
View imeSwitcherButton = addButton(R.drawable.ic_ime_switcher, BUTTON_IME_SWITCH,
- mEndContextualContainer, mControllers.navButtonController, R.id.ime_switcher);
+ isThreeButtonNav ? mStartContextualContainer : mEndContextualContainer,
+ mControllers.navButtonController, R.id.ime_switcher);
mPropertyHolders.add(new StatePropertyHolder(imeSwitcherButton,
flags -> ((flags & MASK_IME_SWITCHER_VISIBLE) == MASK_IME_SWITCHER_VISIBLE)
&& ((flags & FLAG_ROTATION_BUTTON_VISIBLE) == 0)
&& ((flags & FLAG_A11Y_VISIBLE) == 0)));
- View imeDownButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK,
- mStartContextualContainer, mControllers.navButtonController, R.id.back);
- imeDownButton.setRotation(Utilities.isRtl(mContext.getResources()) ? 90 : -90);
- // Rotate when Ime visible
- mPropertyHolders.add(new StatePropertyHolder(imeDownButton,
- flags -> (flags & FLAG_IME_VISIBLE) != 0));
-
mPropertyHolders.add(new StatePropertyHolder(
mControllers.taskbarViewController.getTaskbarIconAlpha()
.getProperty(ALPHA_INDEX_KEYGUARD),
@@ -150,7 +146,7 @@
// Force nav buttons (specifically back button) to be visible during setup wizard.
boolean areButtonsForcedVisible = !SettingsCache.INSTANCE.get(mContext).getValue(
Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), 0);
- if (mContext.isThreeButtonNav() || areButtonsForcedVisible) {
+ if (isThreeButtonNav || areButtonsForcedVisible) {
initButtons(mNavButtonContainer, mEndContextualContainer,
mControllers.navButtonController);
@@ -163,11 +159,18 @@
// Rotation button
RotationButton rotationButton = new RotationButtonImpl(
- addButton(mEndContextualContainer, R.id.rotate_suggestion));
+ addButton(mEndContextualContainer, R.id.rotate_suggestion,
+ R.layout.taskbar_contextual_button));
rotationButton.hide();
mControllers.rotationButtonController.setRotationButton(rotationButton);
} else {
mControllers.rotationButtonController.setRotationButton(new RotationButton() {});
+ View imeDownButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK,
+ mStartContextualContainer, mControllers.navButtonController, R.id.back);
+ imeDownButton.setRotation(Utilities.isRtl(mContext.getResources()) ? 90 : -90);
+ // Rotate when Ime visible
+ mPropertyHolders.add(new StatePropertyHolder(imeDownButton,
+ flags -> (flags & FLAG_IME_VISIBLE) != 0));
}
applyState();
@@ -180,8 +183,11 @@
mBackButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK,
mNavButtonContainer, mControllers.navButtonController, R.id.back);
mPropertyHolders.add(new StatePropertyHolder(mBackButton,
- flags -> (flags & FLAG_IME_VISIBLE) == 0 &&
- (flags & FLAG_DISABLE_BACK) == 0));
+ flags -> (flags & FLAG_DISABLE_BACK) == 0));
+ boolean isRtl = Utilities.isRtl(mContext.getResources());
+ mPropertyHolders.add(new StatePropertyHolder(
+ mBackButton, flags -> (flags & FLAG_IME_VISIBLE) != 0, View.ROTATION,
+ isRtl ? 90 : -90, 0));
// Hide when keyguard is showing, show when bouncer is showing
mPropertyHolders.add(new StatePropertyHolder(mBackButton,
flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 ||
@@ -191,19 +197,18 @@
View homeButton = addButton(R.drawable.ic_sysbar_home, BUTTON_HOME, navContainer,
navButtonController, R.id.home);
mPropertyHolders.add(new StatePropertyHolder(homeButton,
- flags -> (flags & FLAG_IME_VISIBLE) == 0 &&
- (flags & FLAG_KEYGUARD_VISIBLE) == 0 &&
+ flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 &&
(flags & FLAG_DISABLE_HOME) == 0));
View recentsButton = addButton(R.drawable.ic_sysbar_recent, BUTTON_RECENTS,
navContainer, navButtonController, R.id.recent_apps);
mPropertyHolders.add(new StatePropertyHolder(recentsButton,
- flags -> (flags & FLAG_IME_VISIBLE) == 0 &&
- (flags & FLAG_KEYGUARD_VISIBLE) == 0 &&
+ flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 &&
(flags & FLAG_DISABLE_RECENTS) == 0));
// A11y button
mA11yButton = addButton(R.drawable.ic_sysbar_accessibility_button, BUTTON_A11Y,
- endContainer, navButtonController, R.id.accessibility_button);
+ endContainer, navButtonController, R.id.accessibility_button,
+ R.layout.taskbar_contextual_button);
mPropertyHolders.add(new StatePropertyHolder(mA11yButton,
flags -> (flags & FLAG_A11Y_VISIBLE) != 0
&& (flags & FLAG_ROTATION_BUTTON_VISIBLE) == 0));
@@ -306,15 +311,22 @@
private ImageView addButton(@DrawableRes int drawableId, @TaskbarButton int buttonType,
ViewGroup parent, TaskbarNavButtonController navButtonController, @IdRes int id) {
- ImageView buttonView = addButton(parent, id);
+ return addButton(drawableId, buttonType, parent, navButtonController, id,
+ R.layout.taskbar_nav_button);
+ }
+
+ private ImageView addButton(@DrawableRes int drawableId, @TaskbarButton int buttonType,
+ ViewGroup parent, TaskbarNavButtonController navButtonController, @IdRes int id,
+ @LayoutRes int layoutId) {
+ ImageView buttonView = addButton(parent, id, layoutId);
buttonView.setImageResource(drawableId);
buttonView.setOnClickListener(view -> navButtonController.onButtonClick(buttonType));
return buttonView;
}
- private ImageView addButton(ViewGroup parent, int id) {
+ private ImageView addButton(ViewGroup parent, @IdRes int id, @LayoutRes int layoutId) {
ImageView buttonView = (ImageView) mContext.getLayoutInflater()
- .inflate(R.layout.taskbar_nav_button, parent, false);
+ .inflate(layoutId, parent, false);
buttonView.setId(id);
parent.addView(buttonView);
mAllButtons.add(buttonView);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java b/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
index 8181a84..c9909cc 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
@@ -56,8 +56,14 @@
public static int getHotseatEndOffset(Context context) {
if (SysUINavigationMode.INSTANCE.get(context).getMode() == Mode.THREE_BUTTONS) {
Resources res = context.getResources();
+ /*
+ * 2 (left + right) x Padding +
+ * 3 nav buttons +
+ * Little space at the end for contextual buttons
+ */
return 2 * res.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_spacing)
- + 3 * res.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size);
+ + 3 * res.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size)
+ + res.getDimensionPixelSize(R.dimen.taskbar_contextual_button_margin);
} else {
return 0;
}
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index be0c980..830737d 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -96,6 +96,7 @@
import com.android.launcher3.util.WindowBounds;
import com.android.quickstep.BaseActivityInterface.AnimationFactory;
import com.android.quickstep.GestureState.GestureEndTarget;
+import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.AnimatorControllerWithResistance;
@@ -434,7 +435,7 @@
// RecentsView never updates the display rotation until swipe-up, force update
// RecentsOrientedState before passing to TaskViewSimulator.
mRecentsView.updateRecentsRotation();
- runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.mTaskViewSimulator
+ runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator()
.setOrientationState(mRecentsView.getPagedViewOrientedState()));
// If we've already ended the gesture and are going home, don't prepare recents UI,
@@ -753,6 +754,8 @@
public void onRecentsAnimationStart(RecentsAnimationController controller,
RecentsAnimationTargets targets) {
super.onRecentsAnimationStart(controller, targets);
+ ActiveGestureLog.INSTANCE.addLog("startRecentsAnimationCallback", targets.apps.length);
+ mRemoteTargetHandles = mTargetGluer.assignTargetsForSplitScreen(targets);
mRecentsAnimationController = controller;
mRecentsAnimationTargets = targets;
@@ -763,7 +766,7 @@
// orientation state is independent of which remote target handle we use since both
// should be pointing to the same one. Just choose index 0 for now since that works for
// both split and non-split
- RecentsOrientedState orientationState = mRemoteTargetHandles[0].mTaskViewSimulator
+ RecentsOrientedState orientationState = mRemoteTargetHandles[0].getTaskViewSimulator()
.getOrientationState();
DeviceProfile dp = orientationState.getLauncherDeviceProfile();
if (targets.minimizedHomeBounds != null && primaryTaskTarget != null) {
@@ -1350,7 +1353,7 @@
RemoteAnimationTargetCompat runningTaskTarget, float startProgress) {
// Directly animate the app to PiP (picture-in-picture) mode
final ActivityManager.RunningTaskInfo taskInfo = mGestureState.getRunningTask();
- final RecentsOrientedState orientationState = mRemoteTargetHandles[0].mTaskViewSimulator
+ final RecentsOrientedState orientationState = mRemoteTargetHandles[0].getTaskViewSimulator()
.getOrientationState();
final int windowRotation = calculateWindowRotation(runningTaskTarget, orientationState);
final int homeRotation = orientationState.getRecentsActivityRotation();
@@ -1386,7 +1389,7 @@
// is not ROTATION_0 (which implies the rotation is turned on in launcher settings).
if (homeRotation == ROTATION_0
&& (windowRotation == ROTATION_90 || windowRotation == ROTATION_270)) {
- builder.setFromRotation(mRemoteTargetHandles[0].mTaskViewSimulator, windowRotation,
+ builder.setFromRotation(mRemoteTargetHandles[0].getTaskViewSimulator(), windowRotation,
taskInfo.displayCutoutInsets);
}
final SwipePipToHomeAnimator swipePipToHomeAnimator = builder.build();
@@ -1756,7 +1759,7 @@
* depend on proper class initialization.
*/
protected void initAfterSubclassConstructor() {
- initTransitionEndpoints(mRemoteTargetHandles[0].mTaskViewSimulator
+ initTransitionEndpoints(mRemoteTargetHandles[0].getTaskViewSimulator()
.getOrientationState().getLauncherDeviceProfile());
}
@@ -1774,7 +1777,7 @@
protected void linkRecentsViewScroll() {
SurfaceTransactionApplier.create(mRecentsView, applier -> {
- runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.mTransformParams
+ runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTransformParams()
.setSyncTransactionApplier(applier));
runOnRecentsAnimationStart(() ->
mRecentsAnimationTargets.addReleaseCheck(applier));
@@ -1910,18 +1913,19 @@
boolean notSwipingPipToHome = mRecentsAnimationTargets != null && !mIsSwipingPipToHome;
boolean setRecentsScroll = mRecentsViewScrollLinked && mRecentsView != null;
for (RemoteTargetHandle remoteHandle : mRemoteTargetHandles) {
- AnimatorControllerWithResistance playbackController = remoteHandle.mPlaybackController;
+ AnimatorControllerWithResistance playbackController =
+ remoteHandle.getPlaybackController();
if (playbackController != null) {
playbackController.setProgress(Math.max(mCurrentShift.value,
getScaleProgressDueToScroll()), mDragLengthFactor);
}
if (notSwipingPipToHome) {
- TaskViewSimulator taskViewSimulator = remoteHandle.mTaskViewSimulator;
+ TaskViewSimulator taskViewSimulator = remoteHandle.getTaskViewSimulator();
if (setRecentsScroll) {
taskViewSimulator.setScroll(mRecentsView.getScrollOffset());
}
- taskViewSimulator.apply(remoteHandle.mTransformParams);
+ taskViewSimulator.apply(remoteHandle.getTransformParams());
}
}
ProtoTracer.INSTANCE.get(mContext).scheduleFrameUpdate();
diff --git a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
index 773817f..80ae65e 100644
--- a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
@@ -105,7 +105,7 @@
mRunningOverHome = ActivityManagerWrapper.isHomeTask(mGestureState.getRunningTask());
if (mRunningOverHome) {
runActionOnRemoteHandles(remoteTargetHandle ->
- remoteTargetHandle.mTransformParams.setHomeBuilderProxy(
+ remoteTargetHandle.getTransformParams().setHomeBuilderProxy(
FallbackSwipeHandler.this::updateHomeActivityTransformDuringSwipeUp));
}
}
@@ -115,7 +115,8 @@
super.initTransitionEndpoints(dp);
if (mRunningOverHome) {
// Full screen scale should be independent of remote target handle
- mMaxLauncherScale = 1 / mRemoteTargetHandles[0].mTaskViewSimulator.getFullScreenScale();
+ mMaxLauncherScale = 1 / mRemoteTargetHandles[0].getTaskViewSimulator()
+ .getFullScreenScale();
}
}
@@ -214,21 +215,21 @@
mHomeAlpha.value = Utilities.boundToRange(1 - mCurrentShift.value, 0, 1);
mVerticalShiftForScale.value = mCurrentShift.value;
runActionOnRemoteHandles(remoteTargetHandle ->
- remoteTargetHandle.mTransformParams.setHomeBuilderProxy(
+ remoteTargetHandle.getTransformParams().setHomeBuilderProxy(
FallbackHomeAnimationFactory.this
::updateHomeActivityTransformDuringHomeAnim));
} else {
mHomeAlpha = new AnimatedFloat(this::updateHomeAlpha);
mHomeAlpha.value = 0;
runActionOnRemoteHandles(remoteTargetHandle ->
- remoteTargetHandle.mTransformParams.setHomeBuilderProxy(
+ remoteTargetHandle.getTransformParams().setHomeBuilderProxy(
FallbackHomeAnimationFactory.this
::updateHomeActivityTransformDuringHomeAnim));
}
mRecentsAlpha.value = 1;
runActionOnRemoteHandles(remoteTargetHandle ->
- remoteTargetHandle.mTransformParams.setHomeBuilderProxy(
+ remoteTargetHandle.getTransformParams().setHomeBuilderProxy(
FallbackHomeAnimationFactory.this
::updateRecentsActivityTransformDuringHomeAnim));
}
diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
index ce3406c..dc22a61 100644
--- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
+++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
@@ -183,13 +183,13 @@
Rect crop = new Rect();
// We can assume there is only one remote target here because staged split never animates
// into the app icon, only into the homescreen
- mRemoteTargetHandles[0].mTaskViewSimulator.getCurrentCropRect().roundOut(crop);
+ mRemoteTargetHandles[0].getTaskViewSimulator().getCurrentCropRect().roundOut(crop);
Size windowSize = new Size(crop.width(), crop.height());
int fallbackBackgroundColor =
FloatingWidgetView.getDefaultBackgroundColor(mContext, runningTaskTarget);
FloatingWidgetView floatingWidgetView = FloatingWidgetView.getFloatingWidgetView(mActivity,
hostView, backgroundLocation, windowSize,
- mRemoteTargetHandles[0].mTaskViewSimulator.getCurrentCornerRadius(),
+ mRemoteTargetHandles[0].getTaskViewSimulator().getCurrentCornerRadius(),
isTargetTranslucent, fallbackBackgroundColor);
return new FloatingViewHomeAnimationFactory(floatingWidgetView) {
diff --git a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
new file mode 100644
index 0000000..8a4a632
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep;
+
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
+
+import android.content.Context;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.util.SplitConfigurationOptions;
+import com.android.quickstep.util.AnimatorControllerWithResistance;
+import com.android.quickstep.util.LauncherSplitScreenListener;
+import com.android.quickstep.util.TaskViewSimulator;
+import com.android.quickstep.util.TransformParams;
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+
+/**
+ * Glues together the necessary components to animate a remote target using a
+ * {@link TaskViewSimulator}
+ */
+public class RemoteTargetGluer {
+ private final RemoteTargetHandle[] mRemoteTargetHandles;
+ private SplitConfigurationOptions.StagedSplitBounds mStagedSplitBounds;
+
+ /**
+ * Use this constructor if remote targets are split-screen independent
+ */
+ public RemoteTargetGluer(Context context, BaseActivityInterface sizingStrategy,
+ RemoteAnimationTargets targets) {
+ mRemoteTargetHandles = createHandles(context, sizingStrategy, targets.apps.length);
+ }
+
+ /**
+ * Use this constructor if you want the number of handles created to match the number of active
+ * running tasks
+ */
+ public RemoteTargetGluer(Context context, BaseActivityInterface sizingStrategy) {
+ int[] splitIds = LauncherSplitScreenListener.INSTANCE.getNoCreate()
+ .getRunningSplitTaskIds();
+ mRemoteTargetHandles = createHandles(context, sizingStrategy, splitIds.length == 2 ? 2 : 1);
+ }
+
+ private RemoteTargetHandle[] createHandles(Context context,
+ BaseActivityInterface sizingStrategy, int numHandles) {
+ RemoteTargetHandle[] handles = new RemoteTargetHandle[numHandles];
+ for (int i = 0; i < numHandles; i++) {
+ TaskViewSimulator tvs = new TaskViewSimulator(context, sizingStrategy);
+ TransformParams transformParams = new TransformParams();
+ handles[i] = new RemoteTargetHandle(tvs, transformParams);
+ }
+ return handles;
+ }
+
+ /**
+ * Pairs together {@link TaskViewSimulator}s and {@link TransformParams} into a
+ * {@link RemoteTargetHandle}
+ * Assigns only the apps associated with {@param targets} into their own TaskViewSimulators.
+ * Length of targets.apps should match that of {@link #mRemoteTargetHandles}.
+ *
+ * If split screen may be active when this is called, you might want to use
+ * {@link #assignTargetsForSplitScreen(RemoteAnimationTargets)}
+ */
+ public RemoteTargetHandle[] assignTargets(RemoteAnimationTargets targets) {
+ for (int i = 0; i < mRemoteTargetHandles.length; i++) {
+ RemoteAnimationTargetCompat primaryTaskTarget = targets.apps[i];
+ mRemoteTargetHandles[i].mTransformParams.setTargetSet(
+ createRemoteAnimationTargetsForTarget(primaryTaskTarget, targets));
+ mRemoteTargetHandles[i].mTaskViewSimulator.setPreview(primaryTaskTarget, null);
+ }
+ return mRemoteTargetHandles;
+ }
+
+ /**
+ * Similar to {@link #assignTargets(RemoteAnimationTargets)}, except this matches the
+ * apps in targets.apps to that of the split screened tasks. If split screen is active, then
+ * {@link #mRemoteTargetHandles} index 0 will be the left/top task, index one right/bottom
+ */
+ public RemoteTargetHandle[] assignTargetsForSplitScreen(RemoteAnimationTargets targets) {
+ int[] splitIds = LauncherSplitScreenListener.INSTANCE.getNoCreate()
+ .getRunningSplitTaskIds();
+ RemoteAnimationTargetCompat primaryTaskTarget;
+ RemoteAnimationTargetCompat secondaryTaskTarget;
+ if (mRemoteTargetHandles.length == 1) {
+ // If we're not in split screen, the splitIds count doesn't really matter since we
+ // should always hit this case. Right now there's no use case for multiple app targets
+ // without being in split screen
+ primaryTaskTarget = targets.apps[0];
+ mRemoteTargetHandles[0].mTransformParams.setTargetSet(targets);
+ mRemoteTargetHandles[0].mTaskViewSimulator.setPreview(primaryTaskTarget, null);
+ } else {
+ // split screen
+ primaryTaskTarget = targets.findTask(splitIds[0]);
+ secondaryTaskTarget = targets.findTask(splitIds[1]);
+
+ RemoteAnimationTargetCompat dividerTarget = targets.getNonAppTargetOfType(
+ TYPE_DOCK_DIVIDER);
+ mStagedSplitBounds = new SplitConfigurationOptions.StagedSplitBounds(
+ primaryTaskTarget.screenSpaceBounds,
+ secondaryTaskTarget.screenSpaceBounds, dividerTarget.screenSpaceBounds);
+ mRemoteTargetHandles[0].mTransformParams.setTargetSet(
+ createRemoteAnimationTargetsForTarget(primaryTaskTarget, targets));
+ mRemoteTargetHandles[0].mTaskViewSimulator.setPreview(primaryTaskTarget,
+ mStagedSplitBounds);
+
+ mRemoteTargetHandles[1].mTransformParams.setTargetSet(
+ createRemoteAnimationTargetsForTarget(secondaryTaskTarget, targets));
+ mRemoteTargetHandles[1].mTaskViewSimulator.setPreview(secondaryTaskTarget,
+ mStagedSplitBounds);
+ }
+ return mRemoteTargetHandles;
+ }
+
+ private RemoteAnimationTargets createRemoteAnimationTargetsForTarget(
+ RemoteAnimationTargetCompat target,
+ RemoteAnimationTargets targets) {
+ return new RemoteAnimationTargets(new RemoteAnimationTargetCompat[]{target},
+ targets.wallpapers, targets.nonApps, targets.targetMode);
+ }
+
+ public RemoteTargetHandle[] getRemoteTargetHandles() {
+ return mRemoteTargetHandles;
+ }
+
+ public SplitConfigurationOptions.StagedSplitBounds getStagedSplitBounds() {
+ return mStagedSplitBounds;
+ }
+
+ /**
+ * Container to keep together all the associated objects whose properties need to be updated to
+ * animate a single remote app target
+ */
+ public static class RemoteTargetHandle {
+ private final TaskViewSimulator mTaskViewSimulator;
+ private final TransformParams mTransformParams;
+ @Nullable
+ private AnimatorControllerWithResistance mPlaybackController;
+
+ public RemoteTargetHandle(TaskViewSimulator taskViewSimulator,
+ TransformParams transformParams) {
+ mTransformParams = transformParams;
+ mTaskViewSimulator = taskViewSimulator;
+ }
+
+ public TaskViewSimulator getTaskViewSimulator() {
+ return mTaskViewSimulator;
+ }
+
+ public TransformParams getTransformParams() {
+ return mTransformParams;
+ }
+
+ @Nullable
+ public AnimatorControllerWithResistance getPlaybackController() {
+ return mPlaybackController;
+ }
+
+ public void setPlaybackController(
+ @Nullable AnimatorControllerWithResistance playbackController) {
+ mPlaybackController = playbackController;
+ }
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
index 78de300..51a491e 100644
--- a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
+++ b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
@@ -15,13 +15,10 @@
*/
package com.android.quickstep;
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
-
import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_SELECT;
import static com.android.launcher3.config.FeatureFlags.PROTOTYPE_APP_CLOSE;
-import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import android.animation.Animator;
import android.content.Context;
@@ -40,8 +37,7 @@
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.touch.PagedOrientationHandler;
-import com.android.launcher3.util.SplitConfigurationOptions;
-import com.android.quickstep.util.ActiveGestureLog;
+import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.AppCloseConfig;
import com.android.quickstep.util.LauncherSplitScreenListener;
@@ -60,6 +56,7 @@
RecentsAnimationCallbacks.RecentsAnimationListener{
protected static final Rect TEMP_RECT = new Rect();
+ protected final RemoteTargetGluer mTargetGluer;
protected DeviceProfile mDp;
@@ -67,8 +64,7 @@
protected final RecentsAnimationDeviceState mDeviceState;
protected final GestureState mGestureState;
- protected final RemoteTargetHandle[] mRemoteTargetHandles;
- protected SplitConfigurationOptions.StagedSplitBounds mStagedSplitBounds;
+ protected RemoteTargetHandle[] mRemoteTargetHandles;
// Shift in the range of [0, 1].
// 0 => preview snapShot is completely visible, and hotseat is completely translated down
@@ -98,39 +94,30 @@
primaryTVS.getOrientationState().update(
mDeviceState.getRotationTouchHelper().getCurrentActiveRotation(),
mDeviceState.getRotationTouchHelper().getDisplayRotation());
- mRemoteTargetHandles = new RemoteTargetHandle[mIsSwipeForStagedSplit ? 2 : 1];
- mRemoteTargetHandles[0] = new RemoteTargetHandle(primaryTVS, transformParams);
-
- if (mIsSwipeForStagedSplit) {
- TaskViewSimulator secondaryTVS = new TaskViewSimulator(context,
- gestureState.getActivityInterface());
- secondaryTVS.getOrientationState().update(
- mDeviceState.getRotationTouchHelper().getCurrentActiveRotation(),
- mDeviceState.getRotationTouchHelper().getDisplayRotation());
- mRemoteTargetHandles[1] = new RemoteTargetHandle(secondaryTVS, new TransformParams());
- }
+ mTargetGluer = new RemoteTargetGluer(mContext, mGestureState.getActivityInterface());
+ mRemoteTargetHandles = mTargetGluer.getRemoteTargetHandles();
}
protected void initTransitionEndpoints(DeviceProfile dp) {
mDp = dp;
mTransitionDragLength = mGestureState.getActivityInterface().getSwipeUpDestinationAndLength(
- dp, mContext, TEMP_RECT, mRemoteTargetHandles[0].mTaskViewSimulator
+ dp, mContext, TEMP_RECT, mRemoteTargetHandles[0].getTaskViewSimulator()
.getOrientationState().getOrientationHandler());
mDragLengthFactor = (float) dp.heightPx / mTransitionDragLength;
for (RemoteTargetHandle remoteHandle : mRemoteTargetHandles) {
PendingAnimation pendingAnimation = new PendingAnimation(mTransitionDragLength * 2);
- TaskViewSimulator taskViewSimulator = remoteHandle.mTaskViewSimulator;
+ TaskViewSimulator taskViewSimulator = remoteHandle.getTaskViewSimulator();
taskViewSimulator.setDp(dp);
taskViewSimulator.addAppToOverviewAnim(pendingAnimation, LINEAR);
AnimatorPlaybackController playbackController =
pendingAnimation.createPlaybackController();
- remoteHandle.mPlaybackController = AnimatorControllerWithResistance.createForRecents(
+ remoteHandle.setPlaybackController(AnimatorControllerWithResistance.createForRecents(
playbackController, mContext, taskViewSimulator.getOrientationState(),
mDp, taskViewSimulator.recentsViewScale, AnimatedFloat.VALUE,
taskViewSimulator.recentsViewSecondaryTranslation, AnimatedFloat.VALUE
- );
+ ));
}
}
@@ -157,7 +144,7 @@
protected PagedOrientationHandler getOrientationHandler() {
// OrientationHandler should be independent of remote target, can directly take one
- return mRemoteTargetHandles[0].mTaskViewSimulator
+ return mRemoteTargetHandles[0].getTaskViewSimulator()
.getOrientationState().getOrientationHandler();
}
@@ -246,8 +233,8 @@
for (int i = 0, mRemoteTargetHandlesLength = mRemoteTargetHandles.length;
i < mRemoteTargetHandlesLength; i++) {
RemoteTargetHandle remoteHandle = mRemoteTargetHandles[i];
- TaskViewSimulator tvs = remoteHandle.mTaskViewSimulator;
- tvs.apply(remoteHandle.mTransformParams.setProgress(startProgress));
+ TaskViewSimulator tvs = remoteHandle.getTaskViewSimulator();
+ tvs.apply(remoteHandle.getTransformParams().setProgress(startProgress));
startRects[i] = new RectF(tvs.getCurrentCropRect());
tvs.applyWindowToHomeRotation(outMatrix);
@@ -266,53 +253,10 @@
/** @return only the TaskViewSimulators from {@link #mRemoteTargetHandles} */
protected TaskViewSimulator[] getRemoteTaskViewSimulators() {
return Arrays.stream(mRemoteTargetHandles)
- .map(remoteTargetHandle -> remoteTargetHandle.mTaskViewSimulator)
+ .map(remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator())
.toArray(TaskViewSimulator[]::new);
}
- @Override
- public void onRecentsAnimationStart(RecentsAnimationController controller,
- RecentsAnimationTargets targets) {
- ActiveGestureLog.INSTANCE.addLog("startRecentsAnimationCallback", targets.apps.length);
- RemoteAnimationTargetCompat dividerTarget = targets.getNonAppTargetOfType(
- TYPE_DOCK_DIVIDER);
- RemoteAnimationTargetCompat primaryTaskTarget;
- RemoteAnimationTargetCompat secondaryTaskTarget;
-
- // TODO(b/197568823) Determine if we need to exclude assistant as one of the targets we
- // animate
- if (!mIsSwipeForStagedSplit) {
- primaryTaskTarget = targets.findTask(mGestureState.getRunningTaskId());
- mRemoteTargetHandles[0].mTransformParams.setTargetSet(targets);
-
- if (primaryTaskTarget != null) {
- mRemoteTargetHandles[0].mTaskViewSimulator.setPreview(primaryTaskTarget);
- }
- } else {
- int[] taskIds = LauncherSplitScreenListener.INSTANCE.getNoCreate()
- .getRunningSplitTaskIds();
- // We're in staged split
- primaryTaskTarget = targets.findTask(taskIds[0]);
- secondaryTaskTarget = targets.findTask(taskIds[1]);
- mStagedSplitBounds = new SplitConfigurationOptions.StagedSplitBounds(
- primaryTaskTarget.screenSpaceBounds,
- secondaryTaskTarget.screenSpaceBounds, dividerTarget.screenSpaceBounds);
- mRemoteTargetHandles[0].mTaskViewSimulator.setPreview(primaryTaskTarget,
- mStagedSplitBounds);
- mRemoteTargetHandles[1].mTaskViewSimulator.setPreview(secondaryTaskTarget,
- mStagedSplitBounds);
- mRemoteTargetHandles[0].mTransformParams.setTargetSet(
- createRemoteAnimationTargetsForTarget(primaryTaskTarget));
- mRemoteTargetHandles[1].mTransformParams.setTargetSet(
- createRemoteAnimationTargetsForTarget(secondaryTaskTarget));
- }
- }
-
- private RemoteAnimationTargets createRemoteAnimationTargetsForTarget(
- RemoteAnimationTargetCompat target) {
- return new RemoteAnimationTargets(new RemoteAnimationTargetCompat[]{target},
- null, null, MODE_CLOSING);
- }
/**
* Creates an animation that transforms the current app window into the home app.
* @param startProgress The progress of {@link #mCurrentShift} to start the window from.
@@ -329,8 +273,8 @@
i < mRemoteTargetHandlesLength; i++) {
RemoteTargetHandle remoteHandle = mRemoteTargetHandles[i];
out[i] = getWindowAnimationToHomeInternal(homeAnimationFactory,
- targetRect, remoteHandle.mTransformParams, remoteHandle.mTaskViewSimulator,
- startRects[i], homeToWindowPositionMap);
+ targetRect, remoteHandle.getTransformParams(),
+ remoteHandle.getTaskViewSimulator(), startRects[i], homeToWindowPositionMap);
}
return out;
}
@@ -445,21 +389,6 @@
}
}
- /**
- * Container to keep together all the associated objects whose properties need to be updated to
- * animate a single remote app target
- */
- public static class RemoteTargetHandle {
- public TaskViewSimulator mTaskViewSimulator;
- public TransformParams mTransformParams;
- public AnimatorControllerWithResistance mPlaybackController;
- public RemoteTargetHandle(TaskViewSimulator taskViewSimulator,
- TransformParams transformParams) {
- mTransformParams = transformParams;
- mTaskViewSimulator = taskViewSimulator;
- }
- }
-
public interface RunningWindowAnim {
void end();
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index d4c94db..23dc913 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -55,7 +55,6 @@
import android.window.TransitionInfo;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
@@ -67,6 +66,7 @@
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.util.DisplayController;
+import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
import com.android.quickstep.util.MultiValueUpdateListener;
import com.android.quickstep.util.SurfaceTransactionApplier;
import com.android.quickstep.util.TaskViewSimulator;
@@ -151,28 +151,7 @@
RemoteAnimationTargetCompat[] wallpaperTargets,
RemoteAnimationTargetCompat[] nonAppTargets, DepthController depthController,
PendingAnimation out) {
- boolean isRunningTask = v.isRunningTask();
- TransformParams params = null;
- TaskViewSimulator tsv = null;
- // TODO(b/195675206) handle two TSVs here
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isRunningTask) {
- params = v.getRecentsView().getRemoteTargetHandles()[0].mTransformParams;
- tsv = v.getRecentsView().getRemoteTargetHandles()[0].mTaskViewSimulator;
- }
- createRecentsWindowAnimator(v, skipViewChanges, appTargets, wallpaperTargets, nonAppTargets,
- depthController, out, params, tsv);
- }
-
- /**
- * Creates an animation that controls the window of the opening targets for the recents launch
- * animation.
- */
- public static void createRecentsWindowAnimator(TaskView v, boolean skipViewChanges,
- RemoteAnimationTargetCompat[] appTargets,
- RemoteAnimationTargetCompat[] wallpaperTargets,
- RemoteAnimationTargetCompat[] nonAppTargets, DepthController depthController,
- PendingAnimation out, @Nullable TransformParams params,
- @Nullable TaskViewSimulator tsv) {
+ RecentsView recentsView = v.getRecentsView();
boolean isQuickSwitch = v.isEndQuickswitchCuj();
v.setEndQuickswitchCuj(false);
@@ -183,16 +162,27 @@
inLiveTileMode ? MODE_CLOSING : MODE_OPENING);
final RemoteAnimationTargetCompat navBarTarget = targets.getNavBarRemoteAnimationTarget();
- if (params == null) {
- SurfaceTransactionApplier applier = new SurfaceTransactionApplier(v);
- targets.addReleaseCheck(applier);
+ SurfaceTransactionApplier applier = new SurfaceTransactionApplier(v);
+ targets.addReleaseCheck(applier);
- params = new TransformParams()
- .setSyncTransactionApplier(applier)
- .setTargetSet(targets);
+ RemoteTargetHandle[] remoteTargetHandles;
+ RemoteTargetHandle[] recentsViewHandles = recentsView.getRemoteTargetHandles();
+ if (v.isRunningTask()) {
+ // Re-use existing handles
+ remoteTargetHandles = recentsViewHandles;
+ } else {
+ RemoteTargetGluer gluer = new RemoteTargetGluer(v.getContext(),
+ recentsView.getSizeStrategy(), targets);
+ if (recentsViewHandles != null && recentsViewHandles.length > 1) {
+ remoteTargetHandles = gluer.assignTargetsForSplitScreen(targets);
+ } else {
+ remoteTargetHandles = gluer.assignTargets(targets);
+ }
+ }
+ for (RemoteTargetHandle remoteTargetGluer : remoteTargetHandles) {
+ remoteTargetGluer.getTransformParams().setSyncTransactionApplier(applier);
}
- final RecentsView recentsView = v.getRecentsView();
int taskIndex = recentsView.indexOfChild(v);
Context context = v.getContext();
DeviceProfile dp = BaseActivity.fromContext(context).getDeviceProfile();
@@ -202,45 +192,51 @@
float gridTranslationSecondary = recentsView.getGridTranslationSecondary(taskIndex);
int startScroll = recentsView.getScrollOffset(taskIndex);
- TaskViewSimulator topMostSimulator = null;
+ RemoteTargetHandle[] topMostSimulators = null;
- if (tsv == null && targets.apps.length > 0) {
- tsv = new TaskViewSimulator(context, recentsView.getSizeStrategy());
- tsv.setDp(dp);
+ if (!v.isRunningTask()) {
+ // TVSs already initialized from the running task, no need to re-init
+ for (RemoteTargetHandle targetHandle : remoteTargetHandles) {
+ TaskViewSimulator tvsLocal = targetHandle.getTaskViewSimulator();
+ tvsLocal.setDp(dp);
- // RecentsView never updates the display rotation until swipe-up so the value may
- // be stale. Use the display value instead.
- int displayRotation = DisplayController.INSTANCE.get(context).getInfo().rotation;
- tsv.getOrientationState().update(displayRotation, displayRotation);
+ // RecentsView never updates the display rotation until swipe-up so the value may
+ // be stale. Use the display value instead.
+ int displayRotation = DisplayController.INSTANCE.get(context).getInfo().rotation;
+ tvsLocal.getOrientationState().update(displayRotation, displayRotation);
- tsv.setPreview(targets.apps[targets.apps.length - 1]);
- tsv.fullScreenProgress.value = 0;
- tsv.recentsViewScale.value = 1;
- if (showAsGrid) {
- tsv.taskSecondaryTranslation.value = gridTranslationSecondary;
+ tvsLocal.fullScreenProgress.value = 0;
+ tvsLocal.recentsViewScale.value = 1;
+ if (showAsGrid) {
+ tvsLocal.taskSecondaryTranslation.value = gridTranslationSecondary;
+ }
+ tvsLocal.setScroll(startScroll);
+
+ // Fade in the task during the initial 20% of the animation
+ out.addFloat(targetHandle.getTransformParams(), TransformParams.TARGET_ALPHA, 0, 1,
+ clampToProgress(LINEAR, 0, 0.2f));
}
- tsv.setScroll(startScroll);
-
- // Fade in the task during the initial 20% of the animation
- out.addFloat(params, TransformParams.TARGET_ALPHA, 0, 1,
- clampToProgress(LINEAR, 0, 0.2f));
}
- if (tsv != null) {
- out.setFloat(tsv.fullScreenProgress,
+ for (RemoteTargetHandle targetHandle : remoteTargetHandles) {
+ TaskViewSimulator tvsLocal = targetHandle.getTaskViewSimulator();
+ out.setFloat(tvsLocal.fullScreenProgress,
AnimatedFloat.VALUE, 1, TOUCH_RESPONSE_INTERPOLATOR);
- out.setFloat(tsv.recentsViewScale,
- AnimatedFloat.VALUE, tsv.getFullScreenScale(), TOUCH_RESPONSE_INTERPOLATOR);
+ out.setFloat(tvsLocal.recentsViewScale,
+ AnimatedFloat.VALUE, tvsLocal.getFullScreenScale(),
+ TOUCH_RESPONSE_INTERPOLATOR);
if (showAsGrid) {
- out.setFloat(tsv.taskSecondaryTranslation, AnimatedFloat.VALUE, 0,
+ out.setFloat(tvsLocal.taskSecondaryTranslation, AnimatedFloat.VALUE, 0,
TOUCH_RESPONSE_INTERPOLATOR_ACCEL_DEACCEL);
}
- out.setFloat(tsv.recentsViewScroll, AnimatedFloat.VALUE, 0,
+ out.setFloat(tvsLocal.recentsViewScroll, AnimatedFloat.VALUE, 0,
TOUCH_RESPONSE_INTERPOLATOR);
- TaskViewSimulator finalTsv = tsv;
- TransformParams finalParams = params;
- out.addOnFrameCallback(() -> finalTsv.apply(finalParams));
+ out.addOnFrameCallback(() -> {
+ for (RemoteTargetHandle handle : remoteTargetHandles) {
+ handle.getTaskViewSimulator().apply(handle.getTransformParams());
+ }
+ });
if (navBarTarget != null) {
final Rect cropRect = new Rect();
out.addOnFrameListener(new MultiValueUpdateListener() {
@@ -253,15 +249,20 @@
public void onUpdate(float percent, boolean initOnly) {
final SurfaceParams.Builder navBuilder =
new SurfaceParams.Builder(navBarTarget.leash);
- if (mNavFadeIn.value > mNavFadeIn.getStartValue()) {
- finalTsv.getCurrentCropRect().round(cropRect);
- navBuilder.withMatrix(finalTsv.getCurrentMatrix())
- .withWindowCrop(cropRect)
- .withAlpha(mNavFadeIn.value);
- } else {
- navBuilder.withAlpha(mNavFadeOut.value);
+
+ // TODO Do we need to operate over multiple TVSs for the navbar leash?
+ for (RemoteTargetHandle handle : remoteTargetHandles) {
+ if (mNavFadeIn.value > mNavFadeIn.getStartValue()) {
+ TaskViewSimulator taskViewSimulator = handle.getTaskViewSimulator();
+ taskViewSimulator.getCurrentCropRect().round(cropRect);
+ navBuilder.withMatrix(taskViewSimulator.getCurrentMatrix())
+ .withWindowCrop(cropRect)
+ .withAlpha(mNavFadeIn.value);
+ } else {
+ navBuilder.withAlpha(mNavFadeOut.value);
+ }
+ handle.getTransformParams().applySurfaceParams(navBuilder.build());
}
- finalParams.applySurfaceParams(navBuilder.build());
}
});
} else if (inLiveTileMode) {
@@ -273,14 +274,16 @@
controller.animateNavigationBarToApp(RECENTS_LAUNCH_DURATION);
}
}
- topMostSimulator = tsv;
+ topMostSimulators = remoteTargetHandles;
}
- if (!skipViewChanges && parallaxCenterAndAdjacentTask && topMostSimulator != null) {
+ if (!skipViewChanges && parallaxCenterAndAdjacentTask && topMostSimulators.length > 0) {
out.addFloat(v, VIEW_ALPHA, 1, 0, clampToProgress(LINEAR, 0.2f, 0.4f));
- TaskViewSimulator simulatorToCopy = topMostSimulator;
- simulatorToCopy.apply(params);
+ RemoteTargetHandle[] simulatorCopies = topMostSimulators;
+ for (RemoteTargetHandle handle : simulatorCopies) {
+ handle.getTaskViewSimulator().apply(handle.getTransformParams());
+ }
// Mt represents the overall transformation on the thumbnailView relative to the
// Launcher's rootView
@@ -294,36 +297,49 @@
// During animation we apply transformation on the thumbnailView (and not the rootView)
// to follow the TaskViewSimulator. So the final matrix applied on the thumbnailView is:
// Mt K(0)` K(t) Mt`
- TaskThumbnailView ttv = v.getThumbnail();
- RectF tvBounds = new RectF(0, 0, ttv.getWidth(), ttv.getHeight());
- float[] tvBoundsMapped = new float[]{0, 0, ttv.getWidth(), ttv.getHeight()};
- getDescendantCoordRelativeToAncestor(ttv, ttv.getRootView(), tvBoundsMapped, false);
- RectF tvBoundsInRoot = new RectF(
- tvBoundsMapped[0], tvBoundsMapped[1],
- tvBoundsMapped[2], tvBoundsMapped[3]);
+ TaskThumbnailView[] thumbnails = v.getThumbnails();
+ Matrix[] mt = new Matrix[simulatorCopies.length];
+ Matrix[] mti = new Matrix[simulatorCopies.length];
+ for (int i = 0; i < thumbnails.length; i++) {
+ TaskThumbnailView ttv = thumbnails[i];
+ RectF localBounds = new RectF(0, 0, ttv.getWidth(), ttv.getHeight());
+ float[] tvBoundsMapped = new float[]{0, 0, ttv.getWidth(), ttv.getHeight()};
+ getDescendantCoordRelativeToAncestor(ttv, ttv.getRootView(), tvBoundsMapped, false);
+ RectF localBoundsInRoot = new RectF(
+ tvBoundsMapped[0], tvBoundsMapped[1],
+ tvBoundsMapped[2], tvBoundsMapped[3]);
+ Matrix localMt = new Matrix();
+ localMt.setRectToRect(localBounds, localBoundsInRoot, ScaleToFit.FILL);
+ mt[i] = localMt;
- Matrix mt = new Matrix();
- mt.setRectToRect(tvBounds, tvBoundsInRoot, ScaleToFit.FILL);
+ Matrix localMti = new Matrix();
+ localMti.invert(localMt);
+ mti[i] = localMti;
+ }
- Matrix mti = new Matrix();
- mt.invert(mti);
-
- Matrix k0i = new Matrix();
- simulatorToCopy.getCurrentMatrix().invert(k0i);
-
+ Matrix[] k0i = new Matrix[simulatorCopies.length];
+ for (int i = 0; i < simulatorCopies.length; i++) {
+ k0i[i] = new Matrix();
+ simulatorCopies[i].getTaskViewSimulator().getCurrentMatrix().invert(k0i[i]);
+ }
Matrix animationMatrix = new Matrix();
out.addOnFrameCallback(() -> {
- animationMatrix.set(mt);
- animationMatrix.postConcat(k0i);
- animationMatrix.postConcat(simulatorToCopy.getCurrentMatrix());
- animationMatrix.postConcat(mti);
- ttv.setAnimationMatrix(animationMatrix);
+ for (int i = 0; i < simulatorCopies.length; i++) {
+ animationMatrix.set(mt[i]);
+ animationMatrix.postConcat(k0i[i]);
+ animationMatrix.postConcat(simulatorCopies[i]
+ .getTaskViewSimulator().getCurrentMatrix());
+ animationMatrix.postConcat(mti[i]);
+ thumbnails[i].setAnimationMatrix(animationMatrix);
+ }
});
out.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- ttv.setAnimationMatrix(null);
+ for (TaskThumbnailView ttv : thumbnails) {
+ ttv.setAnimationMatrix(null);
+ }
}
});
}
diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
index c2c8f61..1f75936 100644
--- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
@@ -46,7 +46,6 @@
import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
-import com.android.launcher3.statemanager.StatefulActivity;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.GestureState;
import com.android.quickstep.OverviewComponentObserver;
@@ -260,16 +259,16 @@
void initDp(DeviceProfile dp) {
initTransitionEndpoints(dp);
- mRemoteTargetHandles[0].mTaskViewSimulator.setPreviewBounds(
+ mRemoteTargetHandles[0].getTaskViewSimulator().setPreviewBounds(
new Rect(0, 0, dp.widthPx, dp.heightPx), dp.getInsets());
}
@Override
public void updateFinalShift() {
- mRemoteTargetHandles[0].mPlaybackController
+ mRemoteTargetHandles[0].getPlaybackController()
.setProgress(mCurrentShift.value, mDragLengthFactor);
- mRemoteTargetHandles[0].mTaskViewSimulator.apply(
- mRemoteTargetHandles[0].mTransformParams);
+ mRemoteTargetHandles[0].getTaskViewSimulator().apply(
+ mRemoteTargetHandles[0].getTransformParams());
}
AnimatedFloat getCurrentShift() {
diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
index 841e578..a4db596 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
+++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
@@ -600,17 +600,7 @@
width = Math.min(currentSize.x, currentSize.y);
height = Math.max(currentSize.x, currentSize.y);
}
-
- DeviceProfile bestMatch = idp.supportedProfiles.get(0);
- float minDiff = Float.MAX_VALUE;
- for (DeviceProfile profile : idp.supportedProfiles) {
- float diff = Math.abs(profile.widthPx - width) + Math.abs(profile.heightPx - height);
- if (diff < minDiff) {
- minDiff = diff;
- bestMatch = profile;
- }
- }
- return bestMatch;
+ return idp.getBestMatch(width, height);
}
private static String nameAndAddress(Object obj) {
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
index d3077ad..8562719 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
@@ -113,6 +113,11 @@
}
@Override
+ public TaskThumbnailView[] getThumbnails() {
+ return new TaskThumbnailView[]{mSnapshotView, mSnapshotView2};
+ }
+
+ @Override
public void onRecycle() {
super.onRecycle();
mSnapshotView2.setThumbnail(mSecondaryTask, null);
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index b690982..24d6044 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -19,7 +19,6 @@
import static android.view.Surface.ROTATION_0;
import static android.view.View.MeasureSpec.EXACTLY;
import static android.view.View.MeasureSpec.makeMeasureSpec;
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU;
import static com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType;
@@ -53,7 +52,6 @@
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS;
-import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -146,7 +144,8 @@
import com.android.quickstep.RecentsModel;
import com.android.quickstep.RecentsModel.TaskVisualsChangeListener;
import com.android.quickstep.RemoteAnimationTargets;
-import com.android.quickstep.SwipeUpAnimationLogic.RemoteTargetHandle;
+import com.android.quickstep.RemoteTargetGluer;
+import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskOverlayFactory;
import com.android.quickstep.TaskThumbnailCache;
@@ -325,7 +324,7 @@
view.runActionOnRemoteHandles(new Consumer<RemoteTargetHandle>() {
@Override
public void accept(RemoteTargetHandle remoteTargetHandle) {
- remoteTargetHandle.mTaskViewSimulator.recentsViewScale.value =
+ remoteTargetHandle.getTaskViewSimulator().recentsViewScale.value =
scale;
}
});
@@ -828,7 +827,7 @@
mActivity.addMultiWindowModeChangedListener(mMultiWindowModeChangedListener);
TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener);
mSyncTransactionApplier = new SurfaceTransactionApplier(this);
- runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.mTransformParams
+ runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTransformParams()
.setSyncTransactionApplier(mSyncTransactionApplier));
RecentsModel.INSTANCE.get(getContext()).addThumbnailChangeListener(this);
mIPipAnimationListener.setActivityAndRecentsView(mActivity, this);
@@ -847,7 +846,7 @@
mActivity.removeMultiWindowModeChangedListener(mMultiWindowModeChangedListener);
TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
mSyncTransactionApplier = null;
- runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.mTransformParams
+ runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTransformParams()
.setSyncTransactionApplier(null));
executeSideTaskLaunchCallback();
RecentsModel.INSTANCE.get(getContext()).removeThumbnailChangeListener(this);
@@ -937,7 +936,7 @@
public void launchSideTaskInLiveTileModeForRestartedApp(int taskId) {
int runningTaskViewId = getTaskViewIdFromTaskId(taskId);
if (mRunningTaskViewId != -1 && mRunningTaskViewId == runningTaskViewId) {
- TransformParams params = mRemoteTargetHandles[0].mTransformParams;
+ TransformParams params = mRemoteTargetHandles[0].getTransformParams();
RemoteAnimationTargets targets = params.getTargetSet();
if (targets != null && targets.findTask(taskId) != null) {
launchSideTaskInLiveTileMode(taskId, targets.apps, targets.wallpapers,
@@ -1481,10 +1480,11 @@
// to reset the params after it settles in Overview from swipe up so that we don't
// render with obsolete param values.
runActionOnRemoteHandles(remoteTargetHandle -> {
- remoteTargetHandle.mTaskViewSimulator.taskPrimaryTranslation.value = 0;
- remoteTargetHandle.mTaskViewSimulator.taskSecondaryTranslation.value = 0;
- remoteTargetHandle.mTaskViewSimulator.fullScreenProgress.value = 0;
- remoteTargetHandle.mTaskViewSimulator.recentsViewScale.value = 1;
+ TaskViewSimulator simulator = remoteTargetHandle.getTaskViewSimulator();
+ simulator.taskPrimaryTranslation.value = 0;
+ simulator.taskSecondaryTranslation.value = 0;
+ simulator.fullScreenProgress.value = 0;
+ simulator.recentsViewScale.value = 1;
});
// Similar to setRunningTaskHidden below, reapply the state before runningTaskView is
@@ -1540,7 +1540,7 @@
// Propagate DeviceProfile change event.
runActionOnRemoteHandles(
- remoteTargetHandle -> remoteTargetHandle.mTaskViewSimulator.setDp(dp));
+ remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator().setDp(dp));
mActionsView.setDp(dp);
mOrientationState.setDeviceProfile(dp);
@@ -1877,7 +1877,7 @@
}
}
setEnableDrawingLiveTile(false);
- runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.mTransformParams
+ runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTransformParams()
.setTargetSet(null));
// These are relatively expensive and don't need to be done this frame (RecentsView isn't
@@ -2590,7 +2590,7 @@
// alpha is set to 0 so that it can be recycled in the view pool properly
if (ENABLE_QUICKSTEP_LIVE_TILE.get() && taskView.isRunningTask()) {
runActionOnRemoteHandles(remoteTargetHandle -> {
- TransformParams params = remoteTargetHandle.mTransformParams;
+ TransformParams params = remoteTargetHandle.getTransformParams();
anim.setFloat(params, TransformParams.TARGET_ALPHA, 0,
clampToProgress(ACCEL, 0, 0.5f));
});
@@ -2613,7 +2613,7 @@
&& taskView.isRunningTask()) {
anim.addOnFrameCallback(() -> {
runActionOnRemoteHandles(
- remoteTargetHandle -> remoteTargetHandle.mTaskViewSimulator
+ remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator()
.taskSecondaryTranslation.value = mOrientationHandler
.getSecondaryValue(taskView.getTranslationX(),
taskView.getTranslationY()
@@ -2782,7 +2782,7 @@
anim.addOnFrameCallback(() -> {
runActionOnRemoteHandles(
remoteTargetHandle ->
- remoteTargetHandle.mTaskViewSimulator
+ remoteTargetHandle.getTaskViewSimulator()
.taskPrimaryTranslation.value =
TaskView.GRID_END_TRANSLATION_X.get(taskView));
redrawLiveTile();
@@ -2855,7 +2855,7 @@
anim.addOnFrameCallback(() -> {
runActionOnRemoteHandles(
remoteTargetHandle ->
- remoteTargetHandle.mTaskViewSimulator
+ remoteTargetHandle.getTaskViewSimulator()
.taskPrimaryTranslation.value =
mOrientationHandler.getPrimaryValue(
child.getTranslationX(),
@@ -3533,7 +3533,7 @@
mLastComputedTaskEndPushOutDistance = null;
updatePageOffsets();
runActionOnRemoteHandles(
- remoteTargetHandle -> remoteTargetHandle.mTaskViewSimulator
+ remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator()
.setScroll(getScrollOffset()));
setImportantForAccessibility(isModal() ? IMPORTANT_FOR_ACCESSIBILITY_NO
: IMPORTANT_FOR_ACCESSIBILITY_AUTO);
@@ -3599,7 +3599,7 @@
if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile
&& i == getRunningTaskIndex()) {
runActionOnRemoteHandles(
- remoteTargetHandle -> remoteTargetHandle.mTaskViewSimulator
+ remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator()
.taskPrimaryTranslation.value = totalTranslation);
redrawLiveTile();
}
@@ -3707,7 +3707,7 @@
task.getTaskResistanceTranslationProperty().set(task, translation / getScaleY());
}
runActionOnRemoteHandles(
- remoteTargetHandle -> remoteTargetHandle.mTaskViewSimulator
+ remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator()
.recentsViewSecondaryTranslation.value = translation);
}
@@ -4023,7 +4023,7 @@
&& runningTaskIndex != taskIndex) {
for (RemoteTargetHandle remoteHandle : recentsView.getRemoteTargetHandles()) {
anim.play(ObjectAnimator.ofFloat(
- remoteHandle.mTaskViewSimulator.taskPrimaryTranslation,
+ remoteHandle.getTaskViewSimulator().taskPrimaryTranslation,
AnimatedFloat.VALUE,
primaryTranslation));
}
@@ -4107,7 +4107,7 @@
mPendingAnimation.add(anim);
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
runActionOnRemoteHandles(
- remoteTargetHandle -> remoteTargetHandle.mTaskViewSimulator
+ remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator()
.addOverviewToAppAnim(mPendingAnimation, interpolator));
mPendingAnimation.addOnFrameCallback(this::redrawLiveTile);
}
@@ -4201,9 +4201,9 @@
public void redrawLiveTile() {
runActionOnRemoteHandles(remoteTargetHandle -> {
- TransformParams params = remoteTargetHandle.mTransformParams;
+ TransformParams params = remoteTargetHandle.getTransformParams();
if (params.getTargetSet() != null) {
- remoteTargetHandle.mTaskViewSimulator.apply(params);
+ remoteTargetHandle.getTaskViewSimulator().apply(params);
}
});
}
@@ -4224,44 +4224,14 @@
recentsAnimationTargets.addReleaseCheck(mSyncTransactionApplier);
}
- RemoteAnimationTargetCompat dividerTarget =
- recentsAnimationTargets.getNonAppTargetOfType(TYPE_DOCK_DIVIDER);
- // TODO Consolidate this shared code with SwipeUpAnimationLogic (or maybe just reuse
- // what that class has and pass it into here)
- mRemoteTargetHandles = new RemoteTargetHandle[dividerTarget == null ? 1 : 2];
- TaskViewSimulator primaryTvs = createTaskViewSimulator();
- mRemoteTargetHandles[0] = new RemoteTargetHandle(primaryTvs, new TransformParams());
- if (dividerTarget == null) {
- mRemoteTargetHandles[0].mTaskViewSimulator
- .setPreview(recentsAnimationTargets.apps[0], null);
- mRemoteTargetHandles[0].mTransformParams.setTargetSet(recentsAnimationTargets);
- } else {
- TaskViewSimulator secondaryTvs = createTaskViewSimulator();
- secondaryTvs.setOrientationState(mOrientationState);
- secondaryTvs.recentsViewScale.value = 1;
-
- mRemoteTargetHandles[1] = new RemoteTargetHandle(secondaryTvs, new TransformParams());
- RemoteAnimationTargetCompat primaryTaskTarget = recentsAnimationTargets.apps[0];
- RemoteAnimationTargetCompat secondaryTaskTarget = recentsAnimationTargets.apps[1];
- mSplitBoundsConfig = new SplitConfigurationOptions.StagedSplitBounds(
- primaryTaskTarget.screenSpaceBounds,
- secondaryTaskTarget.screenSpaceBounds, dividerTarget.screenSpaceBounds);
- mRemoteTargetHandles[0].mTaskViewSimulator.setPreview(primaryTaskTarget,
- mSplitBoundsConfig);
- mRemoteTargetHandles[1].mTaskViewSimulator.setPreview(secondaryTaskTarget,
- mSplitBoundsConfig);
- RemoteAnimationTargets rats = new RemoteAnimationTargets(
- new RemoteAnimationTargetCompat[]{primaryTaskTarget},
- recentsAnimationTargets.wallpapers, recentsAnimationTargets.nonApps,
- MODE_CLOSING
- );
- RemoteAnimationTargets splitRats = new RemoteAnimationTargets(
- new RemoteAnimationTargetCompat[]{secondaryTaskTarget},
- recentsAnimationTargets.wallpapers, recentsAnimationTargets.nonApps,
- MODE_CLOSING
- );
- mRemoteTargetHandles[0].mTransformParams.setTargetSet(rats);
- mRemoteTargetHandles[1].mTransformParams.setTargetSet(splitRats);
+ RemoteTargetGluer gluer = new RemoteTargetGluer(getContext(), getSizeStrategy());
+ mRemoteTargetHandles = gluer.assignTargetsForSplitScreen(recentsAnimationTargets);
+ mSplitBoundsConfig = gluer.getStagedSplitBounds();
+ for (RemoteTargetHandle remoteTargetHandle : mRemoteTargetHandles) {
+ TaskViewSimulator tvs = remoteTargetHandle.getTaskViewSimulator();
+ tvs.setOrientationState(mOrientationState);
+ tvs.setDp(mActivity.getDeviceProfile());
+ tvs.recentsViewScale.value = 1;
}
}
@@ -4276,14 +4246,6 @@
}
}
- private TaskViewSimulator createTaskViewSimulator() {
- TaskViewSimulator tvs = new TaskViewSimulator(getContext(), getSizeStrategy());
- tvs.setOrientationState(mOrientationState);
- tvs.setDp(mActivity.getDeviceProfile());
- tvs.recentsViewScale.value = 1;
- return tvs;
- }
-
public void finishRecentsAnimation(boolean toRecents, Runnable onFinishComplete) {
finishRecentsAnimation(toRecents, true /* shouldPip */, onFinishComplete);
}
@@ -4778,7 +4740,7 @@
private void dispatchScrollChanged() {
runActionOnRemoteHandles(remoteTargetHandle ->
- remoteTargetHandle.mTaskViewSimulator.setScroll(getScrollOffset()));
+ remoteTargetHandle.getTaskViewSimulator().setScroll(getScrollOffset()));
for (int i = mScrollListeners.size() - 1; i >= 0; i--) {
mScrollListeners.get(i).onScrollChanged();
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 0e6c0fd..08b614a 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -91,7 +91,7 @@
import com.android.launcher3.util.ViewPool.Reusable;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.RemoteAnimationTargets;
-import com.android.quickstep.SwipeUpAnimationLogic.RemoteTargetHandle;
+import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskIconCache;
import com.android.quickstep.TaskOverlayFactory;
@@ -592,6 +592,11 @@
return mSnapshotView;
}
+ /** TODO(b/197033698) Remove all usages of above method and migrate to this one */
+ public TaskThumbnailView[] getThumbnails() {
+ return new TaskThumbnailView[]{mSnapshotView};
+ }
+
public IconView getIconView() {
return mIconView;
}
@@ -618,13 +623,12 @@
mIsClickableAsLiveTile = false;
RecentsView recentsView = getRecentsView();
RemoteAnimationTargets targets;
- RemoteTargetHandle[] remoteTargetHandles =
- recentsView.mRemoteTargetHandles;
+ RemoteTargetHandle[] remoteTargetHandles = recentsView.mRemoteTargetHandles;
if (remoteTargetHandles.length == 1) {
- targets = remoteTargetHandles[0].mTransformParams.getTargetSet();
+ targets = remoteTargetHandles[0].getTransformParams().getTargetSet();
} else {
- TransformParams topLeftParams = remoteTargetHandles[0].mTransformParams;
- TransformParams rightBottomParams = remoteTargetHandles[1].mTransformParams;
+ TransformParams topLeftParams = remoteTargetHandles[0].getTransformParams();
+ TransformParams rightBottomParams = remoteTargetHandles[1].getTransformParams();
RemoteAnimationTargetCompat[] apps = Stream.concat(
Arrays.stream(topLeftParams.getTargetSet().apps),
Arrays.stream(rightBottomParams.getTargetSet().apps))
diff --git a/quickstep/robolectric_tests/src/com/android/quickstep/util/RecentsOrientedStateTest.java b/quickstep/tests/src/com/android/quickstep/util/RecentsOrientedStateTest.java
similarity index 89%
rename from quickstep/robolectric_tests/src/com/android/quickstep/util/RecentsOrientedStateTest.java
rename to quickstep/tests/src/com/android/quickstep/util/RecentsOrientedStateTest.java
index 656379f..47ef13b 100644
--- a/quickstep/robolectric_tests/src/com/android/quickstep/util/RecentsOrientedStateTest.java
+++ b/quickstep/tests/src/com/android/quickstep/util/RecentsOrientedStateTest.java
@@ -19,33 +19,34 @@
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_90;
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import android.content.Context;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
import com.android.quickstep.FallbackActivityInterface;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.LooperMode;
-import org.robolectric.annotation.LooperMode.Mode;
/**
* Tests for {@link RecentsOrientedState}
*/
-@RunWith(RobolectricTestRunner.class)
-@LooperMode(Mode.PAUSED)
+@SmallTest
+@RunWith(AndroidJUnit4.class)
public class RecentsOrientedStateTest {
private RecentsOrientedState mR1, mR2;
@Before
public void setup() {
- Context context = RuntimeEnvironment.application;
+ Context context = getApplicationContext();
mR1 = new RecentsOrientedState(context, FallbackActivityInterface.INSTANCE, i -> { });
mR2 = new RecentsOrientedState(context, FallbackActivityInterface.INSTANCE, i -> { });
assertEquals(mR1.getStateId(), mR2.getStateId());
diff --git a/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java b/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
new file mode 100644
index 0000000..9c5cfcd
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.util;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.view.Display;
+import android.view.Surface;
+import android.view.SurfaceControl;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.DisplayController.Info;
+import com.android.launcher3.util.LauncherModelHelper;
+import com.android.launcher3.util.ReflectionHelpers;
+import com.android.quickstep.FallbackActivityInterface;
+import com.android.quickstep.SysUINavigationMode;
+import com.android.quickstep.SystemUiProxy;
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
+
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TaskViewSimulatorTest {
+
+ @Test
+ public void taskProperlyScaled_portrait_noRotation_sameInsets1() {
+ new TaskMatrixVerifier()
+ .withLauncherSize(1200, 2450)
+ .withInsets(new Rect(0, 80, 0, 120))
+ .verifyNoTransforms();
+ }
+
+ @Test
+ public void taskProperlyScaled_portrait_noRotation_sameInsets2() {
+ new TaskMatrixVerifier()
+ .withLauncherSize(1200, 2450)
+ .withInsets(new Rect(55, 80, 55, 120))
+ .verifyNoTransforms();
+ }
+
+ @Test
+ public void taskProperlyScaled_landscape_noRotation_sameInsets1() {
+ new TaskMatrixVerifier()
+ .withLauncherSize(2450, 1250)
+ .withInsets(new Rect(0, 80, 0, 40))
+ .verifyNoTransforms();
+ }
+
+ @Test
+ public void taskProperlyScaled_landscape_noRotation_sameInsets2() {
+ new TaskMatrixVerifier()
+ .withLauncherSize(2450, 1250)
+ .withInsets(new Rect(0, 80, 120, 0))
+ .verifyNoTransforms();
+ }
+
+ @Test
+ public void taskProperlyScaled_landscape_noRotation_sameInsets3() {
+ new TaskMatrixVerifier()
+ .withLauncherSize(2450, 1250)
+ .withInsets(new Rect(55, 80, 55, 120))
+ .verifyNoTransforms();
+ }
+
+ @Test
+ public void taskProperlyScaled_landscape_rotated() {
+ new TaskMatrixVerifier()
+ .withLauncherSize(1200, 2450)
+ .withInsets(new Rect(0, 80, 0, 120))
+ .withAppBounds(
+ new Rect(0, 0, 2450, 1200),
+ new Rect(0, 80, 0, 120),
+ Surface.ROTATION_90)
+ .verifyNoTransforms();
+ }
+
+ private static class TaskMatrixVerifier extends TransformParams {
+
+ private Point mDisplaySize = new Point();
+ private Rect mDisplayInsets = new Rect();
+ private Rect mAppBounds = new Rect();
+ private Rect mLauncherInsets = new Rect();
+
+ private Rect mAppInsets;
+
+ private int mAppRotation = -1;
+ private DeviceProfile mDeviceProfile;
+
+ TaskMatrixVerifier withLauncherSize(int width, int height) {
+ mDisplaySize.set(width, height);
+ if (mAppBounds.isEmpty()) {
+ mAppBounds.set(0, 0, width, height);
+ }
+ return this;
+ }
+
+ TaskMatrixVerifier withInsets(Rect insets) {
+ mDisplayInsets.set(insets);
+ mLauncherInsets.set(insets);
+ return this;
+ }
+
+ TaskMatrixVerifier withAppBounds(Rect bounds, Rect insets, int appRotation) {
+ mAppBounds.set(bounds);
+ mAppInsets = insets;
+ mAppRotation = appRotation;
+ return this;
+ }
+
+ void verifyNoTransforms() {
+ LauncherModelHelper helper = new LauncherModelHelper();
+ try {
+ helper.sandboxContext.allow(SystemUiProxy.INSTANCE);
+ helper.sandboxContext.allow(SysUINavigationMode.INSTANCE);
+
+ Display display = mock(Display.class);
+ doReturn(DEFAULT_DISPLAY).when(display).getDisplayId();
+ doReturn(mDisplaySize.x > mDisplaySize.y ? Surface.ROTATION_90 : Surface.ROTATION_0)
+ .when(display).getRotation();
+ doAnswer(i -> {
+ ((Point) i.getArgument(0)).set(mDisplaySize.x, mDisplaySize.y);
+ return null;
+ }).when(display).getRealSize(any());
+ doAnswer(i -> {
+ Point smallestSize = i.getArgument(0);
+ Point largestSize = i.getArgument(1);
+ smallestSize.x = smallestSize.y = Math.min(mDisplaySize.x, mDisplaySize.y);
+ largestSize.x = largestSize.y = Math.max(mDisplaySize.x, mDisplaySize.y);
+
+ smallestSize.x -= mDisplayInsets.left + mDisplayInsets.right;
+ largestSize.x -= mDisplayInsets.left + mDisplayInsets.right;
+
+ smallestSize.y -= mDisplayInsets.top + mDisplayInsets.bottom;
+ largestSize.y -= mDisplayInsets.top + mDisplayInsets.bottom;
+ return null;
+ }).when(display).getCurrentSizeRange(any(), any());
+ DisplayController.Info mockInfo = new Info(helper.sandboxContext, display);
+
+ DisplayController controller =
+ DisplayController.INSTANCE.get(helper.sandboxContext);
+ controller.close();
+ ReflectionHelpers.setField(controller, "mInfo", mockInfo);
+
+ mDeviceProfile = InvariantDeviceProfile.INSTANCE.get(helper.sandboxContext)
+ .getBestMatch(mAppBounds.width(), mAppBounds.height());
+ mDeviceProfile.updateInsets(mLauncherInsets);
+
+ TaskViewSimulator tvs = new TaskViewSimulator(helper.sandboxContext,
+ FallbackActivityInterface.INSTANCE);
+ tvs.setDp(mDeviceProfile);
+
+ int launcherRotation = mockInfo.rotation;
+ if (mAppRotation < 0) {
+ mAppRotation = launcherRotation;
+ }
+
+ tvs.getOrientationState().update(launcherRotation, mAppRotation);
+ if (mAppInsets == null) {
+ mAppInsets = new Rect(mLauncherInsets);
+ }
+ tvs.setPreviewBounds(mAppBounds, mAppInsets);
+
+ tvs.fullScreenProgress.value = 1;
+ tvs.recentsViewScale.value = tvs.getFullScreenScale();
+ tvs.apply(this);
+ } finally {
+ helper.destroy();
+ }
+ }
+
+ @Override
+ public SurfaceParams[] createSurfaceParams(BuilderProxy proxy) {
+ SurfaceParams.Builder builder = new SurfaceParams.Builder((SurfaceControl) null);
+ proxy.onBuildTargetParams(builder, mock(RemoteAnimationTargetCompat.class), this);
+ return new SurfaceParams[] {builder.build()};
+ }
+
+ @Override
+ public void applySurfaceParams(SurfaceParams[] params) {
+ // Verify that the task position remains the same
+ RectF newAppBounds = new RectF(mAppBounds);
+ params[0].matrix.mapRect(newAppBounds);
+ Assert.assertThat(newAppBounds, new AlmostSame(mAppBounds));
+
+ System.err.println("Bounds mapped: " + mAppBounds + " => " + newAppBounds);
+ }
+ }
+
+ private static class AlmostSame extends TypeSafeMatcher<RectF> {
+
+ // Allow .1% error margin to account for float to int conversions
+ private final float mErrorFactor = .001f;
+ private final Rect mExpected;
+
+ AlmostSame(Rect expected) {
+ mExpected = expected;
+ }
+
+ @Override
+ protected boolean matchesSafely(RectF item) {
+ float errorWidth = mErrorFactor * mExpected.width();
+ float errorHeight = mErrorFactor * mExpected.height();
+ return Math.abs(item.left - mExpected.left) < errorWidth
+ && Math.abs(item.top - mExpected.top) < errorHeight
+ && Math.abs(item.right - mExpected.right) < errorWidth
+ && Math.abs(item.bottom - mExpected.bottom) < errorHeight;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendValue(mExpected);
+ }
+ }
+}
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index a2189c9..244cb59 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -548,15 +548,18 @@
Resources res = context.getResources();
Configuration config = context.getResources().getConfiguration();
- float availableWidth = config.screenWidthDp * res.getDisplayMetrics().density;
- float availableHeight = config.screenHeightDp * res.getDisplayMetrics().density;
+ float screenWidth = config.screenWidthDp * res.getDisplayMetrics().density;
+ float screenHeight = config.screenHeightDp * res.getDisplayMetrics().density;
+ return getBestMatch(screenWidth, screenHeight);
+ }
+ public DeviceProfile getBestMatch(float screenWidth, float screenHeight) {
DeviceProfile bestMatch = supportedProfiles.get(0);
float minDiff = Float.MAX_VALUE;
for (DeviceProfile profile : supportedProfiles) {
- float diff = Math.abs(profile.availableWidthPx - availableWidth)
- + Math.abs(profile.availableHeightPx - availableHeight);
+ float diff = Math.abs(profile.widthPx - screenWidth)
+ + Math.abs(profile.heightPx - screenHeight);
if (diff < minDiff) {
minDiff = diff;
bestMatch = profile;
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 8e1a09c..ed9f044 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -2229,6 +2229,9 @@
ArrayList<ItemInfo> addAnimated) {
// Add the new screens
if (newScreens != null) {
+ // newScreens can contain an empty right panel that is already bound, but not known
+ // by BgDataModel.
+ newScreens.removeAllValues(mWorkspace.mScreenOrder);
bindAddScreens(newScreens);
}
diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java
index 915e140..f348a33 100644
--- a/src/com/android/launcher3/settings/SettingsActivity.java
+++ b/src/com/android/launcher3/settings/SettingsActivity.java
@@ -62,8 +62,9 @@
SharedPreferences.OnSharedPreferenceChangeListener{
/** List of fragments that can be hosted by this activity. */
- private static final List<String> VALID_PREFERENCE_FRAGMENTS = Collections.singletonList(
- DeveloperOptionsFragment.class.getName());
+ private static final List<String> VALID_PREFERENCE_FRAGMENTS =
+ !Utilities.IS_DEBUG_DEVICE ? Collections.emptyList()
+ : Collections.singletonList(DeveloperOptionsFragment.class.getName());
private static final String DEVELOPER_OPTIONS_KEY = "pref_developer_options";
private static final String FLAGS_PREFERENCE_KEY = "flag_toggler";
diff --git a/src/com/android/launcher3/util/ItemInfoMatcher.java b/src/com/android/launcher3/util/ItemInfoMatcher.java
index e8ba28f..ab3083d 100644
--- a/src/com/android/launcher3/util/ItemInfoMatcher.java
+++ b/src/com/android/launcher3/util/ItemInfoMatcher.java
@@ -32,6 +32,11 @@
*/
public interface ItemInfoMatcher {
+ /**
+ * Empty component used for match testing
+ */
+ ComponentName EMPTY_COMPONENT = new ComponentName("", "");
+
boolean matches(ItemInfo info, ComponentName cn);
/**
@@ -40,7 +45,7 @@
default boolean matchesInfo(ItemInfo info) {
if (info != null) {
ComponentName cn = info.getTargetComponent();
- return cn != null && matches(info, cn);
+ return matches(info, cn != null ? cn : EMPTY_COMPONENT);
} else {
return false;
}