Merge "Support individual lock task features" into ub-launcher3-qt-dev
diff --git a/Android.bp b/Android.bp
index b80282e..4c38205 100644
--- a/Android.bp
+++ b/Android.bp
@@ -25,7 +25,7 @@
"tests/tapl/**/*.java",
"src/com/android/launcher3/util/SecureSettingsObserver.java",
"src/com/android/launcher3/ResourceUtils.java",
- "src/com/android/launcher3/TestProtocol.java",
+ "src/com/android/launcher3/testing/TestProtocol.java",
],
manifest: "tests/tapl/AndroidManifest.xml",
platform_apis: true,
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index ef5bb26..5318a12 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -176,5 +176,12 @@
</intent-filter>
</activity>
+ <provider
+ android:name="com.android.launcher3.testing.TestInformationProvider"
+ android:authorities="${packageName}.TestInfo"
+ android:readPermission="android.permission.WRITE_SECURE_SETTINGS"
+ android:writePermission="android.permission.WRITE_SECURE_SETTINGS"
+ android:exported="true"
+ android:enabled="false" />
</application>
</manifest>
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..6c1273f
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,12 @@
+# Use this reviewer by default.
+# gnl-eng@google.com (Googlers only)
+
+# People who can approve changes for submission
+#
+
+adamcohen@google.com
+hyunyoungs@google.com
+mrcasey@google.com
+sunnygoyal@google.com
+twickham@google.com
+winsonc@google.com
diff --git a/go/quickstep/res/layout/clear_all_button.xml b/go/quickstep/res/layout/clear_all_button.xml
index 2f7c8ae..eef66ad 100644
--- a/go/quickstep/res/layout/clear_all_button.xml
+++ b/go/quickstep/res/layout/clear_all_button.xml
@@ -29,5 +29,6 @@
android:text="@string/recents_clear_all"
android:textAllCaps="false"
android:textColor="@color/clear_all_button_text"
- android:textSize="14sp"/>
+ android:textSize="14sp"
+ style="@style/TextTitle"/>
</FrameLayout>
diff --git a/go/quickstep/res/layout/icon_recents_root_view.xml b/go/quickstep/res/layout/icon_recents_root_view.xml
index 595a380..8381ebc 100644
--- a/go/quickstep/res/layout/icon_recents_root_view.xml
+++ b/go/quickstep/res/layout/icon_recents_root_view.xml
@@ -36,5 +36,6 @@
android:text="@string/recents_empty_message"
android:textColor="@android:color/white"
android:textSize="25sp"
+ style="@style/TextTitle"
android:visibility="gone"/>
</com.android.quickstep.views.IconRecentsView>
\ No newline at end of file
diff --git a/go/quickstep/res/layout/task_item_view.xml b/go/quickstep/res/layout/task_item_view.xml
index ab2cf28..aeac477 100644
--- a/go/quickstep/res/layout/task_item_view.xml
+++ b/go/quickstep/res/layout/task_item_view.xml
@@ -41,5 +41,6 @@
android:layout_gravity="center_vertical"
android:singleLine="true"
android:textColor="@android:color/white"
- android:textSize="24sp"/>
+ android:textSize="24sp"
+ style="@style/TextTitle"/>
</com.android.quickstep.views.TaskItemView>
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index be275e0..332e0fa 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -73,14 +73,6 @@
</intent-filter>
</provider>
- <provider
- android:name="com.android.quickstep.TestInformationProvider"
- android:authorities="${packageName}.TestInfo"
- android:readPermission="android.permission.WRITE_SECURE_SETTINGS"
- android:writePermission="android.permission.WRITE_SECURE_SETTINGS"
- android:exported="true">
- </provider>
-
<service
android:name="com.android.launcher3.uioverrides.dynamicui.WallpaperManagerCompatVL$ColorExtractionService"
tools:node="remove" />
@@ -92,6 +84,11 @@
android:clearTaskOnLaunch="true"
android:exported="false" />
+ <activity android:name="com.android.quickstep.LockScreenRecentsActivity"
+ android:theme="@android:style/Theme.NoDisplay"
+ android:showOnLockScreen="true"
+ android:directBootAware="true" />
+
</application>
</manifest>
diff --git a/quickstep/recents_ui_overrides/res/layout/prediction_load_progress.xml b/quickstep/recents_ui_overrides/res/layout/prediction_load_progress.xml
deleted file mode 100644
index 20c4004..0000000
--- a/quickstep/recents_ui_overrides/res/layout/prediction_load_progress.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
- style="?android:attr/progressBarStyleHorizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:layout_marginLeft="20dp"
- android:layout_marginRight="20dp"
- android:indeterminate="true"
- android:indeterminateOnly="true"
- android:indeterminateTint="?workspaceTextColor" />
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java
index af67e1b..8f1282d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java
@@ -56,7 +56,7 @@
private static final int MSG_LAUNCH = 2;
private static final int MSG_PREDICT = 3;
- private final Context mContext;
+ protected final Context mContext;
private final Handler mMessageHandler;
// Accessed only on worker thread
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java
index 55f4c98..4a486f8 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -28,7 +28,6 @@
import android.util.AttributeSet;
import android.util.IntProperty;
import android.util.Log;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.Interpolator;
import android.widget.LinearLayout;
@@ -115,8 +114,6 @@
private final AnimatedFloat mOverviewScrollFactor =
new AnimatedFloat(this::updateTranslationAndAlpha);
- private View mLoadingProgress;
-
private boolean mPredictionsEnabled = false;
public PredictionRowView(@NonNull Context context) {
@@ -165,7 +162,6 @@
public void setup(FloatingHeaderView parent, FloatingHeaderRow[] rows, boolean tabsHidden) {
mParent = parent;
- setPredictionsEnabled(mPredictionUiStateManager.arePredictionsEnabled());
}
private void setPredictionsEnabled(boolean predictionsEnabled) {
@@ -205,7 +201,7 @@
@Override
public boolean hasVisibleContent() {
- return mPredictionUiStateManager.arePredictionsEnabled();
+ return mPredictionsEnabled;
}
/**
@@ -241,9 +237,6 @@
}
private void applyPredictionApps() {
- if (mLoadingProgress != null) {
- removeView(mLoadingProgress);
- }
if (!mPredictionsEnabled) {
mParent.onHeightUpdated();
return;
@@ -290,15 +283,8 @@
}
if (predictionCount == 0) {
- if (mLoadingProgress == null) {
- mLoadingProgress = LayoutInflater.from(getContext())
- .inflate(R.layout.prediction_load_progress, this, false);
- }
- addView(mLoadingProgress);
- } else {
- mLoadingProgress = null;
+ setPredictionsEnabled(false);
}
-
mParent.onHeightUpdated();
}
@@ -342,11 +328,8 @@
public void setTextAlpha(int alpha) {
mIconCurrentTextAlpha = alpha;
int iconColor = setColorAlphaBound(mIconTextColor, mIconCurrentTextAlpha);
-
- if (mLoadingProgress == null) {
- for (int i = 0; i < getChildCount(); i++) {
- ((BubbleTextView) getChildAt(i)).setTextColor(iconColor);
- }
+ for (int i = 0; i < getChildCount(); i++) {
+ ((BubbleTextView) getChildAt(i)).setTextColor(iconColor);
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
index 6dad9af..64cb4b4 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
@@ -24,7 +24,6 @@
import android.app.prediction.AppTarget;
import android.content.ComponentName;
import android.content.Context;
-import android.os.Handler;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import com.android.launcher3.AppInfo;
@@ -63,7 +62,6 @@
OnIDPChangeListener, OnUpdateListener {
public static final String LAST_PREDICTION_ENABLED_STATE = "last_prediction_enabled_state";
- private static final long INITIAL_CALLBACK_WAIT_TIMEOUT_MS = 5000;
// TODO (b/129421797): Update the client constants
public enum Client {
@@ -110,13 +108,8 @@
for (int i = 0; i < mPredictionServicePredictions.length; i++) {
mPredictionServicePredictions[i] = Collections.emptyList();
}
-
mGettingValidPredictionResults = Utilities.getDevicePrefs(context)
.getBoolean(LAST_PREDICTION_ENABLED_STATE, true);
- if (mGettingValidPredictionResults) {
- new Handler().postDelayed(
- this::updatePredictionStateAfterCallback, INITIAL_CALLBACK_WAIT_TIMEOUT_MS);
- }
// Call this last
mCurrentState = parseLastState();
@@ -293,10 +286,6 @@
dispatchOnChange(false);
}
- public boolean arePredictionsEnabled() {
- return mCurrentState.isEnabled;
- }
-
private boolean canApplyPredictions(PredictionState newState) {
if (mAppsView == null) {
// If there is no apps view, no need to schedule.
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
index 90b5536..00e4a9d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
@@ -30,6 +30,7 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.RectF;
@@ -68,6 +69,8 @@
*/
public final class LauncherActivityControllerHelper implements ActivityControlHelper<Launcher> {
+ private Runnable mAdjustInterpolatorsRunnable;
+
@Override
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
LayoutUtils.calculateLauncherTaskSize(context, dp, outRect);
@@ -118,7 +121,8 @@
final RectF iconLocation = new RectF();
boolean canUseWorkspaceView = workspaceView != null && workspaceView.isAttachedToWindow();
FloatingIconView floatingIconView = canUseWorkspaceView
- ? recentsView.getFloatingIconView(activity, workspaceView, iconLocation)
+ ? FloatingIconView.getFloatingIconView(activity, workspaceView,
+ true /* hideOriginal */, iconLocation, false /* isOpening */)
: null;
return new HomeAnimationFactory() {
@@ -193,6 +197,13 @@
}
@Override
+ public void adjustActivityControllerInterpolators() {
+ if (mAdjustInterpolatorsRunnable != null) {
+ mAdjustInterpolatorsRunnable.run();
+ }
+ }
+
+ @Override
public void onTransitionCancelled() {
activity.getStateManager().goToState(startState, false /* animate */);
}
@@ -274,6 +285,7 @@
playScaleDownAnim(anim, activity, fromState, endState);
anim.setDuration(transitionLength * 2);
+ anim.setInterpolator(LINEAR);
AnimatorPlaybackController controller =
AnimatorPlaybackController.wrap(anim, transitionLength * 2);
activity.getStateManager().setCurrentUserControlledAnimation(controller);
@@ -290,7 +302,6 @@
Animator shiftAnim = new SpringObjectAnimator<>(activity.getAllAppsController(),
"allAppsSpringFromACH", activity.getAllAppsController().getShiftRange(),
SPRING_DAMPING_RATIO, SPRING_STIFFNESS, progressValues);
- shiftAnim.setInterpolator(LINEAR);
return shiftAnim;
}
@@ -309,19 +320,37 @@
= fromState.getOverviewScaleAndTranslation(launcher);
LauncherState.ScaleAndTranslation endScaleAndTranslation
= endState.getOverviewScaleAndTranslation(launcher);
+ float fromTranslationY = fromScaleAndTranslation.translationY;
+ float endTranslationY = endScaleAndTranslation.translationY;
float fromFullscreenProgress = fromState.getOverviewFullscreenProgress();
float endFullscreenProgress = endState.getOverviewFullscreenProgress();
Animator scale = ObjectAnimator.ofFloat(recentsView, SCALE_PROPERTY,
fromScaleAndTranslation.scale, endScaleAndTranslation.scale);
Animator translateY = ObjectAnimator.ofFloat(recentsView, TRANSLATION_Y,
- fromScaleAndTranslation.translationY, endScaleAndTranslation.translationY);
+ fromTranslationY, endTranslationY);
Animator applyFullscreenProgress = ObjectAnimator.ofFloat(recentsView,
RecentsView.FULLSCREEN_PROGRESS, fromFullscreenProgress, endFullscreenProgress);
- scale.setInterpolator(LINEAR);
- translateY.setInterpolator(LINEAR);
- applyFullscreenProgress.setInterpolator(LINEAR);
anim.playTogether(scale, translateY, applyFullscreenProgress);
+
+ mAdjustInterpolatorsRunnable = () -> {
+ // Adjust the translateY interpolator to account for the running task's top inset.
+ // When progress <= 1, this is handled by each task view as they set their fullscreen
+ // progress. However, once we go to progress > 1, fullscreen progress stays at 0, so
+ // recents as a whole needs to translate further to keep up with the app window.
+ TaskView runningTaskView = recentsView.getRunningTaskView();
+ if (runningTaskView == null) {
+ runningTaskView = recentsView.getTaskViewAt(recentsView.getCurrentPage());
+ }
+ TimeInterpolator oldInterpolator = translateY.getInterpolator();
+ Rect fallbackInsets = launcher.getDeviceProfile().getInsets();
+ float extraTranslationY = runningTaskView.getThumbnail().getInsets(fallbackInsets).top;
+ float normalizedTranslationY = extraTranslationY / (fromTranslationY - endTranslationY);
+ translateY.setInterpolator(t -> {
+ float newT = oldInterpolator.getInterpolation(t);
+ return newT <= 1f ? newT : newT + normalizedTranslationY * (newT - 1);
+ });
+ };
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LockScreenRecentsActivity.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LockScreenRecentsActivity.java
new file mode 100644
index 0000000..65f323c
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LockScreenRecentsActivity.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * Empty activity to start a recents transition
+ */
+public class LockScreenRecentsActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ finish();
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index 906ce5d..7563c3f 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -337,16 +337,8 @@
defaultDisplay.getRealSize(realSize);
mSwipeTouchRegion.set(0, 0, realSize.x, realSize.y);
if (mMode == Mode.NO_BUTTON) {
- switch (defaultDisplay.getRotation()) {
- case Surface.ROTATION_90:
- case Surface.ROTATION_270:
- mSwipeTouchRegion.top = mSwipeTouchRegion.bottom - getNavbarSize(
- ResourceUtils.NAVBAR_LANDSCAPE_BOTTOM_SIZE);
- break;
- default:
- mSwipeTouchRegion.top = mSwipeTouchRegion.bottom - getNavbarSize(
- ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE);
- }
+ mSwipeTouchRegion.top = mSwipeTouchRegion.bottom -
+ getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE);
} else {
switch (defaultDisplay.getRotation()) {
case Surface.ROTATION_90:
@@ -359,7 +351,7 @@
break;
default:
mSwipeTouchRegion.top = mSwipeTouchRegion.bottom
- - getNavbarSize(ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE);
+ - getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE);
}
}
}
@@ -490,7 +482,7 @@
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 new DeviceLockedInputConsumer(this);
+ return createDeviceLockedInputConsumer(mAM.getRunningTask(0));
} else {
return InputConsumer.NO_OP;
}
@@ -525,16 +517,15 @@
}
private InputConsumer newBaseConsumer(boolean useSharedState, MotionEvent event) {
- if (mKM.isDeviceLocked()) {
- // 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 new DeviceLockedInputConsumer(this);
- }
-
final RunningTaskInfo runningTaskInfo = mAM.getRunningTask(0);
if (!useSharedState) {
mSwipeSharedState.clearAllState();
}
+ if (mKM.isDeviceLocked()) {
+ // 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(runningTaskInfo);
+ }
final ActivityControlHelper activityControl =
mOverviewComponentObserver.getActivityControlHelper();
@@ -572,6 +563,15 @@
mSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion);
}
+ private InputConsumer createDeviceLockedInputConsumer(RunningTaskInfo taskInfo) {
+ if (mMode == Mode.NO_BUTTON && taskInfo != null) {
+ return new DeviceLockedInputConsumer(this, mSwipeSharedState, mInputMonitorCompat,
+ mSwipeTouchRegion, taskInfo.taskId);
+ } else {
+ return InputConsumer.NO_OP;
+ }
+ }
+
/**
* To be called by the consumer when it's no longer active.
*/
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 2484d2f..ca966c8 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -172,7 +172,8 @@
STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_LAUNCHER_STARTED;
public enum GestureEndTarget {
- HOME(1, STATE_SCALED_CONTROLLER_HOME, true, false, ContainerType.WORKSPACE, false),
+ HOME(1, STATE_SCALED_CONTROLLER_HOME | STATE_CAPTURE_SCREENSHOT, true, false,
+ ContainerType.WORKSPACE, false),
RECENTS(1, STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT
| STATE_SCREENSHOT_VIEW_SHOWN, true, false, ContainerType.TASKSWITCHER, true),
@@ -218,6 +219,12 @@
private static final long SHELF_ANIM_DURATION = 120;
public static final long RECENTS_ATTACH_DURATION = 300;
+ // Start resisting when swiping past this factor of mTransitionDragLength.
+ private static final float DRAG_LENGTH_FACTOR_START_PULLBACK = 1.4f;
+ // This is how far down we can scale down, where 0f is full screen and 1f is recents.
+ private static final float DRAG_LENGTH_FACTOR_MAX_PULLBACK = 1.8f;
+ private static final Interpolator PULLBACK_INTERPOLATOR = DEACCEL;
+
/**
* Used as the page index for logging when we return to the last task at the end of the gesture.
*/
@@ -232,7 +239,10 @@
private RunningWindowAnim mRunningWindowAnim;
private boolean mIsShelfPeeking;
private DeviceProfile mDp;
+ // The distance needed to drag to reach the task size in recents.
private int mTransitionDragLength;
+ // How much further we can drag past recents, as a factor of mTransitionDragLength.
+ private float mDragLengthFactor = 1;
// Shift in the range of [0, 1].
// 0 => preview snapShot is completely visible, and hotseat is completely translated down
@@ -333,9 +343,8 @@
| STATE_SCALED_CONTROLLER_RECENTS,
this::finishCurrentTransitionToRecents);
- mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_GESTURE_COMPLETED
- | STATE_SCALED_CONTROLLER_HOME | STATE_APP_CONTROLLER_RECEIVED
- | STATE_LAUNCHER_DRAWN,
+ mStateCallback.addCallback(STATE_SCREENSHOT_CAPTURED | STATE_GESTURE_COMPLETED
+ | STATE_SCALED_CONTROLLER_HOME,
this::finishCurrentTransitionToHome);
mStateCallback.addCallback(STATE_SCALED_CONTROLLER_HOME | STATE_CURRENT_TASK_FINISHED,
this::reset);
@@ -377,6 +386,10 @@
mTransitionDragLength = mActivityControlHelper.getSwipeUpDestinationAndLength(
dp, mContext, tempRect);
mClipAnimationHelper.updateTargetRect(tempRect);
+ if (mMode == Mode.NO_BUTTON) {
+ // We can drag all the way to the top of the screen.
+ mDragLengthFactor = (float) dp.heightPx / mTransitionDragLength;
+ }
}
private long getFadeInDuration() {
@@ -548,11 +561,18 @@
public void updateDisplacement(float displacement) {
// We are moving in the negative x/y direction
displacement = -displacement;
- if (displacement > mTransitionDragLength && mTransitionDragLength > 0) {
- mCurrentShift.updateValue(1);
+ if (displacement > mTransitionDragLength * mDragLengthFactor && mTransitionDragLength > 0) {
+ mCurrentShift.updateValue(mDragLengthFactor);
} else {
float translation = Math.max(displacement, 0);
float shift = mTransitionDragLength == 0 ? 0 : translation / mTransitionDragLength;
+ if (shift > DRAG_LENGTH_FACTOR_START_PULLBACK) {
+ float pullbackProgress = Utilities.getProgress(shift,
+ DRAG_LENGTH_FACTOR_START_PULLBACK, mDragLengthFactor);
+ pullbackProgress = PULLBACK_INTERPOLATOR.getInterpolation(pullbackProgress);
+ shift = DRAG_LENGTH_FACTOR_START_PULLBACK + pullbackProgress
+ * (DRAG_LENGTH_FACTOR_MAX_PULLBACK - DRAG_LENGTH_FACTOR_START_PULLBACK);
+ }
mCurrentShift.updateValue(shift);
}
}
@@ -640,6 +660,8 @@
private void onAnimatorPlaybackControllerCreated(AnimatorPlaybackController anim) {
mLauncherTransitionController = anim;
+ mLauncherTransitionController.dispatchSetInterpolator(t -> t * mDragLengthFactor);
+ mAnimationFactory.adjustActivityControllerInterpolators();
mLauncherTransitionController.dispatchOnStart();
updateLauncherTransitionProgress();
}
@@ -692,7 +714,9 @@
if (mGestureEndTarget == HOME) {
return;
}
- float progress = mCurrentShift.value;
+ // Normalize the progress to 0 to 1, as the animation controller will clamp it to that
+ // anyway. The controller mimics the drag length factor by applying it to its interpolators.
+ float progress = mCurrentShift.value / mDragLengthFactor;
mLauncherTransitionController.setPlayFraction(
progress <= mShiftAtGestureStart || mShiftAtGestureStart >= 1
? 0 : (progress - mShiftAtGestureStart) / (1 - mShiftAtGestureStart));
@@ -914,7 +938,7 @@
interpolator = endTarget == RECENTS ? OVERSHOOT_1_2 : DEACCEL;
} else {
startShift = Utilities.boundToRange(currentShift - velocityPxPerMs.y
- * SINGLE_FRAME_MS / mTransitionDragLength, 0, 1);
+ * SINGLE_FRAME_MS / mTransitionDragLength, 0, mDragLengthFactor);
float minFlingVelocity = mContext.getResources()
.getDimension(R.dimen.quickstep_fling_min_velocity);
if (Math.abs(endVelocity) > minFlingVelocity && mTransitionDragLength > 0) {
@@ -952,8 +976,10 @@
} else if (endTarget == RECENTS) {
mLiveTileOverlay.startIconAnimation();
if (mRecentsView != null) {
- duration = Utilities.boundToRange(mRecentsView.getScroller().getDuration(),
- duration, MAX_SWIPE_DURATION);
+ if (mRecentsView.getScroller().getDuration() > MAX_SWIPE_DURATION) {
+ mRecentsView.snapToPage(mRecentsView.getNextPage(), (int) MAX_SWIPE_DURATION);
+ }
+ duration = Math.max(duration, mRecentsView.getScroller().getDuration());
}
if (mMode == Mode.NO_BUTTON) {
setShelfState(ShelfAnimState.OVERVIEW, interpolator, duration);
@@ -1071,6 +1097,7 @@
mLauncherTransitionController.getAnimationPlayer().end();
} else {
mLauncherTransitionController.dispatchSetInterpolator(adjustedInterpolator);
+ mAnimationFactory.adjustActivityControllerInterpolators();
mLauncherTransitionController.getAnimationPlayer().setDuration(duration);
if (QUICKSTEP_SPRINGS.get()) {
@@ -1267,8 +1294,15 @@
if (mTaskSnapshot == null) {
mTaskSnapshot = controller.screenshotTask(mRunningTaskId);
}
- TaskView taskView = mRecentsView.updateThumbnail(mRunningTaskId, mTaskSnapshot);
- if (taskView != null) {
+ final TaskView taskView;
+ if (mGestureEndTarget == HOME) {
+ // Capture the screenshot before finishing the transition to home to ensure it's
+ // taken in the correct orientation, but no need to update the thumbnail.
+ taskView = null;
+ } else {
+ taskView = mRecentsView.updateThumbnail(mRunningTaskId, mTaskSnapshot);
+ }
+ if (taskView != null && !mCanceled) {
// Defer finishing the animation until the next launcher frame with the
// new thumbnail
finishTransitionPosted = new WindowCallbacksCompat(taskView) {
@@ -1278,6 +1312,13 @@
@Override
public void onPostDraw(Canvas canvas) {
+ // If we were cancelled after this was attached, do not update
+ // the state.
+ if (mCanceled) {
+ detach();
+ return;
+ }
+
if (mDeferFrameCount > 0) {
mDeferFrameCount--;
// Workaround, detach and reattach to invalidate the root node for
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java
index 09d323e..1820729 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java
@@ -20,7 +20,6 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.util.AttributeSet;
-import android.view.WindowInsets;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.R;
@@ -71,7 +70,7 @@
// Update device profile before notifying the children.
mActivity.getDeviceProfile().updateInsets(insets);
setInsets(insets);
- return true; // I'll take it from here
+ return false; // Let children get the full insets
}
@Override
@@ -89,10 +88,4 @@
mActivity.getDeviceProfile().updateInsets(mInsets);
super.setInsets(mInsets);
}
-
- @Override
- public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
- updateTouchExcludeRegion(insets);
- return super.dispatchApplyWindowInsets(insets);
- }
}
\ No newline at end of file
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
index d01b5ec..db2af59 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
@@ -15,26 +15,102 @@
*/
package com.android.quickstep.inputconsumers;
+import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_POINTER_DOWN;
+import static android.view.MotionEvent.ACTION_UP;
+
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.Utilities.squaredTouchSlop;
+import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
+import static com.android.quickstep.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.graphics.Point;
import android.graphics.PointF;
+import android.graphics.Rect;
+import android.graphics.RectF;
import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.ViewConfiguration;
+import android.view.WindowManager;
+
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.quickstep.LockScreenRecentsActivity;
+import com.android.quickstep.MultiStateCallback;
+import com.android.quickstep.SwipeSharedState;
+import com.android.quickstep.util.ClipAnimationHelper;
+import com.android.quickstep.util.RecentsAnimationListenerSet;
+import com.android.quickstep.util.SwipeAnimationTargetSet;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.BackgroundExecutor;
+import com.android.systemui.shared.system.InputMonitorCompat;
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
/**
* A dummy input consumer used when the device is still locked, e.g. from secure camera.
*/
-public class DeviceLockedInputConsumer implements InputConsumer {
+public class DeviceLockedInputConsumer implements InputConsumer,
+ SwipeAnimationTargetSet.SwipeAnimationListener {
+
+ private static final float SCALE_DOWN = 0.75f;
+
+ private static final String[] STATE_NAMES = DEBUG_STATES ? new String[2] : null;
+ private static int getFlagForIndex(int index, String name) {
+ if (DEBUG_STATES) {
+ STATE_NAMES[index] = name;
+ }
+ return 1 << index;
+ }
+
+ private static final int STATE_TARGET_RECEIVED =
+ getFlagForIndex(0, "STATE_TARGET_RECEIVED");
+ private static final int STATE_HANDLER_INVALIDATED =
+ getFlagForIndex(1, "STATE_HANDLER_INVALIDATED");
private final Context mContext;
private final float mTouchSlopSquared;
- private final PointF mTouchDown = new PointF();
+ private final SwipeSharedState mSwipeSharedState;
+ private final InputMonitorCompat mInputMonitorCompat;
- public DeviceLockedInputConsumer(Context context) {
+ private final PointF mTouchDown = new PointF();
+ private final ClipAnimationHelper mClipAnimationHelper;
+ private final ClipAnimationHelper.TransformParams mTransformParams;
+ private final Point mDisplaySize;
+ private final MultiStateCallback mStateCallback;
+ private final RectF mSwipeTouchRegion;
+ public final int mRunningTaskId;
+
+ private VelocityTracker mVelocityTracker;
+ private float mProgress;
+
+ private boolean mThresholdCrossed = false;
+
+ private SwipeAnimationTargetSet mTargetSet;
+
+ public DeviceLockedInputConsumer(Context context, SwipeSharedState swipeSharedState,
+ InputMonitorCompat inputMonitorCompat, RectF swipeTouchRegion, int runningTaskId) {
mContext = context;
mTouchSlopSquared = squaredTouchSlop(context);
+ mSwipeSharedState = swipeSharedState;
+ mClipAnimationHelper = new ClipAnimationHelper(context);
+ mTransformParams = new ClipAnimationHelper.TransformParams();
+ mInputMonitorCompat = inputMonitorCompat;
+ mSwipeTouchRegion = swipeTouchRegion;
+ mRunningTaskId = runningTaskId;
+
+ // Do not use DeviceProfile as the user data might be locked
+ mDisplaySize = new Point();
+ context.getSystemService(WindowManager.class).getDefaultDisplay().getRealSize(mDisplaySize);
+
+ // Init states
+ mStateCallback = new MultiStateCallback(STATE_NAMES);
+ mStateCallback.addCallback(STATE_TARGET_RECEIVED | STATE_HANDLER_INVALIDATED,
+ this::endRemoteAnimation);
+
+ mVelocityTracker = VelocityTracker.obtain();
}
@Override
@@ -44,17 +120,137 @@
@Override
public void onMotionEvent(MotionEvent ev) {
+ if (mVelocityTracker == null) {
+ return;
+ }
+ mVelocityTracker.addMovement(ev);
+
float x = ev.getX();
float y = ev.getY();
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- mTouchDown.set(x, y);
- } else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
- if (squaredHypot(x - mTouchDown.x, y - mTouchDown.y) > mTouchSlopSquared) {
+ switch (ev.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mTouchDown.set(x, y);
+ break;
+ case ACTION_POINTER_DOWN: {
+ if (!mThresholdCrossed) {
+ // Cancel interaction in case of multi-touch interaction
+ int ptrIdx = ev.getActionIndex();
+ if (!mSwipeTouchRegion.contains(ev.getX(ptrIdx), ev.getY(ptrIdx))) {
+ int action = ev.getAction();
+ ev.setAction(ACTION_CANCEL);
+ finishTouchTracking(ev);
+ ev.setAction(action);
+ }
+ }
+ break;
+ }
+ case MotionEvent.ACTION_MOVE: {
+ if (!mThresholdCrossed) {
+ if (squaredHypot(x - mTouchDown.x, y - mTouchDown.y) > mTouchSlopSquared) {
+ startRecentsTransition();
+ }
+ } else {
+ float dy = Math.max(mTouchDown.y - y, 0);
+ mProgress = dy / mDisplaySize.y;
+ mTransformParams.setProgress(mProgress);
+ if (mTargetSet != null) {
+ mClipAnimationHelper.applyTransform(mTargetSet, mTransformParams);
+ }
+ }
+ break;
+ }
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ finishTouchTracking(ev);
+ break;
+ }
+ }
+
+ /**
+ * Called when the gesture has ended. Does not correlate to the completion of the interaction as
+ * the animation can still be running.
+ */
+ private void finishTouchTracking(MotionEvent ev) {
+ mStateCallback.setState(STATE_HANDLER_INVALIDATED);
+ if (mThresholdCrossed && ev.getAction() == ACTION_UP) {
+ mVelocityTracker.computeCurrentVelocity(1000,
+ ViewConfiguration.get(mContext).getScaledMaximumFlingVelocity());
+
+ float velocityY = mVelocityTracker.getYVelocity();
+ float flingThreshold = mContext.getResources()
+ .getDimension(R.dimen.quickstep_fling_threshold_velocity);
+
+ boolean dismissTask;
+ if (Math.abs(velocityY) > flingThreshold) {
+ // Is fling
+ dismissTask = velocityY < 0;
+ } else {
+ dismissTask = mProgress >= (1 - MIN_PROGRESS_FOR_OVERVIEW);
+ }
+ if (dismissTask) {
// For now, just start the home intent so user is prompted to unlock the device.
mContext.startActivity(new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_HOME)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
}
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
+
+ private void startRecentsTransition() {
+ mThresholdCrossed = true;
+ RecentsAnimationListenerSet newListenerSet =
+ mSwipeSharedState.newRecentsAnimationListenerSet();
+ newListenerSet.addListener(this);
+ Intent intent = new Intent(Intent.ACTION_MAIN)
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .setComponent(new ComponentName(mContext, LockScreenRecentsActivity.class))
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+
+ mInputMonitorCompat.pilferPointers();
+ BackgroundExecutor.get().submit(
+ () -> ActivityManagerWrapper.getInstance().startRecentsActivity(
+ intent, null, newListenerSet, null, null));
+ }
+
+ @Override
+ public void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet) {
+ mTargetSet = targetSet;
+
+ Rect displaySize = new Rect(0, 0, mDisplaySize.x, mDisplaySize.y);
+ RemoteAnimationTargetCompat targetCompat = targetSet.findTask(mRunningTaskId);
+ if (targetCompat != null) {
+ mClipAnimationHelper.updateSource(displaySize, targetCompat);
+ }
+
+ Utilities.scaleRectAboutCenter(displaySize, SCALE_DOWN);
+ displaySize.offsetTo(displaySize.left, 0);
+ mClipAnimationHelper.updateTargetRect(displaySize);
+ mClipAnimationHelper.applyTransform(mTargetSet, mTransformParams);
+
+ mStateCallback.setState(STATE_TARGET_RECEIVED);
+ }
+
+ @Override
+ public void onRecentsAnimationCanceled() {
+ mTargetSet = null;
+ }
+
+ private void endRemoteAnimation() {
+ if (mTargetSet != null) {
+ mTargetSet.finishController(
+ false /* toRecents */, null /* callback */, false /* sendUserLeaveHint */);
+ }
+ }
+
+ @Override
+ public void onConsumerAboutToBeSwitched() {
+ mStateCallback.setState(STATE_HANDLER_INVALIDATED);
+ }
+
+ @Override
+ public boolean allowInterceptByParent() {
+ return !mThresholdCrossed;
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java
index c164a24..e2fb602 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java
@@ -23,7 +23,6 @@
import android.annotation.TargetApi;
import android.content.Context;
-import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Matrix.ScaleToFit;
import android.graphics.Rect;
@@ -160,14 +159,16 @@
public RectF applyTransform(RemoteAnimationTargetSet targetSet, TransformParams params,
boolean launcherOnTop) {
+ float progress = params.progress;
if (params.currentRect == null) {
RectF currentRect;
mTmpRectF.set(mTargetRect);
Utilities.scaleRectFAboutCenter(mTmpRectF, params.offsetScale);
- float progress = params.progress;
currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTmpRectF);
currentRect.offset(params.offsetX, 0);
+ // Don't clip past progress > 1.
+ progress = Math.min(1, progress);
final RectF sourceWindowClipInsets = params.forLiveTile
? mSourceWindowClipInsetsForLiveTile : mSourceWindowClipInsets;
mClipRectF.left = sourceWindowClipInsets.left * progress;
@@ -189,7 +190,7 @@
float alpha = 1f;
int layer = RemoteAnimationProvider.getLayer(app, mBoostModeTargetLayers);
float cornerRadius = 0f;
- float scale = params.currentRect.width() / crop.width();
+ float scale = Math.max(params.currentRect.width(), mTargetRect.width()) / crop.width();
if (app.mode == targetSet.targetMode) {
if (app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
mTmpMatrix.setRectToRect(mSourceRect, params.currentRect, ScaleToFit.FILL);
@@ -198,7 +199,7 @@
if (mSupportsRoundedCornersOnWindows) {
float windowCornerRadius = mUseRoundedCornersOnWindows
? mWindowCornerRadius : 0;
- cornerRadius = Utilities.mapRange(params.progress, windowCornerRadius,
+ cornerRadius = Utilities.mapRange(progress, windowCornerRadius,
mTaskCornerRadius);
mCurrentCornerRadius = cornerRadius;
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java
index 3f4ad58..77dc6f3 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java
@@ -16,26 +16,22 @@
package com.android.quickstep.util;
import android.animation.Animator;
-import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
-import android.animation.ValueAnimator;
import android.content.res.Resources;
import android.graphics.PointF;
import android.graphics.RectF;
-import android.util.FloatProperty;
import androidx.dynamicanimation.animation.DynamicAnimation.OnAnimationEndListener;
import androidx.dynamicanimation.animation.FloatPropertyCompat;
+import androidx.dynamicanimation.animation.SpringAnimation;
+import androidx.dynamicanimation.animation.SpringForce;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.FlingSpringAnim;
import java.util.ArrayList;
import java.util.List;
-import static com.android.launcher3.anim.Interpolators.DEACCEL;
/**
* Applies spring forces to animate from a starting rect to a target rect,
@@ -43,14 +39,6 @@
*/
public class RectFSpringAnim {
- /**
- * Although the rect position animation takes an indefinite amount of time since it depends on
- * the initial velocity and applied forces, scaling from the starting rect to the target rect
- * can be done in parallel at a fixed duration. Update callbacks are sent based on the progress
- * of this animation, while the end callback is sent after all animations finish.
- */
- private static final long RECT_SCALE_DURATION = 250;
-
private static final FloatPropertyCompat<RectFSpringAnim> RECT_CENTER_X =
new FloatPropertyCompat<RectFSpringAnim>("rectCenterXSpring") {
@Override
@@ -79,17 +67,17 @@
}
};
- private static final FloatProperty<RectFSpringAnim> RECT_SCALE_PROGRESS =
- new FloatProperty<RectFSpringAnim>("rectScaleProgress") {
+ private static final FloatPropertyCompat<RectFSpringAnim> RECT_SCALE_PROGRESS =
+ new FloatPropertyCompat<RectFSpringAnim>("rectScaleProgress") {
@Override
- public Float get(RectFSpringAnim anim) {
- return anim.mCurrentScaleProgress;
+ public float getValue(RectFSpringAnim object) {
+ return object.mCurrentScaleProgress;
}
@Override
- public void setValue(RectFSpringAnim anim, float currentScaleProgress) {
- anim.mCurrentScaleProgress = currentScaleProgress;
- anim.onUpdate();
+ public void setValue(RectFSpringAnim object, float value) {
+ object.mCurrentScaleProgress = value;
+ object.onUpdate();
}
};
@@ -106,7 +94,7 @@
private float mCurrentScaleProgress;
private FlingSpringAnim mRectXAnim;
private FlingSpringAnim mRectYAnim;
- private ValueAnimator mRectScaleAnim;
+ private SpringAnimation mRectScaleAnim;
private boolean mAnimsStarted;
private boolean mRectXAnimEnded;
private boolean mRectYAnimEnded;
@@ -177,17 +165,18 @@
mRectYAnim = new FlingSpringAnim(this, RECT_Y, startY, endY, startVelocityY,
mMinVisChange, minYValue, maxYValue, springVelocityFactor, onYEndListener);
- mRectScaleAnim = ObjectAnimator.ofPropertyValuesHolder(this,
- PropertyValuesHolder.ofFloat(RECT_SCALE_PROGRESS, 1))
- .setDuration(RECT_SCALE_DURATION);
- mRectScaleAnim.setInterpolator(DEACCEL);
- mRectScaleAnim.addListener(new AnimationSuccessListener() {
- @Override
- public void onAnimationSuccess(Animator animator) {
- mRectScaleAnimEnded = true;
- maybeOnEnd();
- }
- });
+ float minVisibleChange = 1f / mStartRect.height();
+ mRectScaleAnim = new SpringAnimation(this, RECT_SCALE_PROGRESS)
+ .setSpring(new SpringForce(1f)
+ .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)
+ .setStiffness(SpringForce.STIFFNESS_LOW))
+ .setStartVelocity(velocityPxPerMs.y * minVisibleChange)
+ .setMaxValue(1f)
+ .setMinimumVisibleChange(minVisibleChange)
+ .addEndListener((animation, canceled, value, velocity) -> {
+ mRectScaleAnimEnded = true;
+ maybeOnEnd();
+ });
mRectXAnim.start();
mRectYAnim.start();
@@ -202,7 +191,9 @@
if (mAnimsStarted) {
mRectXAnim.end();
mRectYAnim.end();
- mRectScaleAnim.end();
+ if (mRectScaleAnim.canSkipToEnd()) {
+ mRectScaleAnim.skipToEnd();
+ }
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index 661468a..1e1007e 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -66,7 +66,6 @@
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
@@ -77,7 +76,6 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils.ViewProgressProperty;
import com.android.launcher3.LauncherState;
import com.android.launcher3.PagedView;
@@ -95,7 +93,6 @@
import com.android.launcher3.util.PendingAnimation;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.ViewPool;
-import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.RecentsAnimationWrapper;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.RecentsModel.TaskThumbnailChangeListener;
@@ -308,8 +305,6 @@
private Layout mEmptyTextLayout;
private LiveTileOverlay mLiveTileOverlay;
- private FloatingIconView mFloatingIconView;
-
private BaseActivity.MultiWindowModeChangedListener mMultiWindowModeChangedListener =
(inMultiWindowMode) -> {
if (!inMultiWindowMode && mOverviewStateEnabled) {
@@ -1687,12 +1682,6 @@
}
}
- public FloatingIconView getFloatingIconView(Launcher launcher, View view, RectF iconLocation) {
- mFloatingIconView = FloatingIconView.getFloatingIconView(launcher, view,
- true /* hideOriginal */, iconLocation, false /* isOpening */, mFloatingIconView);
- return mFloatingIconView;
- }
-
public ClipAnimationHelper getTempClipAnimationHelper() {
return mTempClipAnimationHelper;
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
index 053b738..3364377 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
@@ -633,6 +633,7 @@
* @param progress: 0 = show icon and no insets; 1 = don't show icon and show full insets.
*/
public void setFullscreenProgress(float progress) {
+ progress = Utilities.boundToRange(progress, 0, 1);
if (progress == mFullscreenProgress) {
return;
}
diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml
index ba4ea8b..1869188 100644
--- a/quickstep/res/layout/task.xml
+++ b/quickstep/res/layout/task.xml
@@ -44,7 +44,7 @@
<FrameLayout
android:id="@+id/proactive_suggest_container"
android:layout_width="match_parent"
- android:layout_height="48dp"
+ android:layout_height="wrap_content"
android:gravity="center"
android:visibility="gone"
/>
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index e84543b..5c4d6d8 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -25,6 +25,8 @@
<string name="stats_log_manager_class" translatable="false">com.android.quickstep.logging.StatsLogCompatManager</string>
+ <string name="test_information_handler_class" translatable="false">com.android.quickstep.QuickstepTestInformationHandler</string>
+
<!-- The number of thumbnails and icons to keep in the cache. The thumbnail cache size also
determines how many thumbnails will be fetched in the background. -->
<integer name="recentsThumbnailCacheSize">3</integer>
diff --git a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
index 91c4601..95ae312 100644
--- a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
@@ -142,7 +142,6 @@
private final float mClosingWindowTransY;
private DeviceProfile mDeviceProfile;
- private FloatingIconView mFloatingView;
private RemoteAnimationProvider mRemoteAnimationProvider;
@@ -411,15 +410,15 @@
private ValueAnimator getOpeningWindowAnimators(View v, RemoteAnimationTargetCompat[] targets,
Rect windowTargetBounds, boolean toggleVisibility) {
RectF bounds = new RectF();
- mFloatingView = FloatingIconView.getFloatingIconView(mLauncher, v, toggleVisibility,
- bounds, true /* isOpening */, mFloatingView);
+ FloatingIconView floatingView = FloatingIconView.getFloatingIconView(mLauncher, v,
+ toggleVisibility, bounds, true /* isOpening */);
Rect crop = new Rect();
Matrix matrix = new Matrix();
RemoteAnimationTargetSet openingTargets = new RemoteAnimationTargetSet(targets,
MODE_OPENING);
SyncRtSurfaceTransactionApplierCompat surfaceApplier =
- new SyncRtSurfaceTransactionApplierCompat(mFloatingView);
+ new SyncRtSurfaceTransactionApplierCompat(floatingView);
openingTargets.addDependentTransactionApplier(surfaceApplier);
// Scale the app icon to take up the entire screen. This simplifies the math when
@@ -463,7 +462,7 @@
ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
appAnimator.setDuration(APP_LAUNCH_DURATION);
appAnimator.setInterpolator(LINEAR);
- appAnimator.addListener(mFloatingView);
+ appAnimator.addListener(floatingView);
appAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -557,7 +556,7 @@
} else {
currentBounds.bottom -= croppedHeight;
}
- mFloatingView.update(currentBounds, mIconAlpha.value, percent, 0f,
+ floatingView.update(currentBounds, mIconAlpha.value, percent, 0f,
cornerRadius * scale, true /* isOpening */);
} else {
matrix.setTranslate(target.position.x, target.position.y);
diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
index 17f88c9..b0acd9b 100644
--- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java
+++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
@@ -118,6 +118,8 @@
void createActivityController(long transitionLength);
+ default void adjustActivityControllerInterpolators() { }
+
default void onTransitionCancelled() { }
default void setShelfState(ShelfAnimState animState, Interpolator interpolator,
diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
new file mode 100644
index 0000000..8951363
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -0,0 +1,36 @@
+package com.android.quickstep;
+
+import android.content.Context;
+import android.os.Bundle;
+
+import com.android.launcher3.testing.TestInformationHandler;
+import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.uioverrides.states.OverviewState;
+import com.android.quickstep.util.LayoutUtils;
+
+public class QuickstepTestInformationHandler extends TestInformationHandler {
+
+ public QuickstepTestInformationHandler(Context context) { }
+
+ @Override
+ public Bundle call(String method) {
+ final Bundle response = new Bundle();
+ switch (method) {
+ case TestProtocol.REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT: {
+ final float swipeHeight =
+ OverviewState.getDefaultSwipeHeight(mDeviceProfile);
+ response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
+ return response;
+ }
+
+ case TestProtocol.REQUEST_BACKGROUND_TO_OVERVIEW_SWIPE_HEIGHT: {
+ final float swipeHeight =
+ LayoutUtils.getShelfTrackingDistance(mContext, mDeviceProfile);
+ response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
+ return response;
+ }
+ }
+
+ return super.call(method);
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/TestInformationProvider.java b/quickstep/src/com/android/quickstep/TestInformationProvider.java
deleted file mode 100644
index a948570..0000000
--- a/quickstep/src/com/android/quickstep/TestInformationProvider.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.quickstep;
-
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherState;
-import com.android.launcher3.TestProtocol;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.uioverrides.states.OverviewState;
-import com.android.quickstep.util.LayoutUtils;
-
-public class TestInformationProvider extends ContentProvider {
- @Override
- public boolean onCreate() {
- return true;
- }
-
- @Override
- public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
- return 0;
- }
-
- @Override
- public int delete(Uri uri, String s, String[] strings) {
- return 0;
- }
-
- @Override
- public Uri insert(Uri uri, ContentValues contentValues) {
- return null;
- }
-
- @Override
- public String getType(Uri uri) {
- return null;
- }
-
- @Override
- public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {
- return null;
- }
-
- @Override
- public Bundle call(String method, String arg, Bundle extras) {
- if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
- final Bundle response = new Bundle();
- final Context context = getContext();
- final DeviceProfile deviceProfile = InvariantDeviceProfile.INSTANCE.
- get(context).getDeviceProfile(context);
- final LauncherAppState launcherAppState = LauncherAppState.getInstanceNoCreate();
- final Launcher launcher = launcherAppState != null ?
- (Launcher) launcherAppState.getModel().getCallback() : null;
-
- switch (method) {
- case TestProtocol.REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT: {
- final float swipeHeight =
- OverviewState.getDefaultSwipeHeight(deviceProfile);
- response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
- break;
- }
-
- case TestProtocol.REQUEST_BACKGROUND_TO_OVERVIEW_SWIPE_HEIGHT: {
- final float swipeHeight =
- LayoutUtils.getShelfTrackingDistance(context, deviceProfile);
- response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
- break;
- }
-
- case TestProtocol.REQUEST_ALL_APPS_TO_OVERVIEW_SWIPE_HEIGHT: {
- if (launcher == null) return null;
-
- final float progress = LauncherState.OVERVIEW.getVerticalProgress(launcher)
- - LauncherState.ALL_APPS.getVerticalProgress(launcher);
- final float distance =
- launcher.getAllAppsController().getShiftRange() * progress;
- response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) distance);
- break;
- }
-
- case TestProtocol.REQUEST_HOME_TO_ALL_APPS_SWIPE_HEIGHT: {
- if (launcher == null) return null;
-
- final float progress = LauncherState.NORMAL.getVerticalProgress(launcher)
- - LauncherState.ALL_APPS.getVerticalProgress(launcher);
- final float distance =
- launcher.getAllAppsController().getShiftRange() * progress;
- response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) distance);
- break;
- }
-
- case TestProtocol.REQUEST_ENABLE_DRAG_LOGGING:
- TestProtocol.sDebugTracing = true;
- break;
-
- case TestProtocol.REQUEST_DISABLE_DRAG_LOGGING:
- TestProtocol.sDebugTracing = false;
- break;
- }
- return response;
- }
- return null;
- }
-}
diff --git a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
index 893c053..801a560 100644
--- a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
+++ b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
@@ -21,6 +21,7 @@
import com.android.launcher3.Alarm;
import com.android.launcher3.R;
+import com.android.launcher3.compat.AccessibilityManagerCompat;
/**
* Given positions along x- or y-axis, tracks velocity and acceleration and determines when there is
@@ -47,6 +48,7 @@
private final float mSpeedFast;
private final Alarm mForcePauseTimeout;
private final boolean mMakePauseHarderToTrigger;
+ private final Context mContext;
private Long mPreviousTime = null;
private Float mPreviousPosition = null;
@@ -71,6 +73,7 @@
* @param makePauseHarderToTrigger Used for gestures that require a more explicit pause.
*/
public MotionPauseDetector(Context context, boolean makePauseHarderToTrigger) {
+ mContext = context;
Resources res = context.getResources();
mSpeedVerySlow = res.getDimension(R.dimen.motion_pause_detector_speed_very_slow);
mSpeedSlow = res.getDimension(R.dimen.motion_pause_detector_speed_slow);
@@ -165,6 +168,7 @@
if (mIsPaused != isPaused) {
mIsPaused = isPaused;
if (mIsPaused) {
+ AccessibilityManagerCompat.sendPauseDetectedEventToTest(mContext);
mHasEverBeenPaused = true;
}
if (mOnMotionPauseListener != null) {
diff --git a/quickstep/tests/OWNERS b/quickstep/tests/OWNERS
new file mode 100644
index 0000000..046d871
--- /dev/null
+++ b/quickstep/tests/OWNERS
@@ -0,0 +1 @@
+vadimt@google.com
diff --git a/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java b/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java
index 5e20e56..d9fcf4d 100644
--- a/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java
+++ b/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java
@@ -68,7 +68,6 @@
// Disable app tracker
AppLaunchTracker.INSTANCE.initializeForTesting(new AppLaunchTracker());
-
PredictionUiStateManager.INSTANCE.initializeForTesting(null);
mCallback = PredictionUiStateManager.INSTANCE.get(mTargetContext).appPredictorCallback(
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 43d6311..f02859f 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -127,7 +127,7 @@
assertNotNull("OverviewTask.open returned null", task.open());
assertTrue("Test activity didn't open from Overview", mDevice.wait(Until.hasObject(
By.pkg(getAppPackageName()).text("TestActivity2")),
- LONG_WAIT_TIME_MS));
+ DEFAULT_UI_TIMEOUT));
executeOnLauncher(launcher -> assertTrue(
"Launcher activity is the top activity; expecting another activity to be the top "
+ "one",
diff --git a/res/layout/floating_icon_view.xml b/res/layout/floating_icon_view.xml
new file mode 100644
index 0000000..240c486
--- /dev/null
+++ b/res/layout/floating_icon_view.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.launcher3.views.FloatingIconView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
diff --git a/res/values/config.xml b/res/values/config.xml
index 83aea8b..638a411 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -71,6 +71,7 @@
<string name="main_process_initializer_class" translatable="false"></string>
<string name="system_shortcut_factory_class" translatable="false"></string>
<string name="app_launch_tracker_class" translatable="false"></string>
+ <string name="test_information_handler_class" translatable="false"></string>
<!-- Package name of the default wallpaper picker. -->
<string name="wallpaper_picker_package" translatable="false"></string>
@@ -86,7 +87,6 @@
<!-- View IDs to store item highlight information -->
<item type="id" name="view_unhighlight_background" />
- <item type="id" name="view_highlighted" />
<!-- Menu id for feature flags -->
<item type="id" name="menu_apply_flags" />
diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java
index 7f72242..424ffde 100644
--- a/src/com/android/launcher3/BaseActivity.java
+++ b/src/com/android/launcher3/BaseActivity.java
@@ -36,6 +36,7 @@
import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.util.SystemUiController;
+import com.android.launcher3.util.ViewCache;
import com.android.launcher3.views.ActivityContext;
import java.io.FileDescriptor;
@@ -102,6 +103,12 @@
// animation
@InvisibilityFlags private int mForceInvisible;
+ private final ViewCache mViewCache = new ViewCache();
+
+ public ViewCache getViewCache() {
+ return mViewCache;
+ }
+
@Override
public DeviceProfile getDeviceProfile() {
return mDeviceProfile;
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index ccd9e25..f69b172 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -34,6 +34,7 @@
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.shortcuts.DeepShortcutManager;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.uioverrides.DisplayRotationListener;
import com.android.launcher3.uioverrides.WallpaperColorInfo;
import com.android.launcher3.util.Themes;
@@ -134,6 +135,10 @@
public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item,
@Nullable String sourceContainer) {
+ if (TestProtocol.sDebugTracing) {
+ android.util.Log.d(TestProtocol.NO_START_TAG,
+ "startActivitySafely 1");
+ }
if (mIsSafeModeEnabled && !Utilities.isSystemApp(this, intent)) {
Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
return false;
@@ -157,6 +162,10 @@
startShortcutIntentSafely(intent, optsBundle, item, sourceContainer);
} else if (user == null || user.equals(Process.myUserHandle())) {
// Could be launching some bookkeeping activity
+ if (TestProtocol.sDebugTracing) {
+ android.util.Log.d(TestProtocol.NO_START_TAG,
+ "startActivitySafely 2");
+ }
startActivity(intent, optsBundle);
AppLaunchTracker.INSTANCE.get(this).onStartApp(intent.getComponent(),
Process.myUserHandle(), sourceContainer);
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 40eb912..711cfd2 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -29,6 +29,7 @@
import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_LAUNCHER_LOAD;
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
import static com.android.launcher3.logging.LoggerUtils.newTarget;
+import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
import static com.android.launcher3.util.RaceConditionTracker.ENTER;
import static com.android.launcher3.util.RaceConditionTracker.EXIT;
@@ -76,8 +77,6 @@
import android.view.animation.OvershootInterpolator;
import android.widget.Toast;
-import androidx.annotation.Nullable;
-
import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.allapps.AllAppsContainerView;
@@ -110,6 +109,7 @@
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.states.InternalStateHandler;
import com.android.launcher3.states.RotationHelper;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.userevent.nano.LauncherLogProto;
@@ -154,6 +154,8 @@
import java.util.List;
import java.util.function.Predicate;
+import androidx.annotation.Nullable;
+
/**
* Default launcher application.
*/
@@ -406,6 +408,7 @@
super.onEnterAnimationComplete();
UiFactory.onEnterAnimationComplete(this);
mAllAppsController.highlightWorkTabIfNecessary();
+ mRotationHelper.setCurrentTransitionRequest(REQUEST_NONE);
}
@Override
@@ -1782,6 +1785,10 @@
public boolean startActivitySafely(View v, Intent intent, ItemInfo item,
@Nullable String sourceContainer) {
+ if (TestProtocol.sDebugTracing) {
+ android.util.Log.d(TestProtocol.NO_START_TAG,
+ "startActivitySafely outer");
+ }
boolean success = super.startActivitySafely(v, intent, item, sourceContainer);
if (success && v instanceof BubbleTextView) {
// This is set to the view that launched the activity that navigated the user away
diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java
index 20eec05..49b380b 100644
--- a/src/com/android/launcher3/LauncherRootView.java
+++ b/src/com/android/launcher3/LauncherRootView.java
@@ -14,7 +14,6 @@
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewDebug;
-import android.view.WindowInsets;
import java.util.Collections;
import java.util.List;
@@ -101,7 +100,7 @@
mLauncher.getStateManager().reapplyState(true /* cancelCurrentAnimation */);
}
- return true; // I'll take it from here
+ return false; // Let children get the full insets
}
@Override
@@ -157,12 +156,6 @@
}
@Override
- public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
- mLauncher.getDragLayer().updateTouchExcludeRegion(insets);
- return super.dispatchApplyWindowInsets(insets);
- }
-
- @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
SYSTEM_GESTURE_EXCLUSION_RECT.get(0).set(l, t, r, b);
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index eff58a7..3a92dfb 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -18,13 +18,13 @@
import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO;
import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
-import static com.android.launcher3.TestProtocol.ALL_APPS_STATE_ORDINAL;
-import static com.android.launcher3.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
-import static com.android.launcher3.TestProtocol.NORMAL_STATE_ORDINAL;
-import static com.android.launcher3.TestProtocol.OVERVIEW_PEEK_STATE_ORDINAL;
-import static com.android.launcher3.TestProtocol.OVERVIEW_STATE_ORDINAL;
-import static com.android.launcher3.TestProtocol.QUICK_SWITCH_STATE_ORDINAL;
-import static com.android.launcher3.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.NORMAL_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.OVERVIEW_PEEK_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.QUICK_SWITCH_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index 49ae338..3edd838 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -48,6 +48,7 @@
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.anim.PropertySetter.AnimatedPropertySetter;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.uioverrides.UiFactory;
import java.io.PrintWriter;
@@ -447,8 +448,8 @@
}
private void onStateTransitionStart(LauncherState state) {
- if (com.android.launcher3.TestProtocol.sDebugTracing) {
- android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+ if (TestProtocol.sDebugTracing) {
+ android.util.Log.d(TestProtocol.NO_DRAG_TAG,
"onStateTransitionStart");
}
if (mState != state) {
@@ -576,8 +577,8 @@
private final AnimatorSet mAnim;
public StartAnimRunnable(AnimatorSet anim) {
- if (com.android.launcher3.TestProtocol.sDebugTracing) {
- android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+ if (TestProtocol.sDebugTracing) {
+ android.util.Log.d(TestProtocol.NO_DRAG_TAG,
"StartAnimRunnable");
}
mAnim = anim;
diff --git a/src/com/android/launcher3/ResourceUtils.java b/src/com/android/launcher3/ResourceUtils.java
index 0c80d13..73e705b 100644
--- a/src/com/android/launcher3/ResourceUtils.java
+++ b/src/com/android/launcher3/ResourceUtils.java
@@ -21,10 +21,9 @@
import android.util.TypedValue;
public class ResourceUtils {
- public static final String NAVBAR_PORTRAIT_BOTTOM_SIZE = "navigation_bar_frame_height";
public static final String NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE = "navigation_bar_width";
- public static final String NAVBAR_LANDSCAPE_BOTTOM_SIZE
- = "navigation_bar_frame_height_landscape";
+ public static final String NAVBAR_BOTTOM_GESTURE_SIZE = "navigation_bar_gesture_height";
+
public static int getNavbarSize(String resName, Resources res) {
return getDimenByName(resName, res, 48);
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index d19f9cd..f784226 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -20,8 +20,6 @@
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_TRANSITION_MS;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
-import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
-import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.SPRING_LOADED;
@@ -86,6 +84,7 @@
import com.android.launcher3.pageindicators.WorkspacePageIndicator;
import com.android.launcher3.popup.PopupContainerWithArrow;
import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.touch.WorkspaceTouchListener;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -371,8 +370,8 @@
@Override
public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
- if (com.android.launcher3.TestProtocol.sDebugTracing) {
- android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+ if (TestProtocol.sDebugTracing) {
+ android.util.Log.d(TestProtocol.NO_DRAG_TAG,
"onDragStart 1");
}
if (ENFORCE_DRAG_EVENT_ORDER) {
@@ -425,8 +424,8 @@
}
// Always enter the spring loaded mode
- if (com.android.launcher3.TestProtocol.sDebugTracing) {
- android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+ if (TestProtocol.sDebugTracing) {
+ android.util.Log.d(TestProtocol.NO_DRAG_TAG,
"onDragStart 2");
}
mLauncher.getStateManager().goToState(SPRING_LOADED);
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 41252aa..053c570 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -31,6 +31,7 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowInsets;
import com.android.launcher3.AppInfo;
import com.android.launcher3.DeviceProfile;
@@ -41,8 +42,9 @@
import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
-import com.android.launcher3.TestProtocol;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
@@ -193,11 +195,18 @@
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
+
+ // The AllAppsContainerView houses the QSB and is hence visible from the Workspace
+ // Overview states. We shouldn't intercept for the scrubber in these cases.
+ if (!mLauncher.isInState(LauncherState.ALL_APPS)) return false;
+
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
AllAppsRecyclerView rv = getActiveRecyclerView();
if (rv != null &&
rv.getScrollbar().isHitInParent(ev.getX(), ev.getY(), mFastScrollerOffset)) {
mTouchHandler = rv.getScrollbar();
+ } else {
+ mTouchHandler = null;
}
}
if (mTouchHandler != null) {
@@ -313,13 +322,22 @@
}
setLayoutParams(mlp);
- mNavBarScrimHeight = insets.bottom;
InsettableFrameLayout.dispatchInsets(this, insets);
mLauncher.getAllAppsController()
.setScrollRangeDelta(mSearchUiManager.getScrollRangeDelta(insets));
}
@Override
+ public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
+ if (Utilities.ATLEAST_Q) {
+ mNavBarScrimHeight = insets.getTappableElementInsets().bottom;
+ } else {
+ mNavBarScrimHeight = insets.getStableInsetBottom();
+ }
+ return super.dispatchApplyWindowInsets(insets);
+ }
+
+ @Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index 548d5de..a0e9dc5 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -425,7 +425,7 @@
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
- if (state == SCROLL_STATE_IDLE && Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ if (state == SCROLL_STATE_IDLE) {
AccessibilityManagerCompat.sendScrollFinishedEventToTest(getContext());
}
}
diff --git a/src/com/android/launcher3/allapps/DiscoveryBounce.java b/src/com/android/launcher3/allapps/DiscoveryBounce.java
index 1d62b43..8c59626 100644
--- a/src/com/android/launcher3/allapps/DiscoveryBounce.java
+++ b/src/com/android/launcher3/allapps/DiscoveryBounce.java
@@ -30,6 +30,9 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.LauncherStateManager;
+import com.android.launcher3.LauncherStateManager.StateListener;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.UserManagerCompat;
@@ -52,6 +55,16 @@
private final Launcher mLauncher;
private final Animator mDiscoBounceAnimation;
+ private final StateListener mStateListener = new StateListener() {
+ @Override
+ public void onStateTransitionStart(LauncherState toState) {
+ handleClose(false);
+ }
+
+ @Override
+ public void onStateTransitionComplete(LauncherState finalState) {}
+ };
+
public DiscoveryBounce(Launcher launcher, float delta) {
super(launcher, null);
mLauncher = launcher;
@@ -67,6 +80,7 @@
}
});
mDiscoBounceAnimation.addListener(controller.getProgressAnimatorListener());
+ launcher.getStateManager().addStateListener(mStateListener);
}
@Override
@@ -105,6 +119,7 @@
// Reset the all-apps progress to what ever it was previously.
mLauncher.getAllAppsController().setProgress(mLauncher.getStateManager()
.getState().getVerticalProgress(mLauncher));
+ mLauncher.getStateManager().removeStateListener(mStateListener);
}
}
diff --git a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
index 86f773f..81c95cb 100644
--- a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
+++ b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
@@ -23,7 +23,7 @@
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
-import com.android.launcher3.TestProtocol;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.Utilities;
import java.util.function.Consumer;
@@ -69,6 +69,13 @@
sendEventToTest(accessibilityManager, TestProtocol.SCROLL_FINISHED_MESSAGE, null);
}
+ public static void sendPauseDetectedEventToTest(Context context) {
+ final AccessibilityManager accessibilityManager = getAccessibilityManagerForTest(context);
+ if (accessibilityManager == null) return;
+
+ sendEventToTest(accessibilityManager, TestProtocol.PAUSE_DETECTED_MESSAGE, null);
+ }
+
private static void sendEventToTest(
AccessibilityManager accessibilityManager, String eventTag, Bundle data) {
final AccessibilityEvent e = AccessibilityEvent.obtain(
diff --git a/src/com/android/launcher3/config/BaseFlags.java b/src/com/android/launcher3/config/BaseFlags.java
index 7e20d11..54d0db1 100644
--- a/src/com/android/launcher3/config/BaseFlags.java
+++ b/src/com/android/launcher3/config/BaseFlags.java
@@ -105,7 +105,7 @@
"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(
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index bf692fe..9d3c8f7 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -41,6 +41,7 @@
import com.android.launcher3.R;
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.accessibility.DragViewStateAnnouncer;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.util.TouchController;
@@ -472,8 +473,8 @@
}
private void handleMoveEvent(int x, int y) {
- if (com.android.launcher3.TestProtocol.sDebugTracing) {
- android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+ if (TestProtocol.sDebugTracing) {
+ android.util.Log.d(TestProtocol.NO_DRAG_TAG,
"handleMoveEvent 1");
}
mDragObject.dragView.move(x, y);
@@ -492,8 +493,8 @@
if (mIsInPreDrag && mOptions.preDragCondition != null
&& mOptions.preDragCondition.shouldStartDrag(mDistanceSinceScroll)) {
- if (com.android.launcher3.TestProtocol.sDebugTracing) {
- android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+ if (TestProtocol.sDebugTracing) {
+ android.util.Log.d(TestProtocol.NO_DRAG_TAG,
"handleMoveEvent 2");
}
callOnDragStart();
@@ -533,8 +534,8 @@
* Call this from a drag source view.
*/
public boolean onControllerTouchEvent(MotionEvent ev) {
- if (com.android.launcher3.TestProtocol.sDebugTracing) {
- android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+ if (TestProtocol.sDebugTracing) {
+ android.util.Log.d(TestProtocol.NO_DRAG_TAG,
"onControllerTouchEvent");
}
if (mDragDriver == null || mOptions == null || mOptions.isAccessibleDrag) {
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index 7af12c5..d1bd2db 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -210,8 +210,7 @@
return;
}
// Load the adaptive icon on a background thread and add the view in ui thread.
- final Looper workerLooper = LauncherModel.getWorkerLooper();
- new Handler(workerLooper).postAtFrontOfQueue(new Runnable() {
+ new Handler(LauncherModel.getWorkerLooper()).postAtFrontOfQueue(new Runnable() {
@Override
public void run() {
Object[] outObj = new Object[1];
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 0a9bc72..250169c 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -102,7 +102,6 @@
private List<BubbleTextView> mCurrentPreviewItems = new ArrayList<>();
boolean mAnimating = false;
- private Rect mTempBounds = new Rect();
private float mSlop;
diff --git a/src/com/android/launcher3/states/RotationHelper.java b/src/com/android/launcher3/states/RotationHelper.java
index 3727fa6..b6c3c35 100644
--- a/src/com/android/launcher3/states/RotationHelper.java
+++ b/src/com/android/launcher3/states/RotationHelper.java
@@ -63,6 +63,10 @@
*/
private int mStateHandlerRequest = REQUEST_NONE;
/**
+ * Rotation request made by an app transition
+ */
+ private int mCurrentTransitionRequest = REQUEST_NONE;
+ /**
* Rotation request made by a Launcher State
*/
private int mCurrentStateRequest = REQUEST_NONE;
@@ -123,6 +127,13 @@
}
}
+ public void setCurrentTransitionRequest(int request) {
+ if (mCurrentTransitionRequest != request) {
+ mCurrentTransitionRequest = request;
+ notifyChange();
+ }
+ }
+
public void setCurrentStateRequest(int request) {
if (mCurrentStateRequest != request) {
mCurrentStateRequest = request;
@@ -163,6 +174,9 @@
if (mStateHandlerRequest != REQUEST_NONE) {
activityFlags = mStateHandlerRequest == REQUEST_LOCK ?
SCREEN_ORIENTATION_LOCKED : SCREEN_ORIENTATION_UNSPECIFIED;
+ } else if (mCurrentTransitionRequest != REQUEST_NONE) {
+ activityFlags = mCurrentTransitionRequest == REQUEST_LOCK ?
+ SCREEN_ORIENTATION_LOCKED : SCREEN_ORIENTATION_UNSPECIFIED;
} else if (mCurrentStateRequest == REQUEST_LOCK) {
activityFlags = SCREEN_ORIENTATION_LOCKED;
} else if (mIgnoreAutoRotateSettings || mCurrentStateRequest == REQUEST_ROTATE
diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java
new file mode 100644
index 0000000..b8476aa
--- /dev/null
+++ b/src/com/android/launcher3/testing/TestInformationHandler.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.testing;
+
+import android.content.Context;
+import android.os.Bundle;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.R;
+import com.android.launcher3.util.ResourceBasedOverride;
+
+public class TestInformationHandler implements ResourceBasedOverride {
+
+ public static TestInformationHandler newInstance(Context context) {
+ return Overrides.getObject(TestInformationHandler.class,
+ context, R.string.test_information_handler_class);
+ }
+
+ protected Context mContext;
+ protected DeviceProfile mDeviceProfile;
+ protected LauncherAppState mLauncherAppState;
+ protected Launcher mLauncher;
+
+ public void init(Context context) {
+ mContext = context;
+ mDeviceProfile = InvariantDeviceProfile.INSTANCE.
+ get(context).getDeviceProfile(context);
+ mLauncherAppState = LauncherAppState.getInstanceNoCreate();
+ mLauncher = mLauncherAppState != null ?
+ (Launcher) mLauncherAppState.getModel().getCallback() : null;
+ }
+
+ public Bundle call(String method) {
+ final Bundle response = new Bundle();
+ switch (method) {
+ case TestProtocol.REQUEST_ALL_APPS_TO_OVERVIEW_SWIPE_HEIGHT: {
+ if (mLauncher == null) return null;
+
+ final float progress = LauncherState.OVERVIEW.getVerticalProgress(mLauncher)
+ - LauncherState.ALL_APPS.getVerticalProgress(mLauncher);
+ final float distance = mLauncher.getAllAppsController().getShiftRange() * progress;
+ response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) distance);
+ break;
+ }
+
+ case TestProtocol.REQUEST_HOME_TO_ALL_APPS_SWIPE_HEIGHT: {
+ if (mLauncher == null) return null;
+
+ final float progress = LauncherState.NORMAL.getVerticalProgress(mLauncher)
+ - LauncherState.ALL_APPS.getVerticalProgress(mLauncher);
+ final float distance = mLauncher.getAllAppsController().getShiftRange() * progress;
+ response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) distance);
+ break;
+ }
+
+ case TestProtocol.REQUEST_ENABLE_DEBUG_TRACING:
+ TestProtocol.sDebugTracing = true;
+ break;
+
+ case TestProtocol.REQUEST_DISABLE_DEBUG_TRACING:
+ TestProtocol.sDebugTracing = false;
+ break;
+ }
+ return response;
+ }
+}
diff --git a/src/com/android/launcher3/testing/TestInformationProvider.java b/src/com/android/launcher3/testing/TestInformationProvider.java
new file mode 100644
index 0000000..bd177c0
--- /dev/null
+++ b/src/com/android/launcher3/testing/TestInformationProvider.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.testing;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+
+import com.android.launcher3.Utilities;
+
+public class TestInformationProvider extends ContentProvider {
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
+ return 0;
+ }
+
+ @Override
+ public int delete(Uri uri, String s, String[] strings) {
+ return 0;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues contentValues) {
+ return null;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return null;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {
+ return null;
+ }
+
+ @Override
+ public Bundle call(String method, String arg, Bundle extras) {
+ if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ TestInformationHandler handler = TestInformationHandler.newInstance(getContext());
+ handler.init(getContext());
+ return handler.call(method);
+ }
+ return null;
+ }
+}
diff --git a/src/com/android/launcher3/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
similarity index 89%
rename from src/com/android/launcher3/TestProtocol.java
rename to src/com/android/launcher3/testing/TestProtocol.java
index 081150d..a678ef2 100644
--- a/src/com/android/launcher3/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.launcher3;
+package com.android.launcher3.testing;
/**
* Protocol for custom accessibility events for communication with UI Automation tests.
@@ -25,6 +25,7 @@
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 PAUSE_DETECTED_MESSAGE = "TAPL_PAUSE_DETECTED";
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;
@@ -65,7 +66,8 @@
public static final String REQUEST_HOME_TO_ALL_APPS_SWIPE_HEIGHT =
"home-to-all-apps-swipe-height";
public static boolean sDebugTracing = false;
- public static final String REQUEST_ENABLE_DRAG_LOGGING = "enable-drag-logging";
- public static final String REQUEST_DISABLE_DRAG_LOGGING = "disable-drag-logging";
+ 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_DRAG_TAG = "b/133009122";
+ public static final String NO_START_TAG = "b/132900132";
}
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index 0650001..f858dc4 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -47,6 +47,7 @@
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIcon;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.widget.PendingAppWidgetHostView;
import com.android.launcher3.widget.WidgetAddFlowHandler;
@@ -66,14 +67,26 @@
}
private static void onClick(View v, String sourceContainer) {
+ if (TestProtocol.sDebugTracing) {
+ android.util.Log.d(TestProtocol.NO_START_TAG,
+ "onClick 1");
+ }
// Make sure that rogue clicks don't get through while allapps is launching, or after the
// view has detached (it's possible for this to happen if the view is removed mid touch).
if (v.getWindowToken() == null) {
+ if (TestProtocol.sDebugTracing) {
+ android.util.Log.d(TestProtocol.NO_START_TAG,
+ "onClick 2");
+ }
return;
}
Launcher launcher = Launcher.getLauncher(v.getContext());
if (!launcher.getWorkspace().isFinishedSwitchingState()) {
+ if (TestProtocol.sDebugTracing) {
+ android.util.Log.d(TestProtocol.NO_START_TAG,
+ "onClick 3");
+ }
return;
}
@@ -85,6 +98,10 @@
onClickFolderIcon(v);
}
} else if (tag instanceof AppInfo) {
+ if (TestProtocol.sDebugTracing) {
+ android.util.Log.d(TestProtocol.NO_START_TAG,
+ "onClick 4");
+ }
startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher,
sourceContainer == null ? CONTAINER_ALL_APPS: sourceContainer);
} else if (tag instanceof LauncherAppWidgetInfo) {
@@ -216,6 +233,10 @@
private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher,
@Nullable String sourceContainer) {
+ if (TestProtocol.sDebugTracing) {
+ android.util.Log.d(TestProtocol.NO_START_TAG,
+ "startAppShortcutOrInfoActivity");
+ }
Intent intent;
if (item instanceof PromiseAppInfo) {
PromiseAppInfo promiseAppInfo = (PromiseAppInfo) item;
diff --git a/src/com/android/launcher3/util/ViewCache.java b/src/com/android/launcher3/util/ViewCache.java
new file mode 100644
index 0000000..08b8744
--- /dev/null
+++ b/src/com/android/launcher3/util/ViewCache.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util;
+
+import android.content.Context;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * Utility class to cache views at an activity level
+ */
+public class ViewCache {
+
+ protected final SparseArray<CacheEntry> mCache = new SparseArray();
+
+ public void setCacheSize(int layoutId, int size) {
+ mCache.put(layoutId, new CacheEntry(size));
+ }
+
+ public <T extends View> T getView(int layoutId, Context context, ViewGroup parent) {
+ CacheEntry entry = mCache.get(layoutId);
+ if (entry == null) {
+ entry = new CacheEntry(1);
+ mCache.put(layoutId, entry);
+ }
+
+ if (entry.mCurrentSize > 0) {
+ entry.mCurrentSize --;
+ T result = (T) entry.mViews[entry.mCurrentSize];
+ entry.mViews[entry.mCurrentSize] = null;
+ return result;
+ }
+
+ return (T) LayoutInflater.from(context).inflate(layoutId, parent, false);
+ }
+
+ public void recycleView(int layoutId, View view) {
+ CacheEntry entry = mCache.get(layoutId);
+ if (entry != null && entry.mCurrentSize < entry.mMaxSize) {
+ entry.mViews[entry.mCurrentSize] = view;
+ entry.mCurrentSize++;
+ }
+ }
+
+ private static class CacheEntry {
+
+ final int mMaxSize;
+ final View[] mViews;
+
+ int mCurrentSize;
+
+ public CacheEntry(int maxSize) {
+ mMaxSize = maxSize;
+ mViews = new View[maxSize];
+ mCurrentSize = 0;
+ }
+ }
+}
diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java
index 4964182..939b0f2 100644
--- a/src/com/android/launcher3/views/BaseDragLayer.java
+++ b/src/com/android/launcher3/views/BaseDragLayer.java
@@ -41,6 +41,7 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.Utilities;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.launcher3.util.TouchController;
@@ -213,8 +214,8 @@
@Override
public boolean onTouchEvent(MotionEvent ev) {
- if (com.android.launcher3.TestProtocol.sDebugTracing) {
- android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+ if (TestProtocol.sDebugTracing) {
+ android.util.Log.d(TestProtocol.NO_DRAG_TAG,
"onTouchEvent " + ev);
}
int action = ev.getAction();
@@ -226,8 +227,8 @@
}
if (mActiveController != null) {
- if (com.android.launcher3.TestProtocol.sDebugTracing) {
- android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+ if (TestProtocol.sDebugTracing) {
+ android.util.Log.d(TestProtocol.NO_DRAG_TAG,
"onTouchEvent 1");
}
return mActiveController.onControllerTouchEvent(ev);
@@ -495,12 +496,14 @@
}
}
+ @Override
@TargetApi(Build.VERSION_CODES.Q)
- public void updateTouchExcludeRegion(WindowInsets insets) {
+ public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
if (Utilities.ATLEAST_Q) {
Insets gestureInsets = insets.getMandatorySystemGestureInsets();
mSystemGestureRegion.set(gestureInsets.left, gestureInsets.top,
gestureInsets.right, gestureInsets.bottom);
}
+ return super.dispatchApplyWindowInsets(insets);
}
}
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index 3d5877a..03cbb21 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -20,6 +20,7 @@
import static com.android.launcher3.Utilities.mapToRange;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.config.FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM;
+import static com.android.launcher3.states.RotationHelper.REQUEST_LOCK;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -27,6 +28,7 @@
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
+import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Outline;
@@ -39,7 +41,7 @@
import android.os.Build;
import android.os.CancellationSignal;
import android.os.Handler;
-import android.os.Looper;
+import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
@@ -148,12 +150,20 @@
private final SpringAnimation mFgSpringX;
private float mFgTransX;
- private FloatingIconView(Launcher launcher) {
- super(launcher);
- mLauncher = launcher;
+ public FloatingIconView(Context context) {
+ this(context, null);
+ }
+
+ public FloatingIconView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public FloatingIconView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ mLauncher = Launcher.getLauncher(context);
mBlurSizeOutline = getResources().getDimensionPixelSize(
R.dimen.blur_size_medium_outline);
- mListenerView = new ListenerView(launcher, null);
+ mListenerView = new ListenerView(context, attrs);
mFgSpringX = new SpringAnimation(this, mFgTransXProperty)
.setSpring(new SpringForce()
@@ -169,6 +179,7 @@
protected void onAttachedToWindow() {
super.onAttachedToWindow();
getViewTreeObserver().addOnGlobalLayoutListener(this);
+ mLauncher.getRotationHelper().setCurrentTransitionRequest(REQUEST_LOCK);
}
@Override
@@ -350,6 +361,7 @@
}
@WorkerThread
+ @SuppressWarnings("WrongThread")
private void getIcon(View v, ItemInfo info, boolean isOpening,
Runnable onIconLoadedRunnable, CancellationSignal loadIconSignal) {
final LayoutParams lp = (LayoutParams) getLayoutParams();
@@ -396,7 +408,7 @@
&& finalDrawable instanceof AdaptiveIconDrawable;
int iconOffset = getOffsetForIconBounds(finalDrawable);
- new Handler(Looper.getMainLooper()).post(() -> {
+ mLauncher.getMainExecutor().execute(() -> {
if (isAdaptiveIcon) {
mIsAdaptiveIcon = true;
boolean isFolderIcon = finalDrawable instanceof FolderAdaptiveIcon;
@@ -505,6 +517,7 @@
}
@WorkerThread
+ @SuppressWarnings("WrongThread")
private int getOffsetForIconBounds(Drawable drawable) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O ||
!(drawable instanceof AdaptiveIconDrawable)) {
@@ -515,7 +528,7 @@
Rect bounds = new Rect(0, 0, lp.width + mBlurSizeOutline, lp.height + mBlurSizeOutline);
bounds.inset(mBlurSizeOutline / 2, mBlurSizeOutline / 2);
- try (LauncherIcons li = LauncherIcons.obtain(getContext())) {
+ try (LauncherIcons li = LauncherIcons.obtain(mLauncher)) {
Utilities.scaleRectAboutCenter(bounds, li.getNormalizer().getScale(drawable, null));
}
@@ -604,11 +617,14 @@
* @param isOpening True if this view replaces the icon for app open animation.
*/
public static FloatingIconView getFloatingIconView(Launcher launcher, View originalView,
- boolean hideOriginal, RectF positionOut, boolean isOpening, FloatingIconView recycle) {
- if (recycle != null) {
- recycle.recycle();
- }
- FloatingIconView view = recycle != null ? recycle : new FloatingIconView(launcher);
+ boolean hideOriginal, RectF positionOut, boolean isOpening) {
+ final DragLayer dragLayer = launcher.getDragLayer();
+ ViewGroup parent = (ViewGroup) dragLayer.getParent();
+
+ FloatingIconView view = launcher.getViewCache().getView(R.layout.floating_icon_view,
+ launcher, parent);
+ view.recycle();
+
view.mIsVerticalBarLayout = launcher.getDeviceProfile().isVerticalBarLayout();
view.mOriginalIcon = originalView;
@@ -633,9 +649,8 @@
}
// We need to add it to the overlay, but keep it invisible until animation starts..
- final DragLayer dragLayer = launcher.getDragLayer();
view.setVisibility(INVISIBLE);
- ((ViewGroup) dragLayer.getParent()).addView(view);
+ parent.addView(view);
dragLayer.addView(view.mListenerView);
view.mListenerView.setListener(view::onListenerViewClosed);
@@ -714,6 +729,7 @@
((ViewGroup) dragLayer.getParent()).removeView(this);
dragLayer.removeView(mListenerView);
recycle();
+ mLauncher.getViewCache().recycleView(R.layout.floating_icon_view, this);
}
private void recycle() {
diff --git a/tests/Android.mk b/tests/Android.mk
index 0991a04..978209f 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -32,7 +32,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, tapl) \
../src/com/android/launcher3/ResourceUtils.java \
../src/com/android/launcher3/util/SecureSettingsObserver.java \
- ../src/com/android/launcher3/TestProtocol.java
+ ../src/com/android/launcher3/testing/TestProtocol.java
endif
LOCAL_MODULE := ub-launcher-aosp-tapl
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index 75ff66e..61c7306 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -184,5 +184,13 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity-alias>
+ <activity-alias android:name="Activity11"
+ android:label="TestActivity11"
+ android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity-alias>
</application>
</manifest>
diff --git a/tests/OWNERS b/tests/OWNERS
new file mode 100644
index 0000000..046d871
--- /dev/null
+++ b/tests/OWNERS
@@ -0,0 +1 @@
+vadimt@google.com
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 74cece8..44401c7 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -54,6 +54,7 @@
import com.android.launcher3.ResourceUtils;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.tapl.TestHelpers;
import com.android.launcher3.util.Wait;
@@ -91,7 +92,6 @@
public static final long SHORT_UI_TIMEOUT = 300;
public static final long DEFAULT_UI_TIMEOUT = 10000;
- protected static final int LONG_WAIT_TIME_MS = 60000;
private static final String TAG = "AbstractLauncherUiTest";
private static int sScreenshotCount = 0;
@@ -198,6 +198,9 @@
@Before
public void setUp() throws Exception {
+ // Disable app tracker
+ AppLaunchTracker.INSTANCE.initializeForTesting(new AppLaunchTracker());
+
mTargetContext = InstrumentationRegistry.getTargetContext();
mTargetPackage = mTargetContext.getPackageName();
// Unlock the phone
@@ -243,7 +246,7 @@
*/
protected UiObject2 scrollAndFind(UiObject2 container, BySelector condition) {
final int margin = ResourceUtils.getNavbarSize(
- ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE, mLauncher.getResources()) + 1;
+ ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE, mLauncher.getResources()) + 1;
container.setGestureMargins(0, 0, 0, margin);
int i = 0;
@@ -394,7 +397,7 @@
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
instrumentation.getTargetContext().startActivity(intent);
assertTrue(packageName + " didn't start",
- mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), LONG_WAIT_TIME_MS));
+ mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), DEFAULT_UI_TIMEOUT));
}
protected void startTestActivity(int activityNumber) {
@@ -410,7 +413,7 @@
assertTrue(packageName + " didn't start",
mDevice.wait(
Until.hasObject(By.pkg(packageName).text("TestActivity" + activityNumber)),
- LONG_WAIT_TIME_MS));
+ DEFAULT_UI_TIMEOUT));
}
protected static String resolveSystemApp(String category) {
diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java
index 70405fe..18a8f27 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java
@@ -27,7 +27,7 @@
import androidx.test.uiautomator.UiObject2;
import com.android.launcher3.ResourceUtils;
-import com.android.launcher3.TestProtocol;
+import com.android.launcher3.testing.TestProtocol;
/**
* Operations on AllApps opened from Home. Also a parent for All Apps opened from Overview.
@@ -97,7 +97,7 @@
0,
getSearchBox(allAppsContainer).getVisibleBounds().bottom + 1,
0,
- ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE,
+ ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE,
mLauncher.getResources()) + 1);
final BySelector appIconSelector = AppIcon.getAppIconSelector(appName, mLauncher);
if (!hasClickableIcon(allAppsContainer, appListRecycler, appIconSelector)) {
diff --git a/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java b/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java
index a472d31..f48d4dd 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java
@@ -16,14 +16,14 @@
package com.android.launcher3.tapl;
-import static com.android.launcher3.TestProtocol.OVERVIEW_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL;
import android.graphics.Point;
import androidx.annotation.NonNull;
import androidx.test.uiautomator.UiObject2;
-import com.android.launcher3.TestProtocol;
+import com.android.launcher3.testing.TestProtocol;
/**
* Operations on AllApps opened from Overview.
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index 55e14cc..ce95298 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -16,7 +16,7 @@
package com.android.launcher3.tapl;
-import static com.android.launcher3.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
import android.graphics.Point;
import android.os.SystemClock;
@@ -24,7 +24,7 @@
import androidx.annotation.NonNull;
-import com.android.launcher3.TestProtocol;
+import com.android.launcher3.testing.TestProtocol;
/**
* Indicates the base state with a UI other than Overview running as foreground. It can also
@@ -32,7 +32,6 @@
*/
public class Background extends LauncherInstrumentation.VisibleContainer {
private static final int ZERO_BUTTON_SWIPE_UP_GESTURE_DURATION = 500;
- private static final int ZERO_BUTTON_SWIPE_UP_HOLD_DURATION = 400;
Background(LauncherInstrumentation launcher) {
super(launcher);
@@ -72,9 +71,15 @@
final long downTime = SystemClock.uptimeMillis();
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, start);
- mLauncher.movePointer(
- downTime, downTime, ZERO_BUTTON_SWIPE_UP_GESTURE_DURATION, start, end);
- LauncherInstrumentation.sleep(ZERO_BUTTON_SWIPE_UP_HOLD_DURATION);
+ mLauncher.executeAndWaitForEvent(
+ () -> mLauncher.movePointer(
+ downTime,
+ downTime,
+ ZERO_BUTTON_SWIPE_UP_GESTURE_DURATION,
+ start,
+ end),
+ event -> TestProtocol.PAUSE_DETECTED_MESSAGE.equals(event.getClassName()),
+ "Pause wasn't detected");
mLauncher.sendPointer(
downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, end);
break;
@@ -89,7 +94,7 @@
mLauncher.swipeToState(
centerX, startY, centerX,
startY - swipeHeight - mLauncher.getTouchSlop(),
- 60,
+ 10,
expectedState);
break;
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Home.java b/tests/tapl/com/android/launcher3/tapl/Home.java
index 20c116c..cfc4374 100644
--- a/tests/tapl/com/android/launcher3/tapl/Home.java
+++ b/tests/tapl/com/android/launcher3/tapl/Home.java
@@ -16,7 +16,7 @@
package com.android.launcher3.tapl;
-import static com.android.launcher3.TestProtocol.OVERVIEW_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL;
import androidx.annotation.NonNull;
diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index 1b372ec..4261988 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -24,10 +24,13 @@
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
+import com.android.launcher3.testing.TestProtocol;
+
/**
* Ancestor for AppIcon and AppMenuItem.
*/
abstract class Launchable {
+ private static final int WAIT_TIME_MS = 60000;
protected final LauncherInstrumentation mLauncher;
protected final UiObject2 mObject;
@@ -51,9 +54,11 @@
private Background launch(BySelector selector) {
LauncherInstrumentation.log("Launchable.launch before click " +
mObject.getVisibleCenter());
+ mLauncher.getTestInfo(TestProtocol.REQUEST_ENABLE_DEBUG_TRACING);
mLauncher.assertTrue(
"Launching an app didn't open a new window: " + mObject.getText(),
- mObject.clickAndWait(Until.newWindow(), LauncherInstrumentation.WAIT_TIME_MS));
+ mObject.clickAndWait(Until.newWindow(), WAIT_TIME_MS));
+ mLauncher.getTestInfo(TestProtocol.REQUEST_DISABLE_DEBUG_TRACING);
mLauncher.assertTrue(
"App didn't start: " + selector,
mLauncher.getDevice().wait(Until.hasObject(selector),
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index a4711f5..a442e2b 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -16,16 +16,23 @@
package com.android.launcher3.tapl;
-import static com.android.launcher3.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
-import static com.android.launcher3.TestProtocol.NORMAL_STATE_ORDINAL;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.content.pm.PackageManager.DONT_KILL_APP;
+import static android.content.pm.PackageManager.MATCH_ALL;
+import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
+
+import static com.android.launcher3.testing.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.NORMAL_STATE_ORDINAL;
import static com.android.launcher3.tapl.TestHelpers.getOverviewPackageName;
import android.app.ActivityManager;
import android.app.Instrumentation;
import android.app.UiAutomation;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
@@ -53,7 +60,7 @@
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
-import com.android.launcher3.TestProtocol;
+import com.android.launcher3.testing.TestProtocol;
import com.android.systemui.shared.system.QuickStepContract;
import org.junit.Assert;
@@ -115,7 +122,7 @@
private static final String APPS_RES_ID = "apps_view";
private static final String OVERVIEW_RES_ID = "overview_panel";
private static final String WIDGETS_RES_ID = "widgets_list_view";
- public static final int WAIT_TIME_MS = 60000;
+ public static final int WAIT_TIME_MS = 10000;
private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
private static WeakReference<VisibleContainer> sActiveContainer = new WeakReference<>(null);
@@ -149,9 +156,10 @@
getLauncherPackageName() :
targetPackage;
+ String testProviderAuthority = authorityPackage + ".TestInfo";
mTestProviderUri = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
- .authority(authorityPackage + ".TestInfo")
+ .authority(testProviderAuthority)
.build();
try {
@@ -160,6 +168,25 @@
} catch (IOException e) {
fail(e.toString());
}
+
+
+ PackageManager pm = getContext().getPackageManager();
+ ProviderInfo pi = pm.resolveContentProvider(
+ testProviderAuthority, MATCH_ALL | MATCH_DISABLED_COMPONENTS);
+ ComponentName cn = new ComponentName(pi.packageName, pi.name);
+
+ if (pm.getComponentEnabledSetting(cn) != COMPONENT_ENABLED_STATE_ENABLED) {
+ if (TestHelpers.isInLauncherProcess()) {
+ getContext().getPackageManager().setComponentEnabledSetting(
+ cn, COMPONENT_ENABLED_STATE_ENABLED, DONT_KILL_APP);
+ } else {
+ try {
+ mDevice.executeShellCommand("pm enable " + cn.flattenToString());
+ } catch (IOException e) {
+ fail(e.toString());
+ }
+ }
+ }
}
Context getContext() {
@@ -337,7 +364,7 @@
}
}
- private Parcelable executeAndWaitForEvent(Runnable command,
+ Parcelable executeAndWaitForEvent(Runnable command,
UiAutomation.AccessibilityEventFilter eventFilter, String message) {
try {
final AccessibilityEvent event =
@@ -541,25 +568,22 @@
@NonNull
UiObject2 waitForLauncherObject(String resName) {
- final BySelector selector = getLauncherObjectSelector(resName);
- final UiObject2 object = mDevice.wait(Until.findObject(selector), WAIT_TIME_MS);
- assertNotNull("Can't find a launcher object; selector: " + selector, object);
- return object;
+ return waitForObjectBySelector(getLauncherObjectSelector(resName));
}
@NonNull
UiObject2 waitForLauncherObjectByClass(String clazz) {
- final BySelector selector = getLauncherObjectSelectorByClass(clazz);
- final UiObject2 object = mDevice.wait(Until.findObject(selector), WAIT_TIME_MS);
- assertNotNull("Can't find a launcher object; selector: " + selector, object);
- return object;
+ return waitForObjectBySelector(getLauncherObjectSelectorByClass(clazz));
}
@NonNull
UiObject2 waitForFallbackLauncherObject(String resName) {
- final BySelector selector = getFallbackLauncherObjectSelector(resName);
+ return waitForObjectBySelector(getFallbackLauncherObjectSelector(resName));
+ }
+
+ private UiObject2 waitForObjectBySelector(BySelector selector) {
final UiObject2 object = mDevice.wait(Until.findObject(selector), WAIT_TIME_MS);
- assertNotNull("Can't find a fallback launcher object; selector: " + selector, object);
+ assertNotNull("Can't find a launcher object; selector: " + selector, object);
return object;
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Overview.java b/tests/tapl/com/android/launcher3/tapl/Overview.java
index ec99d26..058831f 100644
--- a/tests/tapl/com/android/launcher3/tapl/Overview.java
+++ b/tests/tapl/com/android/launcher3/tapl/Overview.java
@@ -16,7 +16,7 @@
package com.android.launcher3.tapl;
-import static com.android.launcher3.TestProtocol.ALL_APPS_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL;
import androidx.annotation.NonNull;
import androidx.test.uiautomator.UiObject2;
@@ -51,10 +51,9 @@
// Swipe from an app icon to the top.
LauncherInstrumentation.log("Overview.switchToAllApps before swipe");
- final UiObject2 appIcon = mLauncher.waitForLauncherObjectByClass(
- "android.widget.TextView");
+ final UiObject2 allApps = mLauncher.waitForLauncherObject("apps_view");
mLauncher.swipeToState(mLauncher.getDevice().getDisplayWidth() / 2,
- appIcon.getVisibleBounds().centerY(),
+ allApps.getVisibleBounds().top,
mLauncher.getDevice().getDisplayWidth() / 2,
0, 50, ALL_APPS_STATE_ORDINAL);
diff --git a/tests/tapl/com/android/launcher3/tapl/Widgets.java b/tests/tapl/com/android/launcher3/tapl/Widgets.java
index b780df4..94003be 100644
--- a/tests/tapl/com/android/launcher3/tapl/Widgets.java
+++ b/tests/tapl/com/android/launcher3/tapl/Widgets.java
@@ -41,7 +41,7 @@
LauncherInstrumentation.log("Widgets.flingForward enter");
final UiObject2 widgetsContainer = verifyActiveContainer();
widgetsContainer.setGestureMargins(0, 0, 0,
- ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE,
+ ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE,
mLauncher.getResources()) + 1);
widgetsContainer.fling(Direction.DOWN,
(int) (FLING_SPEED * mLauncher.getDisplayDensity()));
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index f1dd013..7dcc426 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -16,7 +16,7 @@
package com.android.launcher3.tapl;
-import static com.android.launcher3.TestProtocol.ALL_APPS_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL;
import static junit.framework.TestCase.assertTrue;
@@ -30,7 +30,7 @@
import androidx.test.uiautomator.Direction;
import androidx.test.uiautomator.UiObject2;
-import com.android.launcher3.TestProtocol;
+import com.android.launcher3.testing.TestProtocol;
/**
* Operations on the workspace screen.
@@ -148,7 +148,7 @@
static void dragIconToWorkspace(
LauncherInstrumentation launcher, Launchable launchable, Point dest,
String longPressIndicator) {
- launcher.getTestInfo(TestProtocol.REQUEST_ENABLE_DRAG_LOGGING);
+ launcher.getTestInfo(TestProtocol.REQUEST_ENABLE_DEBUG_TRACING);
LauncherInstrumentation.log("dragIconToWorkspace: begin");
final Point launchableCenter = launchable.getObject().getVisibleCenter();
final long downTime = SystemClock.uptimeMillis();
@@ -163,7 +163,7 @@
downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, dest);
LauncherInstrumentation.log("dragIconToWorkspace: end");
launcher.waitUntilGone("drop_target_bar");
- launcher.getTestInfo(TestProtocol.REQUEST_DISABLE_DRAG_LOGGING);
+ launcher.getTestInfo(TestProtocol.REQUEST_DISABLE_DEBUG_TRACING);
}
/**