Merging ub-launcher3-qt-r1-dev, build 5749827
am: 3fc9a1cf69
Change-Id: Ia73d517059270c0a5b089413c2b0aae7b1cbcb43
This commit is contained in:
@@ -186,7 +186,7 @@ public class TouchInteractionService extends Service {
|
||||
return mMyBinder;
|
||||
}
|
||||
|
||||
public static boolean isInputMonitorInitialized() {
|
||||
public static boolean isInitialized() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* This class will be moved to androidx library. There shouldn't be any dependency outside
|
||||
@@ -154,7 +155,7 @@ public class BaseIconFactory implements AutoCloseable {
|
||||
* @param scale returns the scale result from normalization
|
||||
* @return a bitmap suitable for disaplaying as an icon at various system UIs.
|
||||
*/
|
||||
public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user,
|
||||
public BitmapInfo createBadgedIconBitmap(@NonNull Drawable icon, UserHandle user,
|
||||
boolean shrinkNonAdaptiveIcons, boolean isInstantApp, float[] scale) {
|
||||
if (scale == null) {
|
||||
scale = new float[1];
|
||||
@@ -204,8 +205,11 @@ public class BaseIconFactory implements AutoCloseable {
|
||||
mDisableColorExtractor = true;
|
||||
}
|
||||
|
||||
private Drawable normalizeAndWrapToAdaptiveIcon(Drawable icon, boolean shrinkNonAdaptiveIcons,
|
||||
RectF outIconBounds, float[] outScale) {
|
||||
private Drawable normalizeAndWrapToAdaptiveIcon(@NonNull Drawable icon,
|
||||
boolean shrinkNonAdaptiveIcons, RectF outIconBounds, float[] outScale) {
|
||||
if (icon == null) {
|
||||
return null;
|
||||
}
|
||||
float scale = 1f;
|
||||
|
||||
if (shrinkNonAdaptiveIcons && ATLEAST_OREO) {
|
||||
@@ -261,7 +265,7 @@ public class BaseIconFactory implements AutoCloseable {
|
||||
* @param icon drawable that should be flattened to a bitmap
|
||||
* @param scale the scale to apply before drawing {@param icon} on the canvas
|
||||
*/
|
||||
public Bitmap createIconBitmap(Drawable icon, float scale, int size) {
|
||||
public Bitmap createIconBitmap(@NonNull Drawable icon, float scale, int size) {
|
||||
Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
|
||||
if (icon == null) {
|
||||
return bitmap;
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ public class QuickstepTestInformationHandler extends TestInformationHandler {
|
||||
|
||||
case TestProtocol.REQUEST_IS_LAUNCHER_INITIALIZED: {
|
||||
response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD,
|
||||
TouchInteractionService.isInputMonitorInitialized());
|
||||
TouchInteractionService.isInitialized());
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
+2
-7
@@ -19,12 +19,12 @@ import static android.view.MotionEvent.ACTION_CANCEL;
|
||||
import static android.view.MotionEvent.ACTION_DOWN;
|
||||
import static android.view.MotionEvent.ACTION_UP;
|
||||
|
||||
import static com.android.launcher3.Utilities.FLAG_NO_GESTURES;
|
||||
|
||||
import android.view.InputEvent;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import com.android.launcher3.util.Preconditions;
|
||||
import com.android.quickstep.inputconsumers.InputConsumer;
|
||||
import com.android.quickstep.util.SwipeAnimationTargetSet;
|
||||
@@ -33,8 +33,6 @@ import com.android.systemui.shared.system.InputConsumerController;
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
/**
|
||||
* Wrapper around RecentsAnimationController to help with some synchronization
|
||||
*/
|
||||
@@ -184,10 +182,7 @@ public class RecentsAnimationWrapper {
|
||||
}
|
||||
}
|
||||
if (mInputConsumer != null) {
|
||||
int flags = ev.getEdgeFlags();
|
||||
ev.setEdgeFlags(flags | FLAG_NO_GESTURES);
|
||||
mInputConsumer.onMotionEvent(ev);
|
||||
ev.setEdgeFlags(flags);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
+44
-8
@@ -33,11 +33,13 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_N
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
|
||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_ASSISTANT;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.app.Service;
|
||||
import android.app.TaskInfo;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
@@ -103,6 +105,7 @@ import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
|
||||
import com.android.systemui.shared.system.RecentsAnimationListener;
|
||||
import com.android.systemui.shared.system.SystemGestureExclusionListenerCompat;
|
||||
|
||||
import com.android.systemui.shared.system.TaskInfoCompat;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Arrays;
|
||||
@@ -154,6 +157,7 @@ public class TouchInteractionService extends Service implements
|
||||
MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::initInputMonitor);
|
||||
MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::onSystemUiProxySet);
|
||||
MAIN_THREAD_EXECUTOR.execute(() -> preloadOverview(true /* fromInit */));
|
||||
sIsInitialized = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -227,15 +231,15 @@ public class TouchInteractionService extends Service implements
|
||||
};
|
||||
|
||||
private static boolean sConnected = false;
|
||||
private static boolean sInputMonitorInitialized = false;
|
||||
private static boolean sIsInitialized = false;
|
||||
private static final SwipeSharedState sSwipeSharedState = new SwipeSharedState();
|
||||
|
||||
public static boolean isConnected() {
|
||||
return sConnected;
|
||||
}
|
||||
|
||||
public static boolean isInputMonitorInitialized() {
|
||||
return sInputMonitorInitialized;
|
||||
public static boolean isInitialized() {
|
||||
return sIsInitialized;
|
||||
}
|
||||
|
||||
public static SwipeSharedState getSwipeSharedState() {
|
||||
@@ -336,25 +340,32 @@ public class TouchInteractionService extends Service implements
|
||||
mInputMonitorCompat.dispose();
|
||||
mInputMonitorCompat = null;
|
||||
}
|
||||
sInputMonitorInitialized = false;
|
||||
}
|
||||
|
||||
private void initInputMonitor() {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "initInputMonitor 1");
|
||||
}
|
||||
if (!mMode.hasGestures || mISystemUiProxy == null) {
|
||||
return;
|
||||
}
|
||||
disposeEventHandlers();
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "initInputMonitor 2");
|
||||
}
|
||||
|
||||
try {
|
||||
mInputMonitorCompat = InputMonitorCompat.fromBundle(mISystemUiProxy
|
||||
.monitorGestureInput("swipe-up", mDefaultDisplayId), KEY_EXTRA_INPUT_MONITOR);
|
||||
mInputEventReceiver = mInputMonitorCompat.getInputReceiver(Looper.getMainLooper(),
|
||||
mMainChoreographer, this::onInputEvent);
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "initInputMonitor 3");
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Unable to create input monitor", e);
|
||||
}
|
||||
initTouchBounds();
|
||||
sInputMonitorInitialized = true;
|
||||
}
|
||||
|
||||
private int getNavbarSize(String resName) {
|
||||
@@ -408,6 +419,9 @@ public class TouchInteractionService extends Service implements
|
||||
|
||||
@Override
|
||||
public void onNavigationModeChanged(Mode newMode) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "onNavigationModeChanged " + newMode);
|
||||
}
|
||||
if (mMode.hasGestures != newMode.hasGestures) {
|
||||
if (newMode.hasGestures) {
|
||||
getSystemService(DisplayManager.class).registerDisplayListener(
|
||||
@@ -492,6 +506,7 @@ public class TouchInteractionService extends Service implements
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
sIsInitialized = false;
|
||||
if (mIsUserUnlocked) {
|
||||
mInputConsumer.unregisterInputConsumer();
|
||||
mOverviewComponentObserver.onDestroy();
|
||||
@@ -516,6 +531,9 @@ public class TouchInteractionService extends Service implements
|
||||
}
|
||||
|
||||
private void onInputEvent(InputEvent ev) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "onInputEvent " + ev);
|
||||
}
|
||||
if (!(ev instanceof MotionEvent)) {
|
||||
Log.e(TAG, "Unknown event " + ev);
|
||||
return;
|
||||
@@ -567,7 +585,7 @@ public class TouchInteractionService extends Service implements
|
||||
if (isInValidSystemUiState) {
|
||||
// This handles apps launched in direct boot mode (e.g. dialer) as well as apps
|
||||
// launched while device is locked even after exiting direct boot mode (e.g. camera).
|
||||
return createDeviceLockedInputConsumer(mAM.getRunningTask(0));
|
||||
return createDeviceLockedInputConsumer(mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT));
|
||||
} else {
|
||||
return mResetGestureInputConsumer;
|
||||
}
|
||||
@@ -605,7 +623,7 @@ public class TouchInteractionService extends Service implements
|
||||
}
|
||||
|
||||
private InputConsumer newBaseConsumer(boolean useSharedState, MotionEvent event) {
|
||||
final RunningTaskInfo runningTaskInfo = mAM.getRunningTask(0);
|
||||
RunningTaskInfo runningTaskInfo = mAM.getRunningTask(0);
|
||||
if (!useSharedState) {
|
||||
sSwipeSharedState.clearAllState(false /* finishAnimation */);
|
||||
}
|
||||
@@ -617,6 +635,17 @@ public class TouchInteractionService extends Service implements
|
||||
final ActivityControlHelper activityControl =
|
||||
mOverviewComponentObserver.getActivityControlHelper();
|
||||
|
||||
boolean forceOverviewInputConsumer = false;
|
||||
if (isExcludedAssistant(runningTaskInfo)) {
|
||||
// In the case where we are in the excluded assistant state, ignore it and treat the
|
||||
// running activity as the task behind the assistant
|
||||
runningTaskInfo = mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT);
|
||||
final ComponentName homeComponent =
|
||||
mOverviewComponentObserver.getHomeIntent().getComponent();
|
||||
forceOverviewInputConsumer =
|
||||
runningTaskInfo.baseIntent.getComponent().equals(homeComponent);
|
||||
}
|
||||
|
||||
if (runningTaskInfo == null && !sSwipeSharedState.goingToLauncher
|
||||
&& !sSwipeSharedState.recentsAnimationFinishInterrupted) {
|
||||
return mResetGestureInputConsumer;
|
||||
@@ -626,7 +655,8 @@ public class TouchInteractionService extends Service implements
|
||||
RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
|
||||
info.id = sSwipeSharedState.nextRunningTaskId;
|
||||
return createOtherActivityInputConsumer(event, info);
|
||||
} else if (sSwipeSharedState.goingToLauncher || activityControl.isResumed()) {
|
||||
} else if (sSwipeSharedState.goingToLauncher || activityControl.isResumed()
|
||||
|| forceOverviewInputConsumer) {
|
||||
return createOverviewInputConsumer(event);
|
||||
} else if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityControl.isInLiveTileMode()) {
|
||||
return createOverviewInputConsumer(event);
|
||||
@@ -638,6 +668,12 @@ public class TouchInteractionService extends Service implements
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isExcludedAssistant(TaskInfo info) {
|
||||
return info != null
|
||||
&& TaskInfoCompat.getActivityType(info) == ACTIVITY_TYPE_ASSISTANT
|
||||
&& (info.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
|
||||
}
|
||||
|
||||
private boolean disableHorizontalSwipe(MotionEvent event) {
|
||||
// mExclusionRegion can change on binder thread, use a local instance here.
|
||||
Region exclusionRegion = mExclusionRegion;
|
||||
|
||||
+4
-4
@@ -56,6 +56,9 @@ import android.view.ViewTreeObserver.OnDrawListener;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
@@ -88,9 +91,6 @@ import com.android.systemui.shared.system.LatencyTrackerCompat;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
import com.android.systemui.shared.system.WindowCallbacksCompat;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
extends BaseSwipeUpHandler<T, RecentsView>
|
||||
@@ -677,7 +677,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
|
||||
@Override
|
||||
protected InputConsumer createNewInputProxyHandler() {
|
||||
endRunningWindowAnim(true /* cancel */);
|
||||
endRunningWindowAnim(mGestureEndTarget == HOME /* cancel */);
|
||||
endLauncherTransitionController();
|
||||
if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
// Hide the task view, if not already hidden
|
||||
|
||||
@@ -473,11 +473,6 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldBlockGestures(MotionEvent ev) {
|
||||
return Utilities.shouldDisableGestures(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
super.onTouchEvent(ev);
|
||||
@@ -1697,6 +1692,9 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
* @return How many pixels the running task is offset on the x-axis due to the current scrollX.
|
||||
*/
|
||||
public float getScrollOffset() {
|
||||
if (getRunningTaskIndex() == -1) {
|
||||
return 0;
|
||||
}
|
||||
int startScroll = getScrollForPage(getRunningTaskIndex());
|
||||
int offsetX = startScroll - getScrollX();
|
||||
offsetX *= getScaleX();
|
||||
|
||||
@@ -410,4 +410,11 @@ public class TaskThumbnailView extends View {
|
||||
|
||||
return new ColorMatrixColorFilter(COLOR_MATRIX);
|
||||
}
|
||||
|
||||
public Bitmap getThumbnail() {
|
||||
if (mThumbnailData == null) {
|
||||
return null;
|
||||
}
|
||||
return mThumbnailData.thumbnail;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@ public class NavigationModeSwitchRule implements TestRule {
|
||||
return new Statement() {
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
mLauncher.enableDebugTracing();
|
||||
final Context context = getInstrumentation().getContext();
|
||||
final int currentInteractionMode =
|
||||
LauncherInstrumentation.getCurrentInteractionMode(context);
|
||||
@@ -104,6 +105,7 @@ public class NavigationModeSwitchRule implements TestRule {
|
||||
} finally {
|
||||
setActiveOverlay(prevOverlayPkg, originalMode);
|
||||
}
|
||||
mLauncher.disableDebugTracing();
|
||||
}
|
||||
|
||||
public void evaluateWithoutChangingSetting(Statement base) throws Throwable {
|
||||
|
||||
@@ -848,7 +848,7 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
*/
|
||||
|
||||
// Skip touch handling if there are no pages to swipe
|
||||
if (getChildCount() <= 0 || shouldBlockGestures(ev)) return false;
|
||||
if (getChildCount() <= 0) return false;
|
||||
|
||||
acquireVelocityTrackerAndAddMovement(ev);
|
||||
|
||||
@@ -1093,14 +1093,10 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
mAllowOverScroll = enable;
|
||||
}
|
||||
|
||||
protected boolean shouldBlockGestures(MotionEvent ev) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
// Skip touch handling if there are no pages to swipe
|
||||
if (getChildCount() <= 0 || shouldBlockGestures(ev)) return false;
|
||||
if (getChildCount() <= 0) return false;
|
||||
|
||||
acquireVelocityTrackerAndAddMovement(ev);
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.ItemInfoWithIcon.FLAG_ICON_BADGED;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager;
|
||||
@@ -92,8 +94,6 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.android.launcher3.ItemInfoWithIcon.FLAG_ICON_BADGED;
|
||||
|
||||
/**
|
||||
* Various utilities shared amongst the Launcher's classes.
|
||||
*/
|
||||
@@ -127,16 +127,6 @@ public final class Utilities {
|
||||
*/
|
||||
public static final int EDGE_NAV_BAR = 1 << 8;
|
||||
|
||||
/**
|
||||
* Set on a motion event do disallow any gestures and only handle touch.
|
||||
* See {@link MotionEvent#setEdgeFlags(int)}.
|
||||
*/
|
||||
public static final int FLAG_NO_GESTURES = 1 << 9;
|
||||
|
||||
public static boolean shouldDisableGestures(MotionEvent ev) {
|
||||
return (ev.getEdgeFlags() & FLAG_NO_GESTURES) == FLAG_NO_GESTURES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the device has a debug build. Should only be used to store additional info or
|
||||
* add extra logging and not for changing the app behavior.
|
||||
|
||||
@@ -105,7 +105,7 @@ abstract class BaseFlags {
|
||||
"ENABLE_QUICKSTEP_LIVE_TILE", false, "Enable live tile in Quickstep overview");
|
||||
|
||||
public static final TogglableFlag ENABLE_HINTS_IN_OVERVIEW = new TogglableFlag(
|
||||
"ENABLE_HINTS_IN_OVERVIEW", false,
|
||||
"ENABLE_HINTS_IN_OVERVIEW", true,
|
||||
"Show chip hints and gleams on the overview screen");
|
||||
|
||||
public static final TogglableFlag FAKE_LANDSCAPE_UI = new TogglableFlag(
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.os.Handler;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
@@ -87,6 +88,9 @@ public class DragPreviewProvider {
|
||||
Rect bounds = getDrawableBounds(d);
|
||||
destCanvas.translate(blurSizeOutline / 2 - bounds.left,
|
||||
blurSizeOutline / 2 - bounds.top);
|
||||
if (d instanceof FastBitmapDrawable) {
|
||||
((FastBitmapDrawable) d).setScale(1);
|
||||
}
|
||||
d.draw(destCanvas);
|
||||
} else {
|
||||
final Rect clipRect = mTempRect;
|
||||
|
||||
@@ -77,4 +77,6 @@ public final class TestProtocol {
|
||||
public static boolean sDebugTracing = false;
|
||||
public static final String REQUEST_ENABLE_DEBUG_TRACING = "enable-debug-tracing";
|
||||
public static final String REQUEST_DISABLE_DEBUG_TRACING = "disable-debug-tracing";
|
||||
|
||||
public static final String NO_BACKGROUND_TO_OVERVIEW_TAG = "b/138251824";
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import static android.view.MotionEvent.ACTION_DOWN;
|
||||
import static android.view.MotionEvent.ACTION_UP;
|
||||
|
||||
import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
|
||||
import static com.android.launcher3.Utilities.shouldDisableGestures;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
@@ -30,7 +29,6 @@ import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.Property;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
@@ -152,8 +150,6 @@ public abstract class BaseDragLayer<T extends Context & ActivityContext>
|
||||
}
|
||||
|
||||
private TouchController findControllerToHandleTouch(MotionEvent ev) {
|
||||
if (shouldDisableGestures(ev)) return null;
|
||||
|
||||
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
|
||||
if (topView != null && topView.onControllerInterceptTouchEvent(ev)) {
|
||||
return topView;
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.android.launcher3.ui;
|
||||
|
||||
import static androidx.test.InstrumentationRegistry.getInstrumentation;
|
||||
|
||||
import static com.android.launcher3.tapl.LauncherInstrumentation.ContainerType;
|
||||
import static com.android.launcher3.ui.TaplTestsLauncher3.getAppPackageName;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -45,6 +46,7 @@ import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherModel;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager;
|
||||
import com.android.launcher3.MainThreadExecutor;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.compat.LauncherAppsCompat;
|
||||
@@ -52,6 +54,7 @@ import com.android.launcher3.model.AppLaunchTracker;
|
||||
import com.android.launcher3.tapl.LauncherInstrumentation;
|
||||
import com.android.launcher3.tapl.TestHelpers;
|
||||
import com.android.launcher3.testcomponent.TestCommandReceiver;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
import com.android.launcher3.util.Wait;
|
||||
import com.android.launcher3.util.rule.FailureWatcher;
|
||||
@@ -103,6 +106,10 @@ public abstract class AbstractLauncherUiTest {
|
||||
Utilities.enableRunningInTestHarnessForTests();
|
||||
mLauncher.setSystemHealthSupplier(() -> TestCommandReceiver.callCommand(
|
||||
TestCommandReceiver.GET_SYSTEM_HEALTH_MESSAGE).getString("result"));
|
||||
mLauncher.setOnSettledStateAction(
|
||||
containerType -> executeOnLauncher(
|
||||
launcher ->
|
||||
checkLauncherIntegrity(launcher, containerType)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,4 +386,68 @@ public abstract class AbstractLauncherUiTest {
|
||||
protected int getAllAppsScroll(Launcher launcher) {
|
||||
return launcher.getAppsView().getActiveRecyclerView().getCurrentScrollY();
|
||||
}
|
||||
|
||||
private static void checkLauncherIntegrity(
|
||||
Launcher launcher, ContainerType expectedContainerType) {
|
||||
if (launcher != null) {
|
||||
final LauncherStateManager stateManager = launcher.getStateManager();
|
||||
final LauncherState stableState = stateManager.getCurrentStableState();
|
||||
|
||||
assertTrue("Stable state != state: " + stableState.getClass().getSimpleName() + ", "
|
||||
+ stateManager.getState().getClass().getSimpleName(),
|
||||
stableState == stateManager.getState());
|
||||
|
||||
final boolean isResumed = launcher.hasBeenResumed();
|
||||
assertTrue("hasBeenResumed() != isStarted(), hasBeenResumed(): " + isResumed,
|
||||
isResumed == launcher.isStarted());
|
||||
assertTrue("hasBeenResumed() != isUserActive(), hasBeenResumed(): " + isResumed,
|
||||
isResumed == launcher.isUserActive());
|
||||
|
||||
final int ordinal = stableState.ordinal;
|
||||
|
||||
switch (expectedContainerType) {
|
||||
case WORKSPACE:
|
||||
case WIDGETS: {
|
||||
assertTrue(
|
||||
"Launcher is not resumed in state: " + expectedContainerType,
|
||||
isResumed);
|
||||
assertTrue(TestProtocol.stateOrdinalToString(ordinal),
|
||||
ordinal == TestProtocol.NORMAL_STATE_ORDINAL);
|
||||
break;
|
||||
}
|
||||
case ALL_APPS: {
|
||||
assertTrue(
|
||||
"Launcher is not resumed in state: " + expectedContainerType,
|
||||
isResumed);
|
||||
assertTrue(TestProtocol.stateOrdinalToString(ordinal),
|
||||
ordinal == TestProtocol.ALL_APPS_STATE_ORDINAL);
|
||||
break;
|
||||
}
|
||||
case OVERVIEW: {
|
||||
assertTrue(
|
||||
"Launcher is not resumed in state: " + expectedContainerType,
|
||||
isResumed);
|
||||
assertTrue(TestProtocol.stateOrdinalToString(ordinal),
|
||||
ordinal == TestProtocol.OVERVIEW_STATE_ORDINAL);
|
||||
break;
|
||||
}
|
||||
case BACKGROUND: {
|
||||
assertTrue("Launcher is resumed in state: " + expectedContainerType,
|
||||
!isResumed);
|
||||
assertTrue(TestProtocol.stateOrdinalToString(ordinal),
|
||||
ordinal == TestProtocol.NORMAL_STATE_ORDINAL);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"Illegal container: " + expectedContainerType);
|
||||
}
|
||||
} else {
|
||||
assertTrue(
|
||||
"Container type is not BACKGROUND or FALLBACK_OVERVIEW: "
|
||||
+ expectedContainerType,
|
||||
expectedContainerType == ContainerType.BACKGROUND ||
|
||||
expectedContainerType == ContainerType.FALLBACK_OVERVIEW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.android.launcher3.ui;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.Surface;
|
||||
|
||||
import com.android.launcher3.tapl.TestHelpers;
|
||||
@@ -9,6 +10,7 @@ import org.junit.runner.Description;
|
||||
import org.junit.runners.model.Statement;
|
||||
|
||||
class PortraitLandscapeRunner implements TestRule {
|
||||
private static final String TAG = "PortraitLandscapeRunner";
|
||||
private AbstractLauncherUiTest mTest;
|
||||
|
||||
public PortraitLandscapeRunner(AbstractLauncherUiTest test) {
|
||||
@@ -36,6 +38,9 @@ class PortraitLandscapeRunner implements TestRule {
|
||||
|
||||
evaluateInPortrait();
|
||||
evaluateInLandscape();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Exception", e);
|
||||
throw e;
|
||||
} finally {
|
||||
mTest.mDevice.setOrientationNatural();
|
||||
mTest.executeOnLauncher(launcher ->
|
||||
|
||||
@@ -16,10 +16,16 @@
|
||||
|
||||
package com.android.launcher3.tapl;
|
||||
|
||||
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
||||
|
||||
import androidx.test.uiautomator.By;
|
||||
import androidx.test.uiautomator.UiObject2;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class AddToHomeScreenPrompt {
|
||||
private static final Pattern ADD_AUTOMATICALLY =
|
||||
Pattern.compile("^Add automatically$", CASE_INSENSITIVE);
|
||||
private final LauncherInstrumentation mLauncher;
|
||||
private final UiObject2 mWidgetCell;
|
||||
|
||||
@@ -33,9 +39,6 @@ public class AddToHomeScreenPrompt {
|
||||
public void addAutomatically() {
|
||||
mLauncher.waitForObjectInContainer(
|
||||
mWidgetCell.getParent().getParent().getParent().getParent(),
|
||||
By.text(LauncherInstrumentation.isAvd()
|
||||
? "ADD AUTOMATICALLY"
|
||||
: "Add automatically")).
|
||||
click();
|
||||
By.text(ADD_AUTOMATICALLY)).click();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,8 @@ public class Background extends LauncherInstrumentation.VisibleContainer {
|
||||
"want to switch from background to overview")) {
|
||||
verifyActiveContainer();
|
||||
goToOverviewUnchecked(BACKGROUND_APP_STATE_ORDINAL);
|
||||
return new BaseOverview(mLauncher);
|
||||
return mLauncher.isFallbackOverview() ?
|
||||
new BaseOverview(mLauncher) : new Overview(mLauncher);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
|
||||
|
||||
@Override
|
||||
protected LauncherInstrumentation.ContainerType getContainerType() {
|
||||
return LauncherInstrumentation.ContainerType.BASE_OVERVIEW;
|
||||
return LauncherInstrumentation.ContainerType.FALLBACK_OVERVIEW;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -72,6 +72,7 @@ import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
@@ -86,8 +87,8 @@ public final class LauncherInstrumentation {
|
||||
|
||||
// Types for launcher containers that the user is interacting with. "Background" is a
|
||||
// pseudo-container corresponding to inactive launcher covered by another app.
|
||||
enum ContainerType {
|
||||
WORKSPACE, ALL_APPS, OVERVIEW, WIDGETS, BACKGROUND, BASE_OVERVIEW
|
||||
public enum ContainerType {
|
||||
WORKSPACE, ALL_APPS, OVERVIEW, WIDGETS, BACKGROUND, FALLBACK_OVERVIEW
|
||||
}
|
||||
|
||||
public enum NavigationModel {ZERO_BUTTON, TWO_BUTTON, THREE_BUTTON}
|
||||
@@ -135,6 +136,8 @@ public final class LauncherInstrumentation {
|
||||
private final Deque<String> mDiagnosticContext = new LinkedList<>();
|
||||
private Supplier<String> mSystemHealthSupplier;
|
||||
|
||||
private Consumer<ContainerType> mOnSettledStateAction;
|
||||
|
||||
/**
|
||||
* Constructs the root of TAPL hierarchy. You get all other objects from it.
|
||||
*/
|
||||
@@ -296,6 +299,10 @@ public final class LauncherInstrumentation {
|
||||
this.mSystemHealthSupplier = supplier;
|
||||
}
|
||||
|
||||
public void setOnSettledStateAction(Consumer<ContainerType> onSettledStateAction) {
|
||||
mOnSettledStateAction = onSettledStateAction;
|
||||
}
|
||||
|
||||
private String getSystemHealthMessage() {
|
||||
final String testPackage = getContext().getPackageName();
|
||||
try {
|
||||
@@ -396,7 +403,7 @@ public final class LauncherInstrumentation {
|
||||
}
|
||||
|
||||
private UiObject2 verifyContainerType(ContainerType containerType) {
|
||||
//waitForTouchInteractionService();
|
||||
waitForLauncherInitialized();
|
||||
|
||||
assertEquals("Unexpected display rotation",
|
||||
mExpectedRotation, mDevice.getDisplayRotation());
|
||||
@@ -415,6 +422,14 @@ public final class LauncherInstrumentation {
|
||||
assertTrue(error, error == null);
|
||||
log("verifyContainerType: " + containerType);
|
||||
|
||||
final UiObject2 container = verifyVisibleObjects(containerType);
|
||||
|
||||
if (mOnSettledStateAction != null) mOnSettledStateAction.accept(containerType);
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
private UiObject2 verifyVisibleObjects(ContainerType containerType) {
|
||||
try (Closable c = addContextLayer(
|
||||
"but the current state is not " + containerType.name())) {
|
||||
switch (containerType) {
|
||||
@@ -451,7 +466,7 @@ public final class LauncherInstrumentation {
|
||||
|
||||
return waitForLauncherObject(OVERVIEW_RES_ID);
|
||||
}
|
||||
case BASE_OVERVIEW: {
|
||||
case FALLBACK_OVERVIEW: {
|
||||
return waitForFallbackLauncherObject(OVERVIEW_RES_ID);
|
||||
}
|
||||
case BACKGROUND: {
|
||||
@@ -468,7 +483,7 @@ public final class LauncherInstrumentation {
|
||||
}
|
||||
}
|
||||
|
||||
private void waitForTouchInteractionService() {
|
||||
private void waitForLauncherInitialized() {
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
if (getTestInfo(
|
||||
TestProtocol.REQUEST_IS_LAUNCHER_INITIALIZED).
|
||||
@@ -477,7 +492,7 @@ public final class LauncherInstrumentation {
|
||||
}
|
||||
SystemClock.sleep(100);
|
||||
}
|
||||
fail("TouchInteractionService didn't connect");
|
||||
fail("Launcher didn't initialize");
|
||||
}
|
||||
|
||||
Parcelable executeAndWaitForEvent(Runnable command,
|
||||
@@ -739,6 +754,10 @@ public final class LauncherInstrumentation {
|
||||
return mDevice.getLauncherPackageName();
|
||||
}
|
||||
|
||||
boolean isFallbackOverview() {
|
||||
return !getOverviewPackageName().equals(getLauncherPackageName());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public UiDevice getDevice() {
|
||||
return mDevice;
|
||||
@@ -774,7 +793,7 @@ public final class LauncherInstrumentation {
|
||||
startX = endX = rect.centerX();
|
||||
final int vertCenter = rect.centerY();
|
||||
final float halfGestureHeight = rect.height() * percent / 2.0f;
|
||||
startY = (int) (vertCenter - halfGestureHeight);
|
||||
startY = (int) (vertCenter - halfGestureHeight) + 1;
|
||||
endY = (int) (vertCenter + halfGestureHeight);
|
||||
}
|
||||
break;
|
||||
@@ -790,7 +809,7 @@ public final class LauncherInstrumentation {
|
||||
startY = endY = rect.centerY();
|
||||
final int horizCenter = rect.centerX();
|
||||
final float halfGestureWidth = rect.width() * percent / 2.0f;
|
||||
startX = (int) (horizCenter - halfGestureWidth);
|
||||
startX = (int) (horizCenter - halfGestureWidth) + 1;
|
||||
endX = (int) (horizCenter + halfGestureWidth);
|
||||
}
|
||||
break;
|
||||
@@ -817,6 +836,7 @@ public final class LauncherInstrumentation {
|
||||
// Inject a swipe gesture. Inject exactly 'steps' motion points, incrementing event time by a
|
||||
// fixed interval each time.
|
||||
void linearGesture(int startX, int startY, int endX, int endY, int steps) {
|
||||
log("linearGesture: " + startX + ", " + startY + " -> " + endX + ", " + endY);
|
||||
final long downTime = SystemClock.uptimeMillis();
|
||||
final Point start = new Point(startX, startY);
|
||||
final Point end = new Point(endX, endY);
|
||||
@@ -932,4 +952,12 @@ public final class LauncherInstrumentation {
|
||||
getContext().getSystemService(WindowManager.class).getDefaultDisplay().getRealSize(size);
|
||||
return size;
|
||||
}
|
||||
|
||||
public void enableDebugTracing() {
|
||||
getTestInfo(TestProtocol.REQUEST_ENABLE_DEBUG_TRACING);
|
||||
}
|
||||
|
||||
public void disableDebugTracing() {
|
||||
getTestInfo(TestProtocol.REQUEST_DISABLE_DEBUG_TRACING);
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import android.os.DropBoxManager;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class TestHelpers {
|
||||
@@ -104,28 +105,21 @@ public class TestHelpers {
|
||||
DropBoxManager dropbox = (DropBoxManager) context.getSystemService(Context.DROPBOX_SERVICE);
|
||||
Assert.assertNotNull("Unable access the DropBoxManager service", dropbox);
|
||||
|
||||
long timestamp = 0;
|
||||
long timestamp = System.currentTimeMillis() - 5 * 60000;
|
||||
DropBoxManager.Entry entry;
|
||||
int crashCount = 0;
|
||||
StringBuilder errorDetails = new StringBuilder();
|
||||
while (null != (entry = dropbox.getNextEntry(label, timestamp))) {
|
||||
String dropboxSnippet;
|
||||
try {
|
||||
dropboxSnippet = entry.getText(4096);
|
||||
} finally {
|
||||
entry.close();
|
||||
}
|
||||
|
||||
crashCount++;
|
||||
errorDetails.append(label);
|
||||
errorDetails.append(": ");
|
||||
errorDetails.append(truncateCrash(dropboxSnippet, 40));
|
||||
errorDetails.append(" ...\n");
|
||||
|
||||
timestamp = entry.getTimeMillis();
|
||||
errorDetails.append(new Date(timestamp));
|
||||
errorDetails.append(": ");
|
||||
errorDetails.append(entry.getTag());
|
||||
errorDetails.append(": ");
|
||||
final String dropboxSnippet = entry.getText(4096);
|
||||
if (dropboxSnippet != null) errorDetails.append(truncateCrash(dropboxSnippet, 40));
|
||||
errorDetails.append(" ...\n");
|
||||
entry.close();
|
||||
}
|
||||
Assert.assertEquals(errorDetails.toString(), 0, crashCount);
|
||||
return crashCount > 0 ? errorDetails.toString() : null;
|
||||
return errorDetails.length() != 0 ? errorDetails.toString() : null;
|
||||
}
|
||||
|
||||
public static String getSystemHealthMessage(Context context) {
|
||||
@@ -133,9 +127,15 @@ public class TestHelpers {
|
||||
StringBuilder errors = new StringBuilder();
|
||||
|
||||
final String[] labels = {
|
||||
"system_app_anr",
|
||||
"system_app_crash",
|
||||
"system_app_native_crash",
|
||||
"system_app_wtf",
|
||||
"system_server_anr",
|
||||
"system_server_crash",
|
||||
"system_server_native_crash",
|
||||
"system_server_anr",
|
||||
"system_server_watchdog",
|
||||
"system_server_wtf",
|
||||
};
|
||||
|
||||
for (String label : labels) {
|
||||
|
||||
Reference in New Issue
Block a user