Merge "Using model-time scrolling in all apps" into ub-launcher3-qt-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
4fbfb4123a
+2
-2
@@ -19,7 +19,6 @@ package com.android.launcher3.appprediction;
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.quickstep.logging.UserEventDispatcherExtension.ALL_APPS_PREDICTION_TIPS;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.graphics.CornerPathEffect;
|
||||
import android.graphics.Paint;
|
||||
@@ -39,6 +38,7 @@ import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.allapps.FloatingHeaderView;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.compat.UserManagerCompat;
|
||||
@@ -152,7 +152,7 @@ public class AllAppsTipView extends AbstractFloatingView {
|
||||
|| !launcher.isInState(ALL_APPS)
|
||||
|| hasSeenAllAppsTip(launcher)
|
||||
|| UserManagerCompat.getInstance(launcher).isDemoUser()
|
||||
|| ActivityManager.isRunningInTestHarness()) {
|
||||
|| Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ public final class TestProtocol {
|
||||
public static final String SCROLL_Y_FIELD = "scrollY";
|
||||
public static final String STATE_FIELD = "state";
|
||||
public static final String SWITCHED_TO_STATE_MESSAGE = "TAPL_SWITCHED_TO_STATE";
|
||||
public static final String SCROLL_FINISHED_MESSAGE = "TAPL_SCROLL_FINISHED";
|
||||
public static final String RESPONSE_MESSAGE_POSTFIX = "_RESPONSE";
|
||||
public static final int NORMAL_STATE_ORDINAL = 0;
|
||||
public static final int SPRING_LOADED_STATE_ORDINAL = 1;
|
||||
|
||||
@@ -32,7 +32,8 @@ import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.graphics.DrawableFactory;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
||||
import com.android.launcher3.logging.StatsLogUtils.LogContainerProvider;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
@@ -419,4 +420,13 @@ public class AllAppsRecyclerView extends BaseRecyclerView implements LogContaine
|
||||
public boolean hasOverlappingRendering() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrollStateChanged(int state) {
|
||||
super.onScrollStateChanged(state);
|
||||
|
||||
if (state == SCROLL_STATE_IDLE && Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
AccessibilityManagerCompat.sendScrollFinishedEventToTest(getContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerTyp
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorInflater;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Handler;
|
||||
import android.view.MotionEvent;
|
||||
@@ -32,6 +31,7 @@ import android.view.MotionEvent;
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.compat.UserManagerCompat;
|
||||
import com.android.launcher3.states.InternalStateHandler;
|
||||
|
||||
@@ -134,7 +134,7 @@ public class DiscoveryBounce extends AbstractFloatingView {
|
||||
&& !shouldShowForWorkProfile(launcher))
|
||||
|| AbstractFloatingView.getTopOpenView(launcher) != null
|
||||
|| UserManagerCompat.getInstance(launcher).isDemoUser()
|
||||
|| ActivityManager.isRunningInTestHarness()) {
|
||||
|| Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ public class DiscoveryBounce extends AbstractFloatingView {
|
||||
|| (launcher.getSharedPrefs().getBoolean(SHELF_BOUNCE_SEEN, false)
|
||||
&& !shouldShowForWorkProfile(launcher))
|
||||
|| UserManagerCompat.getInstance(launcher).isDemoUser()
|
||||
|| ActivityManager.isRunningInTestHarness()) {
|
||||
|| Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,13 @@ public class AccessibilityManagerCompat {
|
||||
sendEventToTest(accessibilityManager, TestProtocol.SWITCHED_TO_STATE_MESSAGE, parcel);
|
||||
}
|
||||
|
||||
public static void sendScrollFinishedEventToTest(Context context) {
|
||||
final AccessibilityManager accessibilityManager = getAccessibilityManagerForTest(context);
|
||||
if (accessibilityManager == null) return;
|
||||
|
||||
sendEventToTest(accessibilityManager, TestProtocol.SCROLL_FINISHED_MESSAGE, null);
|
||||
}
|
||||
|
||||
private static void sendEventToTest(
|
||||
AccessibilityManager accessibilityManager, String eventTag, Bundle data) {
|
||||
final AccessibilityEvent e = AccessibilityEvent.obtain(
|
||||
|
||||
@@ -18,6 +18,8 @@ package com.android.launcher3.tapl;
|
||||
|
||||
import static com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel.ZERO_BUTTON;
|
||||
|
||||
import android.graphics.Rect;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.test.uiautomator.BySelector;
|
||||
import androidx.test.uiautomator.Direction;
|
||||
@@ -32,7 +34,6 @@ import com.android.launcher3.TestProtocol;
|
||||
public class AllApps extends LauncherInstrumentation.VisibleContainer {
|
||||
private static final int MAX_SCROLL_ATTEMPTS = 40;
|
||||
private static final int MIN_INTERACT_SIZE = 100;
|
||||
private static final int FLING_SPEED = LauncherInstrumentation.needSlowGestures() ? 1000 : 3000;
|
||||
|
||||
private final int mHeight;
|
||||
|
||||
@@ -102,7 +103,7 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer {
|
||||
"search_container_all_apps");
|
||||
|
||||
int attempts = 0;
|
||||
allAppsContainer.setGestureMargins(0, searchBox.getVisibleBounds().bottom + 1, 0, 5);
|
||||
final Rect margins = new Rect(0, searchBox.getVisibleBounds().bottom + 1, 0, 5);
|
||||
|
||||
for (int scroll = getScroll(allAppsContainer);
|
||||
scroll != 0;
|
||||
@@ -113,7 +114,7 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer {
|
||||
"Exceeded max scroll attempts: " + MAX_SCROLL_ATTEMPTS,
|
||||
++attempts <= MAX_SCROLL_ATTEMPTS);
|
||||
|
||||
allAppsContainer.scroll(Direction.UP, 1);
|
||||
mLauncher.scrollWithModelTime(allAppsContainer, Direction.UP, 1, margins, 50);
|
||||
}
|
||||
|
||||
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("scrolled up")) {
|
||||
@@ -133,7 +134,7 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer {
|
||||
// Try to figure out how much percentage of the container needs to be scrolled in order
|
||||
// to reveal the app icon to have the MIN_INTERACT_SIZE
|
||||
final float pct = Math.max(((float) (MIN_INTERACT_SIZE - appHeight)) / mHeight, 0.2f);
|
||||
allAppsContainer.scroll(Direction.DOWN, pct);
|
||||
mLauncher.scrollWithModelTime(allAppsContainer, Direction.DOWN, pct, null, 10);
|
||||
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
|
||||
"scrolled an icon in all apps to make it visible - and then")) {
|
||||
mLauncher.waitForIdle();
|
||||
@@ -150,9 +151,8 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer {
|
||||
mLauncher.addContextLayer("want to fling forward in all apps")) {
|
||||
final UiObject2 allAppsContainer = verifyActiveContainer();
|
||||
// Start the gesture in the center to avoid starting at elements near the top.
|
||||
allAppsContainer.setGestureMargins(0, 0, 0, mHeight / 2);
|
||||
allAppsContainer.fling(Direction.DOWN,
|
||||
(int) (FLING_SPEED * mLauncher.getDisplayDensity()));
|
||||
mLauncher.scrollWithModelTime(
|
||||
allAppsContainer, Direction.DOWN, 1, new Rect(0, 0, 0, mHeight / 2), 10);
|
||||
verifyActiveContainer();
|
||||
}
|
||||
}
|
||||
@@ -165,9 +165,8 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer {
|
||||
mLauncher.addContextLayer("want to fling backward in all apps")) {
|
||||
final UiObject2 allAppsContainer = verifyActiveContainer();
|
||||
// Start the gesture in the center, for symmetry with forward.
|
||||
allAppsContainer.setGestureMargins(0, mHeight / 2, 0, 0);
|
||||
allAppsContainer.fling(Direction.UP,
|
||||
(int) (FLING_SPEED * mLauncher.getDisplayDensity()));
|
||||
mLauncher.scrollWithModelTime(
|
||||
allAppsContainer, Direction.UP, 1, new Rect(0, mHeight / 2, 0, 0), 10);
|
||||
verifyActiveContainer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
@@ -47,6 +48,7 @@ import androidx.annotation.Nullable;
|
||||
import androidx.test.uiautomator.By;
|
||||
import androidx.test.uiautomator.BySelector;
|
||||
import androidx.test.uiautomator.Configurator;
|
||||
import androidx.test.uiautomator.Direction;
|
||||
import androidx.test.uiautomator.UiDevice;
|
||||
import androidx.test.uiautomator.UiObject2;
|
||||
import androidx.test.uiautomator.Until;
|
||||
@@ -363,7 +365,7 @@ public final class LauncherInstrumentation {
|
||||
? NORMAL_STATE_ORDINAL : BACKGROUND_APP_STATE_ORDINAL;
|
||||
final Point displaySize = getRealDisplaySize();
|
||||
|
||||
swipeViaMovePointer(
|
||||
swipeWithModelTime(
|
||||
displaySize.x / 2, displaySize.y - 1,
|
||||
displaySize.x / 2, 0,
|
||||
finalState, ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME);
|
||||
@@ -563,18 +565,65 @@ public final class LauncherInstrumentation {
|
||||
() -> mDevice.swipe(startX, startY, endX, endY, steps));
|
||||
}
|
||||
|
||||
void swipeViaMovePointer(
|
||||
void swipeWithModelTime(
|
||||
int startX, int startY, int endX, int endY, int expectedState, int steps) {
|
||||
changeStateViaGesture(startX, startY, endX, endY, expectedState, () -> {
|
||||
final long downTime = SystemClock.uptimeMillis();
|
||||
final Point start = new Point(startX, startY);
|
||||
final Point end = new Point(endX, endY);
|
||||
sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, start);
|
||||
final long endTime = movePointer(downTime, downTime, steps * GESTURE_STEP_MS, start,
|
||||
end);
|
||||
sendPointer(
|
||||
downTime, endTime, MotionEvent.ACTION_UP, end);
|
||||
});
|
||||
changeStateViaGesture(startX, startY, endX, endY, expectedState,
|
||||
() -> swipeWithModelTime(startX, startY, endX, endY, steps));
|
||||
}
|
||||
|
||||
void scrollWithModelTime(
|
||||
UiObject2 container, Direction direction, float percent, Rect margins, int steps) {
|
||||
final Rect rect = container.getVisibleBounds();
|
||||
if (margins != null) {
|
||||
rect.left += margins.left;
|
||||
rect.top += margins.top;
|
||||
rect.right -= margins.right;
|
||||
rect.bottom -= margins.bottom;
|
||||
}
|
||||
|
||||
final int startX;
|
||||
final int startY;
|
||||
final int endX;
|
||||
final int endY;
|
||||
|
||||
switch (direction) {
|
||||
case UP: {
|
||||
startX = endX = rect.centerX();
|
||||
final int vertCenter = rect.centerY();
|
||||
final float halfGestureHeight = rect.height() * percent / 2.0f;
|
||||
startY = (int) (vertCenter - halfGestureHeight);
|
||||
endY = (int) (vertCenter + halfGestureHeight);
|
||||
}
|
||||
break;
|
||||
case DOWN: {
|
||||
startX = endX = rect.centerX();
|
||||
final int vertCenter = rect.centerY();
|
||||
final float halfGestureHeight = rect.height() * percent / 2.0f;
|
||||
startY = (int) (vertCenter + halfGestureHeight);
|
||||
endY = (int) (vertCenter - halfGestureHeight);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fail("Unsupported direction");
|
||||
return;
|
||||
}
|
||||
|
||||
executeAndWaitForEvent(
|
||||
() -> swipeWithModelTime(startX, startY, endX, endY, steps),
|
||||
event -> TestProtocol.SCROLL_FINISHED_MESSAGE.equals(event.getClassName()),
|
||||
"Didn't receive a scroll end message: " + startX + ", " + startY
|
||||
+ ", " + endX + ", " + endY);
|
||||
}
|
||||
|
||||
// Inject a swipe gesture. Inject exactly 'steps' motion points, incrementing event time by a
|
||||
// fixed interval each time.
|
||||
private void swipeWithModelTime(int startX, int startY, int endX, int endY, int steps) {
|
||||
final long downTime = SystemClock.uptimeMillis();
|
||||
final Point start = new Point(startX, startY);
|
||||
final Point end = new Point(endX, endY);
|
||||
sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, start);
|
||||
final long endTime = movePointer(downTime, downTime, steps * GESTURE_STEP_MS, start, end);
|
||||
sendPointer(downTime, endTime, MotionEvent.ACTION_UP, end);
|
||||
}
|
||||
|
||||
private void changeStateViaGesture(int startX, int startY, int endX, int endY,
|
||||
@@ -688,10 +737,7 @@ public final class LauncherInstrumentation {
|
||||
}
|
||||
|
||||
static void sleep(int duration) {
|
||||
try {
|
||||
Thread.sleep(duration);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
SystemClock.sleep(duration);
|
||||
}
|
||||
|
||||
int getEdgeSensitivityWidth() {
|
||||
|
||||
Reference in New Issue
Block a user