Merge "Check kotlin format before uploading" into tm-qpr-dev
diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml
index 02a439d..bd11c1e 100644
--- a/quickstep/res/layout/task.xml
+++ b/quickstep/res/layout/task.xml
@@ -28,12 +28,14 @@
android:layout_width="match_parent"
android:layout_height="match_parent"/>
+ <!-- Filtering affects only alpha instead of the visibility since visibility can be altered
+ separately through RecentsView#resetFromSplitSelectionState() -->
<ImageView
android:id="@+id/show_windows"
android:layout_height="@dimen/recents_filter_icon_size"
android:layout_width="@dimen/recents_filter_icon_size"
android:layout_gravity="end"
- android:visibility="gone"
+ android:alpha="0"
android:tint="@color/recents_filter_icon"
android:contentDescription="@string/recents_filter_icon_desc"
android:importantForAccessibility="no"
diff --git a/quickstep/res/layout/task_grouped.xml b/quickstep/res/layout/task_grouped.xml
index 7792801..ec03c69 100644
--- a/quickstep/res/layout/task_grouped.xml
+++ b/quickstep/res/layout/task_grouped.xml
@@ -38,23 +38,27 @@
android:layout_width="match_parent"
android:layout_height="match_parent"/>
+ <!-- Filtering affects only alpha instead of the visibility since visibility can be altered
+ separately through RecentsView#resetFromSplitSelectionState() -->
<ImageView
android:id="@+id/show_windows"
android:layout_height="@dimen/recents_filter_icon_size"
android:layout_width="@dimen/recents_filter_icon_size"
android:layout_gravity="start"
- android:visibility="gone"
+ android:alpha="0"
android:tint="@color/recents_filter_icon"
android:contentDescription="@string/recents_filter_icon_desc"
android:importantForAccessibility="no"
android:src="@drawable/ic_select_windows" />
+ <!-- Filtering affects only alpha instead of the visibility since visibility can be altered
+ separately through RecentsView#resetFromSplitSelectionState() -->
<ImageView
android:id="@+id/show_windows_right"
android:layout_height="@dimen/recents_filter_icon_size"
android:layout_width="@dimen/recents_filter_icon_size"
android:layout_gravity="end"
- android:visibility="gone"
+ android:alpha="0"
android:tint="@color/recents_filter_icon"
android:contentDescription="@string/recents_filter_icon_desc"
android:importantForAccessibility="no"
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index 86ea264..c7664be 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -78,7 +78,7 @@
<string name="allset_title" msgid="5021126669778966707">"Fertig!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Nach oben wischen, um den Startbildschirm aufzurufen"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"Startbildschirmtaste drücken, um zum Startbildschirm zu gehen"</string>
- <string name="allset_description_generic" msgid="5385500062202019855">"Du kannst dein Gerät (<xliff:g id="DEVICE">%1$s</xliff:g>) jetzt verwenden"</string>
+ <string name="allset_description_generic" msgid="5385500062202019855">"Du kannst dein <xliff:g id="DEVICE">%1$s</xliff:g> jetzt verwenden"</string>
<string name="default_device_name" msgid="6660656727127422487">"Gerät"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Einstellungen der Systemsteuerung"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Teilen"</string>
diff --git a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
index 95a94ec..9f9f2c8 100644
--- a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
+++ b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
@@ -28,12 +28,15 @@
import android.content.Context;
import android.os.Build;
import android.os.Handler;
+import android.os.RemoteException;
+import android.view.IRemoteAnimationFinishedCallback;
import android.view.RemoteAnimationTarget;
import androidx.annotation.BinderThread;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
+import com.android.systemui.animation.RemoteAnimationDelegate;
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
import java.lang.ref.WeakReference;
@@ -89,7 +92,7 @@
Runnable r = () -> {
finishExistingAnimation();
mAnimationResult = new AnimationResult(() -> mAnimationResult = null, runnable);
- getFactory().onCreateAnimation(transit, appTargets, wallpaperTargets, nonAppTargets,
+ getFactory().onAnimationStart(transit, appTargets, wallpaperTargets, nonAppTargets,
mAnimationResult);
};
if (mStartAtFrontOfQueue) {
@@ -124,7 +127,11 @@
});
}
- public static final class AnimationResult {
+ /**
+ * Used by RemoteAnimationFactory implementations to run the actual animation and its lifecycle
+ * callbacks.
+ */
+ public static final class AnimationResult extends IRemoteAnimationFinishedCallback.Stub {
private final Runnable mSyncFinishRunnable;
private final Runnable mASyncFinishRunnable;
@@ -199,25 +206,41 @@
}
}
}
+
+ /**
+ * When used as a simple IRemoteAnimationFinishedCallback, this method is used to run the
+ * animation finished runnable.
+ */
+ @Override
+ public void onAnimationFinished() throws RemoteException {
+ mASyncFinishRunnable.run();
+ }
}
/**
* Used with LauncherAnimationRunner as an interface for the runner to call back to the
* implementation.
*/
- @FunctionalInterface
- public interface RemoteAnimationFactory {
+ public interface RemoteAnimationFactory extends RemoteAnimationDelegate<AnimationResult> {
/**
* Called on the UI thread when the animation targets are received. The implementation must
* call {@link AnimationResult#setAnimation} with the target animation to be run.
*/
- void onCreateAnimation(int transit,
+ @Override
+ @UiThread
+ void onAnimationStart(int transit,
RemoteAnimationTarget[] appTargets,
RemoteAnimationTarget[] wallpaperTargets,
RemoteAnimationTarget[] nonAppTargets,
LauncherAnimationRunner.AnimationResult result);
+ @Override
+ @UiThread
+ default void onAnimationCancelled(boolean isKeyguardOccluded) {
+ onAnimationCancelled();
+ }
+
/**
* Called when the animation is cancelled. This can happen with or without
* the create being called.
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 2aa0af4..668567e 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -1665,7 +1665,7 @@
}
@Override
- public void onCreateAnimation(int transit,
+ public void onAnimationStart(int transit,
RemoteAnimationTarget[] appTargets,
RemoteAnimationTarget[] wallpaperTargets,
RemoteAnimationTarget[] nonAppTargets,
@@ -1707,7 +1707,7 @@
}
@Override
- public void onCreateAnimation(int transit,
+ public void onAnimationStart(int transit,
RemoteAnimationTarget[] appTargets,
RemoteAnimationTarget[] wallpaperTargets,
RemoteAnimationTarget[] nonAppTargets,
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 22f7f13..a18aabe 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -310,7 +310,7 @@
return;
}
mTaskbarInAppDisplayProgress.put(progressIndex, progress);
- if (!mControllers.taskbarStashController.isInApp()
+ if (mControllers.uiController.isIconAlignedWithHotseat()
&& !mTaskbarLauncherStateController.isAnimatingToLauncher()) {
// Only animate the nav buttons while home and not animating home, otherwise let
// the TaskbarViewController handle it.
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index 049c672..86e1911 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -320,6 +320,12 @@
}
}
+ public void onLongPressHomeEnabled(boolean assistantLongPressEnabled) {
+ if (mNavButtonController != null) {
+ mNavButtonController.setAssistantLongPressEnabled(assistantLongPressEnabled);
+ }
+ }
+
/**
* Sets the flag indicating setup UI is visible
*/
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
index a395548..5bb958a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
@@ -67,6 +67,7 @@
private long mLastScreenPinLongPress;
private boolean mScreenPinned;
+ private boolean mAssistantLongPressEnabled;
@Override
public void dumpLogs(String prefix, PrintWriter pw) {
@@ -251,6 +252,10 @@
mStatsLogManager = null;
}
+ public void setAssistantLongPressEnabled(boolean assistantLongPressEnabled) {
+ mAssistantLongPressEnabled = assistantLongPressEnabled;
+ }
+
private void logEvent(StatsLogManager.LauncherEvent event) {
if (mStatsLogManager == null) {
Log.w(TAG, "No stats log manager to log taskbar button event");
@@ -289,7 +294,7 @@
}
private void startAssistant() {
- if (mScreenPinned) {
+ if (mScreenPinned || !mAssistantLongPressEnabled) {
return;
}
Bundle args = new Bundle();
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 857ace2..8409475 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -324,6 +324,9 @@
// May be set to false when mIsTransientTaskbar is true.
private boolean mCanSlowSwipeGoHome = true;
+ @Nullable
+ private RemoteAnimationTargets.ReleaseCheck mSwipePipToHomeReleaseCheck = null;
+
public AbsSwipeUpHandler(Context context, RecentsAnimationDeviceState deviceState,
TaskAnimationManager taskAnimationManager, GestureState gestureState,
long touchTimeMs, boolean continuingLastGesture,
@@ -869,6 +872,9 @@
mRemoteTargetHandles = mTargetGluer.assignTargetsForSplitScreen(mContext, targets);
mRecentsAnimationController = controller;
mRecentsAnimationTargets = targets;
+ mSwipePipToHomeReleaseCheck = new RemoteAnimationTargets.ReleaseCheck();
+ mSwipePipToHomeReleaseCheck.setCanRelease(true);
+ mRecentsAnimationTargets.addReleaseCheck(mSwipePipToHomeReleaseCheck);
// Only initialize the device profile, if it has not been initialized before, as in some
// configurations targets.homeContentInsets may not be correct.
@@ -1430,9 +1436,16 @@
mSwipePipToHomeAnimator = createWindowAnimationToPip(
homeAnimFactory, runningTaskTarget, start);
mSwipePipToHomeAnimators[0] = mSwipePipToHomeAnimator;
+ if (mSwipePipToHomeReleaseCheck != null) {
+ mSwipePipToHomeReleaseCheck.setCanRelease(false);
+ }
windowAnim = mSwipePipToHomeAnimators;
} else {
mSwipePipToHomeAnimator = null;
+ if (mSwipePipToHomeReleaseCheck != null) {
+ mSwipePipToHomeReleaseCheck.setCanRelease(true);
+ mSwipePipToHomeReleaseCheck = null;
+ }
windowAnim = createWindowAnimationToHome(start, homeAnimFactory);
windowAnim[0].addAnimatorListener(new AnimationSuccessListener() {
@@ -1954,6 +1967,10 @@
finishRecentsControllerToHome(
() -> mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED));
}
+ if (mSwipePipToHomeReleaseCheck != null) {
+ mSwipePipToHomeReleaseCheck.setCanRelease(true);
+ mSwipePipToHomeReleaseCheck = null;
+ }
doLogGesture(HOME, mRecentsView == null ? null : mRecentsView.getCurrentPageTaskView());
}
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index dc405ff..6f86bf5 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -240,7 +240,7 @@
mActivityLaunchAnimationRunner = new RemoteAnimationFactory() {
@Override
- public void onCreateAnimation(int transit, RemoteAnimationTarget[] appTargets,
+ public void onAnimationStart(int transit, RemoteAnimationTarget[] appTargets,
RemoteAnimationTarget[] wallpaperTargets,
RemoteAnimationTarget[] nonAppTargets, AnimationResult result) {
mHandler.removeCallbacks(mAnimationStartTimeoutRunnable);
@@ -407,28 +407,24 @@
}
private final RemoteAnimationFactory mAnimationToHomeFactory =
- new RemoteAnimationFactory() {
- @Override
- public void onCreateAnimation(int transit, RemoteAnimationTarget[] appTargets,
- RemoteAnimationTarget[] wallpaperTargets,
- RemoteAnimationTarget[] nonAppTargets, AnimationResult result) {
- AnimatorPlaybackController controller = getStateManager()
- .createAnimationToNewWorkspace(RecentsState.BG_LAUNCHER, HOME_APPEAR_DURATION);
- controller.dispatchOnStart();
+ (transit, appTargets, wallpaperTargets, nonAppTargets, result) -> {
+ AnimatorPlaybackController controller =
+ getStateManager().createAnimationToNewWorkspace(
+ RecentsState.BG_LAUNCHER, HOME_APPEAR_DURATION);
+ controller.dispatchOnStart();
- RemoteAnimationTargets targets = new RemoteAnimationTargets(
- appTargets, wallpaperTargets, nonAppTargets, MODE_OPENING);
- for (RemoteAnimationTarget app : targets.apps) {
- new Transaction().setAlpha(app.leash, 1).apply();
- }
- AnimatorSet anim = new AnimatorSet();
- anim.play(controller.getAnimationPlayer());
- anim.setDuration(HOME_APPEAR_DURATION);
- result.setAnimation(anim, RecentsActivity.this,
- () -> getStateManager().goToState(RecentsState.HOME, false),
- true /* skipFirstFrame */);
- }
- };
+ RemoteAnimationTargets targets = new RemoteAnimationTargets(
+ appTargets, wallpaperTargets, nonAppTargets, MODE_OPENING);
+ for (RemoteAnimationTarget app : targets.apps) {
+ new Transaction().setAlpha(app.leash, 1).apply();
+ }
+ AnimatorSet anim = new AnimatorSet();
+ anim.play(controller.getAnimationPlayer());
+ anim.setDuration(HOME_APPEAR_DURATION);
+ result.setAnimation(anim, RecentsActivity.this,
+ () -> getStateManager().goToState(RecentsState.HOME, false),
+ true /* skipFirstFrame */);
+ };
@Override
protected void collectStateHandlers(List<StateHandler> out) {
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index b7252bc..67de4b1 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -22,6 +22,8 @@
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
+import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
+import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.QuickstepTransitionManager.ANIMATION_DELAY_NAV_FADE_IN;
@@ -330,6 +332,17 @@
Matrix localMti = new Matrix();
localMt.invert(localMti);
mti[i] = localMti;
+
+ // Translations for child thumbnails also get scaled as the parent taskView scales
+ // Add inverse scaling to keep translations the same
+ float translationY = ttv.getTranslationY();
+ float translationX = ttv.getTranslationX();
+ float fullScreenScale =
+ topMostSimulators[i].getTaskViewSimulator().getFullScreenScale();
+ out.addFloat(ttv, VIEW_TRANSLATE_Y, translationY,
+ translationY / fullScreenScale, TOUCH_RESPONSE_INTERPOLATOR);
+ out.addFloat(ttv, VIEW_TRANSLATE_X, translationX,
+ translationX / fullScreenScale, TOUCH_RESPONSE_INTERPOLATOR);
}
Matrix[] k0i = new Matrix[matrixSize];
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 2565697..5d17cc7 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -216,10 +216,12 @@
@BinderThread
@Override
- public void onAssistantAvailable(boolean available) {
+ public void onAssistantAvailable(boolean available, boolean longPressHomeEnabled) {
MAIN_EXECUTOR.execute(() -> {
mDeviceState.setAssistantAvailable(available);
TouchInteractionService.this.onAssistantVisibilityChanged();
+ executeForTaskbarManager(() -> mTaskbarManager
+ .onLongPressHomeEnabled(longPressHomeEnabled));
});
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 6862874..9cf0601 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -1557,6 +1557,11 @@
ActiveGestureErrorDetector.GestureEvent.SCROLLER_ANIMATION_ABORTED);
}
+ @Override
+ protected boolean isPageScrollsInitialized() {
+ return super.isPageScrollsInitialized() && mLoadPlanEverApplied;
+ }
+
protected void applyLoadPlan(ArrayList<GroupTask> taskGroups) {
if (mPendingAnimation != null) {
mPendingAnimation.addEndListener(success -> applyLoadPlan(taskGroups));
@@ -1570,6 +1575,9 @@
// With all tasks removed, touch handling in PagedView is disabled and we need to reset
// touch state or otherwise values will be obsolete.
resetTouchState();
+ if (isPageScrollsInitialized()) {
+ onPageScrollsInitialized();
+ }
return;
}
@@ -1723,6 +1731,9 @@
resetTaskVisuals();
onTaskStackUpdated();
updateEnabledOverlays();
+ if (isPageScrollsInitialized()) {
+ onPageScrollsInitialized();
+ }
}
private boolean isModal() {
@@ -2066,7 +2077,7 @@
if (!mActivity.getDeviceProfile().isTablet) {
return super.getDestinationPage(scaledScroll);
}
- if (!pageScrollsInitialized()) {
+ if (!isPageScrollsInitialized()) {
Log.e(TAG,
"Cannot get destination page: RecentsView not properly initialized",
new IllegalStateException());
@@ -3178,8 +3189,6 @@
}
}
- announceForAccessibility(getResources().getString(R.string.task_view_closed));
-
float dismissTranslationInterpolationEnd = 1;
boolean closeGapBetweenClearAll = false;
boolean isClearAllHidden = isClearAllHidden();
@@ -3506,6 +3515,8 @@
} else {
removeTaskInternal(dismissedTaskViewId);
}
+ announceForAccessibility(
+ getResources().getString(R.string.task_view_closed));
mActivity.getStatsLogManager().logger()
.withItemInfo(dismissedTaskView.getItemInfo())
.log(LAUNCHER_TASK_DISMISS_SWIPE_UP);
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 1d9e05f..aa37fdd 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -561,10 +561,12 @@
*/
protected void updateFilterCallback(@NonNull View filterView,
@Nullable View.OnClickListener callback) {
+ // Filtering changes alpha instead of the visibility since visibility
+ // can be altered separately through RecentsView#resetFromSplitSelectionState()
if (callback == null) {
- filterView.setVisibility(GONE);
+ filterView.setAlpha(0);
} else {
- filterView.setVisibility(VISIBLE);
+ filterView.setAlpha(1);
}
filterView.setOnClickListener(callback);
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
index 4eec319..9622619 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
@@ -18,6 +18,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -103,12 +104,20 @@
}
@Test
- public void testLongPressHome() {
+ public void testLongPressHome_enabled() {
+ mNavButtonController.setAssistantLongPressEnabled(true /*assistantLongPressEnabled*/);
mNavButtonController.onButtonLongClick(BUTTON_HOME, mockView);
verify(mockSystemUiProxy, times(1)).startAssistant(any());
}
@Test
+ public void testLongPressHome_disabled() {
+ mNavButtonController.setAssistantLongPressEnabled(false /*assistantLongPressEnabled*/);
+ mNavButtonController.onButtonLongClick(BUTTON_HOME, mockView);
+ verify(mockSystemUiProxy, never()).startAssistant(any());
+ }
+
+ @Test
public void testPressHome() {
mNavButtonController.onButtonClick(BUTTON_HOME, mockView);
verify(mockCommandHelper, times(1)).addCommand(TYPE_HOME);
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 9a2fcc0..9f34775 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -262,6 +262,19 @@
return launchedAppState;
}
+ private void quickSwitchToPreviousAppAndAssert(boolean toRight) {
+ final LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
+ if (toRight) {
+ launchedAppState.quickSwitchToPreviousApp();
+ } else {
+ launchedAppState.quickSwitchToPreviousAppSwipeLeft();
+ }
+
+ // While enable shell transition, Launcher can be resumed due to transient launch.
+ waitForLauncherCondition("Launcher shouldn't stay in resume forever",
+ this::isInLaunchedApp, 3000 /* timeout */);
+ }
+
@Test
@PortraitLandscape
public void testAllAppsFromHome() throws Exception {
@@ -288,13 +301,11 @@
startTestActivity(3);
startTestActivity(4);
- LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
- launchedAppState.quickSwitchToPreviousApp();
+ quickSwitchToPreviousAppAndAssert(true /* toRight */);
assertTrue("The first app we should have quick switched to is not running",
isTestActivityRunning(3));
- launchedAppState = getAndAssertLaunchedApp();
- launchedAppState.quickSwitchToPreviousApp();
+ quickSwitchToPreviousAppAndAssert(true /* toRight */);
if (mLauncher.getNavigationModel() == NavigationModel.THREE_BUTTON) {
// 3-button mode toggles between 2 apps, rather than going back further.
assertTrue("Second quick switch should have returned to the first app.",
@@ -303,12 +314,12 @@
assertTrue("The second app we should have quick switched to is not running",
isTestActivityRunning(2));
}
- launchedAppState = getAndAssertLaunchedApp();
- launchedAppState.quickSwitchToPreviousAppSwipeLeft();
+
+ quickSwitchToPreviousAppAndAssert(false /* toRight */);
assertTrue("The 2nd app we should have quick switched to is not running",
isTestActivityRunning(3));
- launchedAppState = getAndAssertLaunchedApp();
+ final LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
launchedAppState.switchToOverview();
}
@@ -327,8 +338,10 @@
launchedAppState.assertTaskbarHidden();
// Quick-switch to the test app with swiping to right.
- launchedAppState.quickSwitchToPreviousApp();
+ quickSwitchToPreviousAppAndAssert(true /* toRight */);
+ assertTrue("The first app we should have quick switched to is not running",
+ isTestActivityRunning(2));
// Expect task bar visible when the launched app was the test activity.
launchedAppState = getAndAssertLaunchedApp();
launchedAppState.assertTaskbarVisible();
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index eb68adb..4f5cc4a 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -699,7 +699,7 @@
}
/** Returns true iff this PagedView's scroll amounts are initialized to each page index. */
- protected boolean pageScrollsInitialized() {
+ protected boolean isPageScrollsInitialized() {
return mPageScrolls != null && mPageScrolls.length == getChildCount();
}
@@ -708,12 +708,12 @@
*/
public void runOnPageScrollsInitialized(Runnable callback) {
mOnPageScrollsInitializedCallbacks.add(callback);
- if (pageScrollsInitialized()) {
+ if (isPageScrollsInitialized()) {
onPageScrollsInitialized();
}
}
- private void onPageScrollsInitialized() {
+ protected void onPageScrollsInitialized() {
for (Runnable callback : mOnPageScrollsInitializedCallbacks) {
callback.run();
}
@@ -727,7 +727,7 @@
final int childCount = getChildCount();
int[] pageScrolls = mPageScrolls;
boolean pageScrollChanged = false;
- if (!pageScrollsInitialized()) {
+ if (!isPageScrollsInitialized()) {
pageScrolls = new int[childCount];
pageScrollChanged = true;
}
@@ -1199,7 +1199,7 @@
}
public int getScrollForPage(int index) {
- if (!pageScrollsInitialized() || index >= mPageScrolls.length || index < 0) {
+ if (!isPageScrollsInitialized() || index >= mPageScrolls.length || index < 0) {
return 0;
} else {
return mPageScrolls[index];
@@ -1209,7 +1209,7 @@
// While layout transitions are occurring, a child's position may stray from its baseline
// position. This method returns the magnitude of this stray at any given time.
public int getLayoutTransitionOffsetForPage(int index) {
- if (!pageScrollsInitialized() || index >= mPageScrolls.length || index < 0) {
+ if (!isPageScrollsInitialized() || index >= mPageScrolls.length || index < 0) {
return 0;
} else {
View child = getChildAt(index);
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index b10256e..d7e84f0 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -723,4 +723,14 @@
}
return options;
}
+
+ /** Logs the Scale and Translate properties of a matrix. Ignores skew and perspective. */
+ public static void logMatrix(String label, Matrix matrix) {
+ float[] matrixValues = new float[9];
+ matrix.getValues(matrixValues);
+ Log.d(label, String.format("%s: %s\nscale (x,y) = (%f, %f)\ntranslate (x,y) = (%f, %f)",
+ label, matrix, matrixValues[Matrix.MSCALE_X], matrixValues[Matrix.MSCALE_Y],
+ matrixValues[Matrix.MTRANS_X], matrixValues[Matrix.MTRANS_Y]
+ ));
+ }
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 483309d..2b9c135 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -62,6 +62,7 @@
import android.widget.Toast;
import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
import com.android.launcher3.accessibility.AccessibleDragListenerAdapter;
import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
@@ -161,7 +162,9 @@
protected ShortcutAndWidgetContainer mDragSourceInternal;
- @Thunk final IntSparseArrayMap<CellLayout> mWorkspaceScreens = new IntSparseArrayMap<>();
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ @Thunk public final IntSparseArrayMap<CellLayout> mWorkspaceScreens = new IntSparseArrayMap<>();
+
@Thunk final IntArray mScreenOrder = new IntArray();
@Thunk boolean mDeferRemoveExtraEmptyScreen = false;
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index fc1b830..29767bf 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -239,23 +239,24 @@
mAdapterItems.addAll(mSearchResults);
} else {
int position = 0;
+ boolean addApps = true;
if (mWorkProviderManager != null) {
position += mWorkProviderManager.addWorkItems(mAdapterItems);
- if (!mWorkProviderManager.shouldShowWorkApps()) {
- return;
- }
+ addApps = mWorkProviderManager.shouldShowWorkApps();
}
- String lastSectionName = null;
- for (AppInfo info : mApps) {
- mAdapterItems.add(AdapterItem.asApp(info));
+ if (addApps) {
+ String lastSectionName = null;
+ for (AppInfo info : mApps) {
+ mAdapterItems.add(AdapterItem.asApp(info));
- String sectionName = info.sectionName;
- // Create a new section if the section names do not match
- if (!sectionName.equals(lastSectionName)) {
- lastSectionName = sectionName;
- mFastScrollerSections.add(new FastScrollSectionInfo(sectionName, position));
+ String sectionName = info.sectionName;
+ // Create a new section if the section names do not match
+ if (!sectionName.equals(lastSectionName)) {
+ lastSectionName = sectionName;
+ mFastScrollerSections.add(new FastScrollSectionInfo(sectionName, position));
+ }
+ position++;
}
- position++;
}
}
mAccessibilityResultsCount = (int) mAdapterItems.stream()
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
index ca08164..00e89ba 100644
--- a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
@@ -163,7 +163,8 @@
mWorkManager = new WorkProfileManager(
mActivityContext.getSystemService(UserManager.class),
- this, LauncherPrefs.getPrefs(mActivityContext));
+ this, LauncherPrefs.getPrefs(mActivityContext),
+ mActivityContext.getStatsLogManager());
mAH = Arrays.asList(null, null, null);
mNavBarScrimPaint = new Paint();
mNavBarScrimPaint.setColor(Themes.getAttrColor(context, R.attr.allAppsNavBarScrimColor));
diff --git a/src/com/android/launcher3/allapps/WorkModeSwitch.java b/src/com/android/launcher3/allapps/WorkModeSwitch.java
index c9466a8..11ce738 100644
--- a/src/com/android/launcher3/allapps/WorkModeSwitch.java
+++ b/src/com/android/launcher3/allapps/WorkModeSwitch.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.allapps;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WORK_FAB_BUTTON_COLLAPSE;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WORK_FAB_BUTTON_EXTEND;
import static com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.getTabWidth;
import android.animation.LayoutTransition;
@@ -37,6 +39,7 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.KeyboardInsetAnimationCallback;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.StringCache;
import com.android.launcher3.views.ActivityContext;
/**
@@ -59,6 +62,8 @@
private final int mScrollThreshold;
private ImageView mIcon;
private TextView mTextView;
+ private final StatsLogManager mStatsLogManager;
+
public WorkModeSwitch(@NonNull Context context) {
this(context, null, 0);
@@ -72,6 +77,7 @@
super(context, attrs, defStyleAttr);
mScrollThreshold = Utilities.dpToPx(SCROLL_THRESHOLD_DP);
mActivityContext = ActivityContext.lookupContext(getContext());
+ mStatsLogManager = mActivityContext.getStatsLogManager();
}
@Override
@@ -197,10 +203,12 @@
public void extend() {
mTextView.setVisibility(VISIBLE);
+ mStatsLogManager.logger().log(LAUNCHER_WORK_FAB_BUTTON_EXTEND);
}
public void shrink(){
mTextView.setVisibility(GONE);
+ mStatsLogManager.logger().log(LAUNCHER_WORK_FAB_BUTTON_COLLAPSE);
}
public int getScrollThreshold() {
diff --git a/src/com/android/launcher3/allapps/WorkProfileManager.java b/src/com/android/launcher3/allapps/WorkProfileManager.java
index 547b74c..279f0d3 100644
--- a/src/com/android/launcher3/allapps/WorkProfileManager.java
+++ b/src/com/android/launcher3/allapps/WorkProfileManager.java
@@ -43,8 +43,8 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
+import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip;
import java.lang.annotation.Retention;
@@ -80,6 +80,7 @@
private final UserManager mUserManager;
private final BaseAllAppsContainerView<?> mAllApps;
private final Predicate<ItemInfo> mMatcher;
+ private final StatsLogManager mStatsLogManager;
private WorkModeSwitch mWorkModeSwitch;
@@ -88,11 +89,13 @@
private SharedPreferences mPreferences;
public WorkProfileManager(
- UserManager userManager, BaseAllAppsContainerView<?> allApps, SharedPreferences prefs) {
+ UserManager userManager, BaseAllAppsContainerView<?> allApps, SharedPreferences prefs,
+ StatsLogManager statsLogManager) {
mUserManager = userManager;
mAllApps = allApps;
mPreferences = prefs;
mMatcher = mAllApps.mPersonalMatcher.negate();
+ mStatsLogManager = statsLogManager;
}
/**
@@ -227,9 +230,7 @@
private void onWorkFabClicked(View view) {
if (Utilities.ATLEAST_P && mCurrentState == STATE_ENABLED && mWorkModeSwitch.isEnabled()) {
- ActivityContext activityContext = ActivityContext.lookupContext(
- mWorkModeSwitch.getContext());
- activityContext.getStatsLogManager().logger().log(LAUNCHER_TURN_OFF_WORK_APPS_TAP);
+ mStatsLogManager.logger().log(LAUNCHER_TURN_OFF_WORK_APPS_TAP);
setWorkProfileEnabled(false);
}
}
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index 09fe740..f54d05d 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -568,7 +568,8 @@
.setSpring(new SpringForce(0)
.setDampingRatio(DAMPENING_RATIO)
.setStiffness(STIFFNESS));
- mDelta = view.getResources().getDisplayMetrics().density * PARALLAX_MAX_IN_DP;
+ mDelta = Math.min(
+ range, view.getResources().getDisplayMetrics().density * PARALLAX_MAX_IN_DP);
}
public void animateToPos(float value) {
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index 9a961ca..de47cb5 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -17,6 +17,7 @@
package com.android.launcher3.graphics;
+import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.config.FeatureFlags.ENABLE_DOWNLOAD_APP_UX_V2;
@@ -39,6 +40,7 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.icons.FastBitmapDrawable;
import com.android.launcher3.icons.GraphicsUtils;
import com.android.launcher3.model.data.ItemInfoWithIcon;
@@ -72,12 +74,13 @@
private static final int DISABLED_ICON_ALPHA = (int) (0.6f * MAX_PAINT_ALPHA);
private static final long DURATION_SCALE = 500;
+ private static final long SCALE_AND_ALPHA_ANIM_DURATION = 500;
// The smaller the number, the faster the animation would be.
// Duration = COMPLETE_ANIM_FRACTION * DURATION_SCALE
private static final float COMPLETE_ANIM_FRACTION = 0.3f;
- private static final float SMALL_SCALE = ENABLE_DOWNLOAD_APP_UX_V2.get() ? 0.85f : 0.7f;
+ private static final float SMALL_SCALE = ENABLE_DOWNLOAD_APP_UX_V2.get() ? 0.867f : 0.7f;
private static final float PROGRESS_STROKE_SCALE = 0.075f;
private static final int PRELOAD_ACCENT_COLOR_INDEX = 0;
@@ -110,12 +113,13 @@
private int mTrackAlpha;
private float mTrackLength;
- private float mIconScale;
private boolean mRanFinishAnimation;
- private int mOverlayAlpha = 127;
- private int mRefreshRateMillis;
+ private final int mRefreshRateMillis;
+ private final AnimatedFloat mIconScale = new AnimatedFloat(this::invalidateSelf);
+ private final AnimatedFloat mOverlayAlpha = new AnimatedFloat(this::updateOverlayAlpha);
+ private boolean mShouldAnimateScaleAndAlpha;
// Progress of the internal state. [0, 1] indicates the fraction of completed progress,
// [1, (1 + COMPLETE_ANIM_FRACTION)] indicates the progress of zoom animation.
@@ -155,6 +159,12 @@
mIsDarkMode = isDarkMode;
mRefreshRateMillis = refreshRateMillis;
+ // If it's a pending app we will animate scale and alpha when it's no longer pending.
+ if (ENABLE_DOWNLOAD_APP_UX_V2.get() && info.getProgressLevel() == 0) {
+ mShouldAnimateScaleAndAlpha = true;
+ mOverlayAlpha.updateValue(127);
+ }
+
setLevel(info.getProgressLevel());
setIsStartable(info.isAppStartable());
}
@@ -199,7 +209,8 @@
canvas.drawPath(mScaledProgressPath, mProgressPaint);
int saveCount = canvas.save();
- canvas.scale(mIconScale, mIconScale, bounds.exactCenterX(), bounds.exactCenterY());
+ canvas.scale(
+ mIconScale.value, mIconScale.value, bounds.exactCenterX(), bounds.exactCenterY());
super.drawInternal(canvas, bounds);
canvas.restoreToCount(saveCount);
@@ -301,18 +312,34 @@
* - only icon is drawn in normal state
*/
private void setInternalProgress(float progress) {
+ // Animate scale and alpha from pending to downloading state.
+ if (ENABLE_DOWNLOAD_APP_UX_V2.get()
+ && mShouldAnimateScaleAndAlpha && mInternalStateProgress == 0 && progress > 0) {
+ Animator iconScaleAnimator = mIconScale.animateToValue(SMALL_SCALE);
+ iconScaleAnimator.setDuration(SCALE_AND_ALPHA_ANIM_DURATION);
+ iconScaleAnimator.setInterpolator(EMPHASIZED);
+ iconScaleAnimator.start();
+
+ Animator overlayAlphaAnimator = mOverlayAlpha.animateToValue(0);
+ overlayAlphaAnimator.setDuration(SCALE_AND_ALPHA_ANIM_DURATION);
+ overlayAlphaAnimator.setInterpolator(EMPHASIZED);
+ overlayAlphaAnimator.start();
+ }
+
mInternalStateProgress = progress;
if (progress <= 0) {
- mIconScale = ENABLE_DOWNLOAD_APP_UX_V2.get() ? 1 : SMALL_SCALE;
+ mIconScale.updateValue(ENABLE_DOWNLOAD_APP_UX_V2.get() ? 1 : SMALL_SCALE);
mScaledTrackPath.reset();
mTrackAlpha = MAX_PAINT_ALPHA;
} else if (progress < 1) {
mPathMeasure.getSegment(0, progress * mTrackLength, mScaledProgressPath, true);
if (ENABLE_DOWNLOAD_APP_UX_V2.get()) {
- mPaint.setColorFilter(null);
mPathMeasure.getSegment(0, mTrackLength, mScaledTrackPath, true);
}
- mIconScale = SMALL_SCALE;
+
+ if (!ENABLE_DOWNLOAD_APP_UX_V2.get() || !mShouldAnimateScaleAndAlpha) {
+ mIconScale.updateValue(SMALL_SCALE);
+ }
mTrackAlpha = MAX_PAINT_ALPHA;
} else {
setIsDisabled(mItem.isDisabled());
@@ -321,11 +348,11 @@
if (fraction >= 1) {
// Animation has completed
- mIconScale = 1;
+ mIconScale.updateValue(1);
mTrackAlpha = 0;
} else {
mTrackAlpha = Math.round((1 - fraction) * MAX_PAINT_ALPHA);
- mIconScale = SMALL_SCALE + (1 - SMALL_SCALE) * fraction;
+ mIconScale.updateValue(SMALL_SCALE + (1 - SMALL_SCALE) * fraction);
}
}
invalidateSelf();
@@ -370,9 +397,7 @@
if (!ENABLE_DOWNLOAD_APP_UX_V2.get() || mInternalStateProgress > 0) {
return;
}
- if (applyPendingIconOverlay()) {
- invalidateSelf();
- } else {
+ if (!applyPendingIconOverlay()) {
reschedule();
}
}
@@ -408,7 +433,7 @@
long waveMotionDelay = (mItem.cellX * WAVE_MOTION_DELAY_FACTOR_MILLIS)
+ (mItem.cellY * WAVE_MOTION_DELAY_FACTOR_MILLIS);
long time = SystemClock.uptimeMillis();
- int newAlpha = (int) Utilities.mapBoundToRange(
+ float newAlpha = Utilities.mapBoundToRange(
(float) (time + waveMotionDelay) % ALPHA_DURATION_MILLIS,
0,
ALPHA_DURATION_MILLIS,
@@ -416,22 +441,25 @@
MAX_PAINT_ALPHA,
LINEAR);
if (newAlpha > OVERLAY_ALPHA_RANGE) {
- newAlpha = (int) (OVERLAY_ALPHA_RANGE - (newAlpha % OVERLAY_ALPHA_RANGE));
+ newAlpha = (OVERLAY_ALPHA_RANGE - (newAlpha % OVERLAY_ALPHA_RANGE));
}
boolean invalidate = false;
- if (mOverlayAlpha != newAlpha) {
- mOverlayAlpha = newAlpha;
- int overlayColor = mIsDarkMode ? 0 : 255;
- int currArgb = Color.argb(mOverlayAlpha, overlayColor, overlayColor, overlayColor);
- mPaint.setColorFilter(COLOR_FILTER_MAP.computeIfAbsent(
- currArgb,
- FILTER_FACTORY));
+ if ((int) mOverlayAlpha.value != newAlpha) {
+ mOverlayAlpha.updateValue(newAlpha);
invalidate = true;
}
return invalidate;
}
+ private void updateOverlayAlpha() {
+ int overlayColor = mIsDarkMode ? 0 : 255;
+ int currArgb =
+ Color.argb((int) mOverlayAlpha.value, overlayColor, overlayColor, overlayColor);
+ mPaint.setColorFilter(COLOR_FILTER_MAP.computeIfAbsent(currArgb, FILTER_FACTORY));
+ invalidateSelf();
+ }
+
protected static class PreloadIconConstantState extends FastBitmapConstantState {
protected final ItemInfoWithIcon mInfo;
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index 24d8c9d..2159c6b 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -624,7 +624,13 @@
LAUNCHER_KEYBOARD_SHORTCUT_SPLIT_RIGHT_BOTTOM(1232),
@UiEvent(doc = "User has invoked split to left half with a keyboard shortcut.")
- LAUNCHER_KEYBOARD_SHORTCUT_SPLIT_LEFT_TOP(1233)
+ LAUNCHER_KEYBOARD_SHORTCUT_SPLIT_LEFT_TOP(1233),
+
+ @UiEvent(doc = "User has collapsed the work FAB button by swiping down")
+ LAUNCHER_WORK_FAB_BUTTON_COLLAPSE(1276),
+
+ @UiEvent(doc = "User has collapsed the work FAB button by swiping up")
+ LAUNCHER_WORK_FAB_BUTTON_EXTEND(1277),
;
// ADD MORE
diff --git a/src/com/android/launcher3/model/AllAppsList.java b/src/com/android/launcher3/model/AllAppsList.java
index 6da948c..8f85bfb 100644
--- a/src/com/android/launcher3/model/AllAppsList.java
+++ b/src/com/android/launcher3/model/AllAppsList.java
@@ -18,7 +18,6 @@
import static com.android.launcher3.model.data.AppInfo.COMPONENT_KEY_COMPARATOR;
import static com.android.launcher3.model.data.AppInfo.EMPTY_ARRAY;
-import static com.android.launcher3.testing.shared.TestProtocol.INCORRECT_INFO_UPDATED;
import android.content.ComponentName;
import android.content.Context;
@@ -39,7 +38,6 @@
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.pm.PackageInstallInfo;
-import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.util.FlagOp;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.SafeCloseable;
@@ -275,14 +273,8 @@
}
public void updateIconsAndLabels(HashSet<String> packages, UserHandle user) {
- if (TestProtocol.sDebugTracing) {
- Log.i(INCORRECT_INFO_UPDATED, "updateIconsAndLabels: packages=" + packages);
- }
for (AppInfo info : data) {
if (info.user.equals(user) && packages.contains(info.componentName.getPackageName())) {
- if (TestProtocol.sDebugTracing) {
- Log.i(INCORRECT_INFO_UPDATED, "updateIconsAndLabels: updating info=" + info);
- }
mIconCache.updateTitleAndIcon(info);
info.sectionName = mIndex.computeSectionName(info.title);
mDataChanged = true;
diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java
index 3e2d051..7ab3013 100644
--- a/src/com/android/launcher3/settings/SettingsActivity.java
+++ b/src/com/android/launcher3/settings/SettingsActivity.java
@@ -268,8 +268,8 @@
return !WidgetsModel.GO_DISABLE_NOTIFICATION_DOTS;
case ALLOW_ROTATION_PREFERENCE_KEY:
- DisplayController.Info info = InvariantDeviceProfile.INSTANCE.get(
- getContext()).getDeviceProfile(getContext()).getDisplayInfo();
+ DisplayController.Info info =
+ DisplayController.INSTANCE.get(getContext()).getInfo();
if (info.isTablet(info.realBounds)) {
// Launcher supports rotation by default. No need to show this setting.
return false;
diff --git a/src/com/android/launcher3/testing/shared/TestProtocol.java b/src/com/android/launcher3/testing/shared/TestProtocol.java
index 1deb23d..f5ee91b 100644
--- a/src/com/android/launcher3/testing/shared/TestProtocol.java
+++ b/src/com/android/launcher3/testing/shared/TestProtocol.java
@@ -148,7 +148,6 @@
public static final String NULL_INT_SET = "b/200572078";
public static final String MISSING_PROMISE_ICON = "b/202985412";
public static final String TASKBAR_IN_APP_STATE = "b/227657604";
- public static final String INCORRECT_INFO_UPDATED = "b/239465630";
public static final String NPE_TRANSIENT_TASKBAR = "b/257549303";
public static final String REQUEST_EMULATE_DISPLAY = "emulate-display";
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index 220d1c1..38cdb4b 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -169,6 +169,7 @@
private View mSearchBarContainer;
private WidgetsSearchBar mSearchBar;
private TextView mHeaderTitle;
+ private @Nullable WidgetsRecyclerView mCurrentTouchEventRecyclerView;
public WidgetsFullSheet(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
@@ -642,6 +643,51 @@
return sheet;
}
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ return isTouchOnScrollbar(ev) || super.onInterceptTouchEvent(ev);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ return maybeHandleTouchEvent(ev) || super.onTouchEvent(ev);
+ }
+
+ private boolean maybeHandleTouchEvent(MotionEvent ev) {
+ boolean isEventHandled = false;
+
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ mCurrentTouchEventRecyclerView = isTouchOnScrollbar(ev) ? getRecyclerView() : null;
+ }
+
+ if (mCurrentTouchEventRecyclerView != null) {
+ final float offsetX = mContent.getX();
+ final float offsetY = mContent.getY();
+ ev.offsetLocation(-offsetX, -offsetY);
+ isEventHandled = mCurrentTouchEventRecyclerView.dispatchTouchEvent(ev);
+ ev.offsetLocation(offsetX, offsetY);
+ }
+
+ if (ev.getAction() == MotionEvent.ACTION_UP
+ || ev.getAction() == MotionEvent.ACTION_CANCEL) {
+ mCurrentTouchEventRecyclerView = null;
+ }
+
+ return isEventHandled;
+ }
+
+ private boolean isTouchOnScrollbar(MotionEvent ev) {
+ final float offsetX = mContent.getX();
+ final float offsetY = mContent.getY();
+ WidgetsRecyclerView rv = getRecyclerView();
+
+ ev.offsetLocation(-offsetX, -offsetY);
+ boolean isOnScrollBar = rv != null && rv.getScrollbar() != null && rv.isHitOnScrollBar(ev);
+ ev.offsetLocation(offsetX, offsetY);
+
+ return isOnScrollBar;
+ }
+
/** Gets the {@link WidgetsRecyclerView} which shows all widgets in {@link WidgetsFullSheet}. */
@VisibleForTesting
public static WidgetsRecyclerView getWidgetsView(Launcher launcher) {
diff --git a/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java b/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java
index 5969e3e..698e764 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java
@@ -127,8 +127,7 @@
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
if (e.getAction() == MotionEvent.ACTION_DOWN) {
- mTouchDownOnScroller =
- mScrollbar.isHitInParent(e.getX(), e.getY(), mFastScrollerOffset);
+ mTouchDownOnScroller = isHitOnScrollBar(e);
}
if (mTouchDownOnScroller) {
final boolean result = mScrollbar.handleTouchEvent(e, mFastScrollerOffset);
@@ -144,6 +143,15 @@
}
}
+ /**
+ * Detects whether a {@code MotionEvent} is on the scroll bar
+ * @param e The {@code MotionEvent} on the screen
+ * @return {@code true} if the motion is on the scroll bar
+ */
+ boolean isHitOnScrollBar(MotionEvent e) {
+ return mScrollbar.isHitInParent(e.getX(), e.getY(), mFastScrollerOffset);
+ }
+
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index bedf277..b170061 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -280,7 +280,7 @@
</intent-filter>
</activity-alias>
<activity-alias android:name="Activity15" android:exported="true"
- android:label="ThemeIconTestActivity"
+ android:label="IconThemedActivity"
android:icon="@drawable/test_theme_icon"
android:targetActivity="com.android.launcher3.testcomponent.OtherBaseTestingActivity">
<intent-filter>
diff --git a/tests/res/xml/shortcuts.xml b/tests/res/xml/shortcuts.xml
index fde0dbb..94e8edd 100644
--- a/tests/res/xml/shortcuts.xml
+++ b/tests/res/xml/shortcuts.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
<shortcut
- android:shortcutId="shortcut1"
+ android:shortcutId="shortcut1_themed"
android:icon="@drawable/test_theme_icon"
android:shortcutShortLabel="@string/shortcut1">
<intent android:action="com.android.launcher3.intent.action.test_shortcut"/>
diff --git a/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java b/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java
index a32ce3c..469d79f 100644
--- a/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java
+++ b/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java
@@ -26,6 +26,7 @@
import java.util.Map;
import java.util.Queue;
import java.util.Set;
+import java.util.stream.Collectors;
public class CellLayoutBoard {
@@ -140,6 +141,73 @@
return mWidgetsMap.get(c);
}
+ private void removeWidgetFromBoard(WidgetRect widget) {
+ for (int xi = widget.mBounds.left; xi < widget.mBounds.right; xi++) {
+ for (int yi = widget.mBounds.top; yi < widget.mBounds.bottom; yi++) {
+ mWidget[xi][yi] = '-';
+ }
+ }
+ }
+
+ private void removeOverlappingItems(Rect rect) {
+ // Remove overlapping widgets and remove them from the board
+ mWidgetsRects = mWidgetsRects.stream().filter(widget -> {
+ if (rect.intersect(widget.mBounds)) {
+ removeWidgetFromBoard(widget);
+ return false;
+ }
+ return true;
+ }).collect(Collectors.toList());
+ // Remove overlapping icons and remove them from the board
+ mIconPoints = mIconPoints.stream().filter(iconPoint -> {
+ int x = iconPoint.coord.x;
+ int y = iconPoint.coord.y;
+ if (rect.contains(x, y)) {
+ mWidget[x][y] = '-';
+ return false;
+ }
+ return true;
+ }).collect(Collectors.toList());
+ }
+
+ private void removeOverlappingItems(Point p) {
+ // Remove overlapping widgets and remove them from the board
+ mWidgetsRects = mWidgetsRects.stream().filter(widget -> {
+ if (widget.mBounds.contains(p.x, p.y)) {
+ removeWidgetFromBoard(widget);
+ return false;
+ }
+ return true;
+ }).collect(Collectors.toList());
+ // Remove overlapping icons and remove them from the board
+ mIconPoints = mIconPoints.stream().filter(iconPoint -> {
+ int x = iconPoint.coord.x;
+ int y = iconPoint.coord.y;
+ if (p.x == x && p.y == y) {
+ mWidget[x][y] = '-';
+ return false;
+ }
+ return true;
+ }).collect(Collectors.toList());
+ }
+
+ public void addWidget(int x, int y, int spanX, int spanY, char type) {
+ Rect rect = new Rect(x, y + spanY - 1, x + spanX - 1, y);
+ removeOverlappingItems(rect);
+ WidgetRect widgetRect = new WidgetRect(type, rect);
+ mWidgetsRects.add(widgetRect);
+ for (int xi = rect.left; xi < rect.right + 1; xi++) {
+ for (int yi = rect.bottom; yi < rect.top + 1; yi++) {
+ mWidget[xi][yi] = type;
+ }
+ }
+ }
+
+ public void addIcon(int x, int y) {
+ removeOverlappingItems(new Point(x, y));
+ mWidget[x][y] = 'i';
+ }
+
public static WidgetRect getWidgetRect(int x, int y, Set<Point> used, char[][] board) {
char type = board[x][y];
Queue<Point> search = new ArrayDeque<Point>();
@@ -227,4 +295,17 @@
board.mIconPoints = getIconPoints(board.mWidget);
return board;
}
+
+ public String toString(int maxX, int maxY) {
+ StringBuilder s = new StringBuilder();
+ maxX = Math.min(maxX, mWidget.length);
+ maxY = Math.min(maxY, mWidget[0].length);
+ for (int y = 0; y < maxY; y++) {
+ for (int x = 0; x < maxX; x++) {
+ s.append(mWidget[x][y]);
+ }
+ s.append('\n');
+ }
+ return s.toString();
+ }
}
diff --git a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
index 9da7e0f..843f011 100644
--- a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
+++ b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
@@ -26,6 +26,7 @@
import androidx.test.filters.SmallTest;
import com.android.launcher3.CellLayout;
+import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.celllayout.testcases.FullReorderCase;
import com.android.launcher3.celllayout.testcases.MoveOutReorderCase;
import com.android.launcher3.celllayout.testcases.PushReorderCase;
@@ -46,6 +47,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.ExecutionException;
@@ -108,6 +110,42 @@
return match;
}
+ private void printCurrentWorkspace() {
+ InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(mTargetContext);
+ ArrayList<CellLayoutBoard> boards = workspaceToBoards();
+ for (int i = 0; i < boards.size(); i++) {
+ Log.d(TAG, "Screen number " + i);
+ Log.d(TAG, ".\n" + boards.get(i).toString(idp.numColumns, idp.numRows));
+ }
+ }
+
+ private ArrayList<CellLayoutBoard> workspaceToBoards() {
+ return getFromLauncher(l -> {
+ ArrayList<CellLayoutBoard> boards = new ArrayList<>();
+ int widgetCount = 0;
+ for (CellLayout cellLayout : l.getWorkspace().mWorkspaceScreens) {
+ CellLayoutBoard board = new CellLayoutBoard();
+ int count = cellLayout.getShortcutsAndWidgets().getChildCount();
+ for (int i = 0; i < count; i++) {
+ View callView = cellLayout.getShortcutsAndWidgets().getChildAt(i);
+ CellLayoutLayoutParams params =
+ (CellLayoutLayoutParams) callView.getLayoutParams();
+ // is icon
+ if (callView instanceof DoubleShadowBubbleTextView) {
+ board.addIcon(params.cellX, params.cellY);
+ } else {
+ // is widget
+ board.addWidget(params.cellX, params.cellY, params.cellHSpan,
+ params.cellVSpan, (char) ('A' + widgetCount));
+ widgetCount++;
+ }
+ }
+ boards.add(board);
+ }
+ return boards;
+ });
+ }
+
private void runTestCase(ReorderTestCase testCase)
throws ExecutionException, InterruptedException {
Point mainWidgetCellPos = testCase.mStart.getMain();
@@ -127,6 +165,7 @@
for (CellLayoutBoard board : testCase.mEnd) {
isValid |= validateBoard(board);
}
+ printCurrentWorkspace();
assertTrue("Non of the valid boards match with the current state", isValid);
}
diff --git a/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java b/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
index 7d36740..f55b244 100644
--- a/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
+++ b/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
@@ -1,7 +1,5 @@
package com.android.launcher3.model;
-import static com.android.launcher3.testing.shared.TestProtocol.INCORRECT_INFO_UPDATED;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
@@ -16,7 +14,6 @@
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
-import android.util.Log;
import androidx.annotation.NonNull;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -29,7 +26,6 @@
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.util.LauncherModelHelper;
import org.junit.After;
@@ -47,15 +43,12 @@
@RunWith(AndroidJUnit4.class)
public class CacheDataUpdatedTaskTest {
- private static final String TAG = "CacheDataUpdatedTaskTest";
-
private static final String NEW_LABEL_PREFIX = "new-label-";
private LauncherModelHelper mModelHelper;
@Before
public void setup() throws Exception {
- TestProtocol.sDebugTracing = true;
mModelHelper = new LauncherModelHelper();
mModelHelper.initializeData("cache_data_updated_task_data");
@@ -98,7 +91,6 @@
@After
public void tearDown() {
mModelHelper.destroy();
- TestProtocol.sDebugTracing = false;
}
private CacheDataUpdatedTask newTask(int op, String... pkg) {
@@ -122,7 +114,6 @@
// Verify that only app1 var updated in allAppsList
assertFalse(mModelHelper.getAllAppsList().data.isEmpty());
for (AppInfo info : mModelHelper.getAllAppsList().data) {
- Log.i(INCORRECT_INFO_UPDATED, "testCacheUpdate_update_apps: checking info=" + info);
if (info.componentName.getPackageName().equals("app1")) {
assertFalse(info.bitmap.isNullOrLowRes());
} else {
diff --git a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
index 3f4a1c1..2c9785c 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
@@ -37,7 +37,6 @@
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -65,7 +64,6 @@
mAppWidgetManager = AppWidgetManager.getInstance(mTargetContext);
}
- @Ignore
@Test
@PortraitLandscape
public void testWidgetConfig() throws Throwable {
diff --git a/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java b/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
index 9d5763b..7ba0b53 100644
--- a/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
+++ b/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
@@ -36,9 +36,7 @@
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.launcher3.util.Executors;
-import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
-import org.junit.Ignore;
import org.junit.Test;
import java.util.ArrayDeque;
@@ -52,7 +50,7 @@
@LargeTest
public class ThemeIconsTest extends AbstractLauncherUiTest {
- private static final String APP_NAME = "ThemeIconTestActivity";
+ private static final String APP_NAME = "IconThemedActivity";
private static final String SHORTCUT_APP_NAME = "LauncherTestApp";
private static final String SHORTCUT_NAME = "Shortcut 1";
@@ -111,9 +109,7 @@
}
}
- @Ignore
@Test
- @ScreenRecord // b/260722220
public void testShortcutIconWithTheme() throws Exception {
setThemeEnabled(true);
TaplTestsLauncher3.initialize(this);