Merge "Moving all-apps predictions to Launcher model" into ub-launcher3-master
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 23a0529..43dba85 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -246,10 +246,8 @@
switch (state.ordinal) {
case HINT_STATE_ORDINAL: {
Workspace workspace = getWorkspace();
- boolean willMoveScreens = workspace.getNextPage() != Workspace.DEFAULT_PAGE;
- getStateManager().goToState(NORMAL, true,
- willMoveScreens ? null : getScrimView()::startDragHandleEducationAnim);
- if (willMoveScreens) {
+ getStateManager().goToState(NORMAL);
+ if (workspace.getNextPage() != Workspace.DEFAULT_PAGE) {
workspace.post(workspace::moveToDefaultScreen);
}
break;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/AbsSwipeUpHandler.java
similarity index 82%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/AbsSwipeUpHandler.java
index 411d74f..f371145 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -15,6 +15,8 @@
*/
package com.android.quickstep;
+import static android.widget.Toast.LENGTH_SHORT;
+
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
@@ -29,7 +31,9 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_LEFT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_RIGHT;
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
+import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
import static com.android.quickstep.GestureState.GestureEndTarget.HOME;
import static com.android.quickstep.GestureState.GestureEndTarget.LAST_TASK;
import static com.android.quickstep.GestureState.GestureEndTarget.NEW_TASK;
@@ -51,13 +55,17 @@
import android.content.Context;
import android.content.Intent;
import android.graphics.PointF;
+import android.graphics.Rect;
import android.os.Build;
import android.os.SystemClock;
+import android.util.Log;
+import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnApplyWindowInsetsListener;
import android.view.ViewTreeObserver.OnDrawListener;
import android.view.WindowInsets;
import android.view.animation.Interpolator;
+import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
@@ -73,17 +81,24 @@
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.util.TraceHelper;
+import com.android.launcher3.util.VibratorWrapper;
+import com.android.launcher3.util.WindowBounds;
import com.android.quickstep.BaseActivityInterface.AnimationFactory;
import com.android.quickstep.GestureState.GestureEndTarget;
import com.android.quickstep.inputconsumers.OverviewInputConsumer;
import com.android.quickstep.util.ActiveGestureLog;
+import com.android.quickstep.util.ActivityInitListener;
+import com.android.quickstep.util.InputConsumerProxy;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.ShelfPeekAnim;
import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
+import com.android.quickstep.util.SurfaceTransactionApplier;
+import com.android.quickstep.util.TransformParams;
import com.android.quickstep.views.LiveTileOverlay;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
@@ -95,17 +110,34 @@
import com.android.systemui.shared.system.TaskInfoCompat;
import com.android.systemui.shared.system.TaskStackChangeListener;
+import java.util.ArrayList;
+import java.util.function.Consumer;
+
/**
* Handles the navigation gestures when Launcher is the default home activity.
- * TODO: Merge this with BaseSwipeUpHandler
*/
-@TargetApi(Build.VERSION_CODES.O)
-public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q extends RecentsView>
- extends BaseSwipeUpHandler<T, Q> implements OnApplyWindowInsetsListener {
- private static final String TAG = BaseSwipeUpHandlerV2.class.getSimpleName();
+@TargetApi(Build.VERSION_CODES.R)
+public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends RecentsView>
+ extends SwipeUpAnimationLogic implements OnApplyWindowInsetsListener,
+ RecentsAnimationCallbacks.RecentsAnimationListener {
+ private static final String TAG = "AbsSwipeUpHandler";
private static final String[] STATE_NAMES = DEBUG_STATES ? new String[16] : null;
+ protected final BaseActivityInterface<?, T> mActivityInterface;
+ protected final InputConsumerProxy mInputConsumerProxy;
+ protected final ActivityInitListener mActivityInitListener;
+ // Callbacks to be made once the recents animation starts
+ private final ArrayList<Runnable> mRecentsAnimationStartCallbacks = new ArrayList<>();
+ protected RecentsAnimationController mRecentsAnimationController;
+ protected RecentsAnimationTargets mRecentsAnimationTargets;
+ protected T mActivity;
+ protected Q mRecentsView;
+ protected Runnable mGestureEndCallback;
+ protected MultiStateCallback mStateCallback;
+ protected boolean mCanceled;
+ private boolean mRecentsViewScrollLinked = false;
+
private static int getFlagForIndex(int index, String name) {
if (DEBUG_STATES) {
STATE_NAMES[index] = name;
@@ -201,11 +233,15 @@
private final Runnable mOnDeferredActivityLaunch = this::onDeferredActivityLaunch;
- public BaseSwipeUpHandlerV2(Context context, RecentsAnimationDeviceState deviceState,
+ public AbsSwipeUpHandler(Context context, RecentsAnimationDeviceState deviceState,
TaskAnimationManager taskAnimationManager, GestureState gestureState,
long touchTimeMs, boolean continuingLastGesture,
InputConsumerController inputConsumer) {
- super(context, deviceState, gestureState, inputConsumer);
+ super(context, deviceState, gestureState, new TransformParams());
+ mActivityInterface = gestureState.getActivityInterface();
+ mActivityInitListener = mActivityInterface.createActivityInitListener(this::onActivityInit);
+ mInputConsumerProxy =
+ new InputConsumerProxy(inputConsumer, this::createNewInputProxyHandler);
mTaskAnimationManager = taskAnimationManager;
mTouchTimeMs = touchTimeMs;
mContinuingLastGesture = continuingLastGesture;
@@ -274,9 +310,17 @@
}
}
- @Override
protected boolean onActivityInit(Boolean alreadyOnHome) {
- super.onActivityInit(alreadyOnHome);
+ T createdActivity = mActivityInterface.getCreatedActivity();
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.PAUSE_NOT_DETECTED, "BaseSwipeUpHandler.1");
+ }
+ if (createdActivity != null) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.PAUSE_NOT_DETECTED, "BaseSwipeUpHandler.2");
+ }
+ initTransitionEndpoints(createdActivity.getDeviceProfile());
+ }
final T activity = mActivityInterface.getCreatedActivity();
if (mActivity == activity) {
return true;
@@ -315,7 +359,9 @@
return true;
}
- @Override
+ /**
+ * Return true if the window should be translated horizontally if the recents view scrolls
+ */
protected boolean moveWindowWithRecentsScroll() {
return mGestureState.getEndTarget() != HOME;
}
@@ -394,7 +440,7 @@
mGestureState.runOnceAtState(STATE_END_TARGET_SET,
() -> mDeviceState.getRotationTouchHelper().
onEndTargetCalculated(mGestureState.getEndTarget(),
- mActivityInterface));
+ mActivityInterface));
notifyGestureStartedAsync();
}
@@ -444,7 +490,9 @@
.getHighResLoadingState().setVisible(true);
}
- @Override
+ /**
+ * Called when motion pause is detected
+ */
public void onMotionPauseChanged(boolean isPaused) {
setShelfState(isPaused ? PEEK : HIDE, ShelfPeekAnim.INTERPOLATOR, ShelfPeekAnim.DURATION);
}
@@ -482,7 +530,6 @@
mAnimationFactory.setRecentsAttachedToAppWindow(recentsAttachedToAppWindow, animate);
}
- @Override
public void setIsLikelyToStartNewTask(boolean isLikelyToStartNewTask) {
setIsLikelyToStartNewTask(isLikelyToStartNewTask, true /* animate */);
}
@@ -538,11 +585,14 @@
updateLauncherTransitionProgress();
}
- @Override
public Intent getLaunchIntent() {
return mGestureState.getOverviewIntent();
}
+ /**
+ * Called when the value of {@link #mCurrentShift} changes
+ */
+ @UiThread
@Override
public void updateFinalShift() {
final boolean passed = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW;
@@ -603,7 +653,41 @@
public void onRecentsAnimationStart(RecentsAnimationController controller,
RecentsAnimationTargets targets) {
ActiveGestureLog.INSTANCE.addLog("startRecentsAnimationCallback", targets.apps.length);
- super.onRecentsAnimationStart(controller, targets);
+ mRecentsAnimationController = controller;
+ mRecentsAnimationTargets = targets;
+ mTransformParams.setTargetSet(mRecentsAnimationTargets);
+ RemoteAnimationTargetCompat runningTaskTarget = targets.findTask(
+ mGestureState.getRunningTaskId());
+
+ if (runningTaskTarget != null) {
+ mTaskViewSimulator.setPreview(runningTaskTarget);
+ }
+
+ // Only initialize the device profile, if it has not been initialized before, as in some
+ // configurations targets.homeContentInsets may not be correct.
+ if (mActivity == null) {
+ DeviceProfile dp = mTaskViewSimulator.getOrientationState().getLauncherDeviceProfile();
+ if (targets.minimizedHomeBounds != null && runningTaskTarget != null) {
+ Rect overviewStackBounds = mActivityInterface
+ .getOverviewWindowBounds(targets.minimizedHomeBounds, runningTaskTarget);
+ dp = dp.getMultiWindowProfile(mContext,
+ new WindowBounds(overviewStackBounds, targets.homeContentInsets));
+ } else {
+ // If we are not in multi-window mode, home insets should be same as system insets.
+ dp = dp.copy(mContext);
+ }
+ dp.updateInsets(targets.homeContentInsets);
+ dp.updateIsSeascape(mContext);
+ initTransitionEndpoints(dp);
+ }
+
+ // Notify when the animation starts
+ if (!mRecentsAnimationStartCallbacks.isEmpty()) {
+ for (Runnable action : new ArrayList<>(mRecentsAnimationStartCallbacks)) {
+ action.run();
+ }
+ mRecentsAnimationStartCallbacks.clear();
+ }
// Only add the callback to enable the input consumer after we actually have the controller
mStateCallback.runOnceAtState(STATE_APP_CONTROLLER_RECEIVED | STATE_GESTURE_STARTED,
@@ -620,10 +704,14 @@
mStateCallback.setStateOnUiThread(STATE_GESTURE_CANCELLED | STATE_HANDLER_INVALIDATED);
// Defer clearing the controller and the targets until after we've updated the state
- super.onRecentsAnimationCanceled(thumbnailData);
+ mRecentsAnimationController = null;
+ mRecentsAnimationTargets = null;
+ if (mRecentsView != null) {
+ mRecentsView.setRecentsAnimationTargets(null, null);
+ }
}
- @Override
+ @UiThread
public void onGestureStarted(boolean isLikelyToStartNewTask) {
notifyGestureStartedAsync();
setIsLikelyToStartNewTask(isLikelyToStartNewTask, false /* animate */);
@@ -647,7 +735,7 @@
/**
* Called as a result on ACTION_CANCEL to return the UI to the start state.
*/
- @Override
+ @UiThread
public void onGestureCancelled() {
updateDisplacement(0);
mStateCallback.setStateOnUiThread(STATE_GESTURE_COMPLETED);
@@ -660,7 +748,7 @@
* @param velocity The x and y components of the velocity when the gesture ends.
* @param downPos The x and y value of where the gesture started.
*/
- @Override
+ @UiThread
public void onGestureEnded(float endVelocity, PointF velocity, PointF downPos) {
float flingThreshold = mContext.getResources()
.getDimension(R.dimen.quickstep_fling_threshold_velocity);
@@ -678,7 +766,10 @@
handleNormalGestureEnd(endVelocity, isFling, velocity, false /* isCancel */);
}
- @Override
+ /**
+ * Called to create a input proxy for the running task
+ */
+ @UiThread
protected InputConsumer createNewInputProxyHandler() {
endRunningWindowAnim(mGestureState.getEndTarget() == HOME /* cancel */);
endLauncherTransitionController();
@@ -719,7 +810,7 @@
ActiveGestureLog.INSTANCE.addLog("onSettledOnEndTarget " + mGestureState.getEndTarget());
}
- @Override
+ /** @return Whether this was the task we were waiting to appear, and thus handled it. */
protected boolean handleTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {
if (mStateCallback.hasStates(STATE_HANDLER_INVALIDATED)) {
return false;
@@ -1081,7 +1172,6 @@
anim.addAnimatorListener(new AnimationSuccessListener() {
@Override
public void onAnimationStart(Animator animation) {
- super.onAnimationStart(animation);
if (mActivity != null) {
removeLiveTileOverlay();
}
@@ -1097,10 +1187,12 @@
mActivityInterface.onSwipeUpToHomeComplete(mDeviceState);
}
});
+ if (mRecentsAnimationTargets != null) {
+ mRecentsAnimationTargets.addReleaseCheck(anim);
+ }
return anim;
}
- @Override
public void onConsumerAboutToBeSwitched() {
if (mActivity != null) {
// In the off chance that the gesture ends before Launcher is started, we should clear
@@ -1151,9 +1243,19 @@
});
}
- @Override
+ /**
+ * Called when we successfully startNewTask() on the task that was previously running. Normally
+ * we call resumeLastTask() when returning to the previously running task, but this handles a
+ * specific edge case: if we switch from A to B, and back to A before B appears, we need to
+ * start A again to ensure it stays on top.
+ */
+ @androidx.annotation.CallSuper
protected void onRestartPreviouslyAppearedTask() {
- super.onRestartPreviouslyAppearedTask();
+ // Finish the controller here, since we won't get onTaskAppeared() for a task that already
+ // appeared.
+ if (mRecentsAnimationController != null) {
+ mRecentsAnimationController.finish(false, null);
+ }
reset();
}
@@ -1258,7 +1360,7 @@
// new thumbnail
finishTransitionPosted = ViewUtils.postDraw(taskView,
() -> mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED),
- this::isCanceled);
+ this::isCanceled);
}
}
if (!finishTransitionPosted) {
@@ -1327,4 +1429,172 @@
return app.isNotInRecents
|| app.activityType == ACTIVITY_TYPE_HOME;
}
+
+ /**
+ * To be called at the end of constructor of subclasses. This calls various methods which can
+ * depend on proper class initialization.
+ */
+ protected void initAfterSubclassConstructor() {
+ initTransitionEndpoints(
+ mTaskViewSimulator.getOrientationState().getLauncherDeviceProfile());
+ }
+
+ protected void performHapticFeedback() {
+ VibratorWrapper.INSTANCE.get(mContext).vibrate(OVERVIEW_HAPTIC);
+ }
+
+ public Consumer<MotionEvent> getRecentsViewDispatcher(float navbarRotation) {
+ return mRecentsView != null ? mRecentsView.getEventDispatcher(navbarRotation) : null;
+ }
+
+ public void setGestureEndCallback(Runnable gestureEndCallback) {
+ mGestureEndCallback = gestureEndCallback;
+ }
+
+ protected void linkRecentsViewScroll() {
+ SurfaceTransactionApplier.create(mRecentsView, applier -> {
+ mTransformParams.setSyncTransactionApplier(applier);
+ runOnRecentsAnimationStart(() ->
+ mRecentsAnimationTargets.addReleaseCheck(applier));
+ });
+
+ mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
+ if (moveWindowWithRecentsScroll()) {
+ updateFinalShift();
+ }
+ });
+ runOnRecentsAnimationStart(() ->
+ mRecentsView.setRecentsAnimationTargets(mRecentsAnimationController,
+ mRecentsAnimationTargets));
+ mRecentsViewScrollLinked = true;
+ }
+
+ protected void startNewTask(Consumer<Boolean> resultCallback) {
+ // Launch the task user scrolled to (mRecentsView.getNextPage()).
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ // We finish recents animation inside launchTask() when live tile is enabled.
+ mRecentsView.getNextPageTaskView().launchTask(false /* animate */,
+ true /* freezeTaskList */);
+ } else {
+ if (!mCanceled) {
+ TaskView nextTask = mRecentsView.getNextPageTaskView();
+ if (nextTask != null) {
+ int taskId = nextTask.getTask().key.id;
+ mGestureState.updateLastStartedTaskId(taskId);
+ boolean hasTaskPreviouslyAppeared = mGestureState.getPreviouslyAppearedTaskIds()
+ .contains(taskId);
+ nextTask.launchTask(false /* animate */, true /* freezeTaskList */,
+ success -> {
+ resultCallback.accept(success);
+ if (success) {
+ if (hasTaskPreviouslyAppeared) {
+ onRestartPreviouslyAppearedTask();
+ }
+ } else {
+ mActivityInterface.onLaunchTaskFailed();
+ nextTask.notifyTaskLaunchFailed(TAG);
+ mRecentsAnimationController.finish(true /* toRecents */, null);
+ }
+ }, MAIN_EXECUTOR.getHandler());
+ } else {
+ mActivityInterface.onLaunchTaskFailed();
+ Toast.makeText(mContext, R.string.activity_not_available, LENGTH_SHORT).show();
+ mRecentsAnimationController.finish(true /* toRecents */, null);
+ }
+ }
+ mCanceled = false;
+ }
+ }
+
+ /**
+ * Runs the given {@param action} if the recents animation has already started, or queues it to
+ * be run when it is next started.
+ */
+ protected void runOnRecentsAnimationStart(Runnable action) {
+ if (mRecentsAnimationTargets == null) {
+ mRecentsAnimationStartCallbacks.add(action);
+ } else {
+ action.run();
+ }
+ }
+
+ /**
+ * TODO can we remove this now that we don't finish the controller until onTaskAppeared()?
+ * @return whether the recents animation has started and there are valid app targets.
+ */
+ protected boolean hasTargets() {
+ return mRecentsAnimationTargets != null && mRecentsAnimationTargets.hasTargets();
+ }
+
+ @Override
+ public void onRecentsAnimationFinished(RecentsAnimationController controller) {
+ mRecentsAnimationController = null;
+ mRecentsAnimationTargets = null;
+ if (mRecentsView != null) {
+ mRecentsView.setRecentsAnimationTargets(null, null);
+ }
+ }
+
+ @Override
+ public void onTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {
+ if (mRecentsAnimationController != null) {
+ if (handleTaskAppeared(appearedTaskTarget)) {
+ mRecentsAnimationController.finish(false /* toRecents */,
+ null /* onFinishComplete */);
+ mActivityInterface.onLaunchTaskSuccess();
+ ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", false);
+ }
+ }
+ }
+
+ /**
+ * @return The index of the TaskView in RecentsView whose taskId matches the task that will
+ * resume if we finish the controller.
+ */
+ protected int getLastAppearedTaskIndex() {
+ return mGestureState.getLastAppearedTaskId() != -1
+ ? mRecentsView.getTaskIndexForId(mGestureState.getLastAppearedTaskId())
+ : mRecentsView.getRunningTaskIndex();
+ }
+
+ /**
+ * @return Whether we are continuing a gesture that already landed on a new task,
+ * but before that task appeared.
+ */
+ protected boolean hasStartedNewTask() {
+ return mGestureState.getLastStartedTaskId() != -1;
+ }
+
+ /**
+ * Registers a callback to run when the activity is ready.
+ * @param intent The intent that will be used to start the activity if it doesn't exist already.
+ */
+ public void initWhenReady(Intent intent) {
+ // Preload the plan
+ RecentsModel.INSTANCE.get(mContext).getTasks(null);
+
+ mActivityInitListener.register(intent);
+ }
+
+ /**
+ * Applies the transform on the recents animation
+ */
+ protected void applyWindowTransform() {
+ if (mWindowTransitionController != null) {
+ float progress = mCurrentShift.value / mDragLengthFactor;
+ mWindowTransitionController.setPlayFraction(progress);
+ }
+ if (mRecentsAnimationTargets != null) {
+ if (mRecentsViewScrollLinked) {
+ mTaskViewSimulator.setScroll(mRecentsView.getScrollOffset());
+ }
+ mTaskViewSimulator.apply(mTransformParams);
+ }
+ }
+
+ public interface Factory {
+
+ AbsSwipeUpHandler<StatefulActivity<?>, RecentsView> newHandler(
+ GestureState gestureState, long touchTimeMs, boolean continuingLastGesture);
+ }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
deleted file mode 100644
index cbef67b..0000000
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
+++ /dev/null
@@ -1,395 +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 static android.widget.Toast.LENGTH_SHORT;
-
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
-import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.PointF;
-import android.graphics.Rect;
-import android.os.Build;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.widget.Toast;
-
-import androidx.annotation.CallSuper;
-import androidx.annotation.UiThread;
-
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.R;
-import com.android.launcher3.statemanager.StatefulActivity;
-import com.android.launcher3.testing.TestProtocol;
-import com.android.launcher3.util.VibratorWrapper;
-import com.android.launcher3.util.WindowBounds;
-import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener;
-import com.android.quickstep.util.ActiveGestureLog;
-import com.android.quickstep.util.ActivityInitListener;
-import com.android.quickstep.util.InputConsumerProxy;
-import com.android.quickstep.util.RectFSpringAnim;
-import com.android.quickstep.util.SurfaceTransactionApplier;
-import com.android.quickstep.util.TransformParams;
-import com.android.quickstep.views.RecentsView;
-import com.android.quickstep.views.TaskView;
-import com.android.systemui.shared.recents.model.ThumbnailData;
-import com.android.systemui.shared.system.InputConsumerController;
-import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-
-import java.util.ArrayList;
-import java.util.function.Consumer;
-
-/**
- * Base class for swipe up handler with some utility methods
- */
-@TargetApi(Build.VERSION_CODES.Q)
-public abstract class BaseSwipeUpHandler<T extends StatefulActivity<?>, Q extends RecentsView>
- extends SwipeUpAnimationLogic implements RecentsAnimationListener {
-
- private static final String TAG = "BaseSwipeUpHandler";
-
- protected final BaseActivityInterface<?, T> mActivityInterface;
- protected final InputConsumerProxy mInputConsumerProxy;
-
- protected final ActivityInitListener mActivityInitListener;
-
- protected RecentsAnimationController mRecentsAnimationController;
- protected RecentsAnimationTargets mRecentsAnimationTargets;
-
- // Callbacks to be made once the recents animation starts
- private final ArrayList<Runnable> mRecentsAnimationStartCallbacks = new ArrayList<>();
-
- protected T mActivity;
- protected Q mRecentsView;
-
- protected Runnable mGestureEndCallback;
-
- protected MultiStateCallback mStateCallback;
-
- protected boolean mCanceled;
-
- private boolean mRecentsViewScrollLinked = false;
-
- protected BaseSwipeUpHandler(Context context, RecentsAnimationDeviceState deviceState,
- GestureState gestureState, InputConsumerController inputConsumer) {
- super(context, deviceState, gestureState, new TransformParams());
- mActivityInterface = gestureState.getActivityInterface();
- mActivityInitListener = mActivityInterface.createActivityInitListener(this::onActivityInit);
- mInputConsumerProxy =
- new InputConsumerProxy(inputConsumer, this::createNewInputProxyHandler);
- }
-
- /**
- * To be called at the end of constructor of subclasses. This calls various methods which can
- * depend on proper class initialization.
- */
- protected void initAfterSubclassConstructor() {
- initTransitionEndpoints(
- mTaskViewSimulator.getOrientationState().getLauncherDeviceProfile());
- }
-
- protected void performHapticFeedback() {
- VibratorWrapper.INSTANCE.get(mContext).vibrate(OVERVIEW_HAPTIC);
- }
-
- public Consumer<MotionEvent> getRecentsViewDispatcher(float navbarRotation) {
- return mRecentsView != null ? mRecentsView.getEventDispatcher(navbarRotation) : null;
- }
-
- public void setGestureEndCallback(Runnable gestureEndCallback) {
- mGestureEndCallback = gestureEndCallback;
- }
-
- public abstract Intent getLaunchIntent();
-
- protected void linkRecentsViewScroll() {
- SurfaceTransactionApplier.create(mRecentsView, applier -> {
- mTransformParams.setSyncTransactionApplier(applier);
- runOnRecentsAnimationStart(() ->
- mRecentsAnimationTargets.addReleaseCheck(applier));
- });
-
- mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
- if (moveWindowWithRecentsScroll()) {
- updateFinalShift();
- }
- });
- runOnRecentsAnimationStart(() ->
- mRecentsView.setRecentsAnimationTargets(mRecentsAnimationController,
- mRecentsAnimationTargets));
- mRecentsViewScrollLinked = true;
- }
-
- protected void startNewTask(Consumer<Boolean> resultCallback) {
- // Launch the task user scrolled to (mRecentsView.getNextPage()).
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- // We finish recents animation inside launchTask() when live tile is enabled.
- mRecentsView.getNextPageTaskView().launchTask(false /* animate */,
- true /* freezeTaskList */);
- } else {
- if (!mCanceled) {
- TaskView nextTask = mRecentsView.getNextPageTaskView();
- if (nextTask != null) {
- int taskId = nextTask.getTask().key.id;
- mGestureState.updateLastStartedTaskId(taskId);
- boolean hasTaskPreviouslyAppeared = mGestureState.getPreviouslyAppearedTaskIds()
- .contains(taskId);
- nextTask.launchTask(false /* animate */, true /* freezeTaskList */,
- success -> {
- resultCallback.accept(success);
- if (success) {
- if (hasTaskPreviouslyAppeared) {
- onRestartPreviouslyAppearedTask();
- }
- } else {
- mActivityInterface.onLaunchTaskFailed();
- nextTask.notifyTaskLaunchFailed(TAG);
- mRecentsAnimationController.finish(true /* toRecents */, null);
- }
- }, MAIN_EXECUTOR.getHandler());
- } else {
- mActivityInterface.onLaunchTaskFailed();
- Toast.makeText(mContext, R.string.activity_not_available, LENGTH_SHORT).show();
- mRecentsAnimationController.finish(true /* toRecents */, null);
- }
- }
- mCanceled = false;
- }
- }
-
- /**
- * Called when we successfully startNewTask() on the task that was previously running. Normally
- * we call resumeLastTask() when returning to the previously running task, but this handles a
- * specific edge case: if we switch from A to B, and back to A before B appears, we need to
- * start A again to ensure it stays on top.
- */
- @CallSuper
- protected void onRestartPreviouslyAppearedTask() {
- // Finish the controller here, since we won't get onTaskAppeared() for a task that already
- // appeared.
- if (mRecentsAnimationController != null) {
- mRecentsAnimationController.finish(false, null);
- }
- }
-
- /**
- * Runs the given {@param action} if the recents animation has already started, or queues it to
- * be run when it is next started.
- */
- protected void runOnRecentsAnimationStart(Runnable action) {
- if (mRecentsAnimationTargets == null) {
- mRecentsAnimationStartCallbacks.add(action);
- } else {
- action.run();
- }
- }
-
- /**
- * TODO can we remove this now that we don't finish the controller until onTaskAppeared()?
- * @return whether the recents animation has started and there are valid app targets.
- */
- protected boolean hasTargets() {
- return mRecentsAnimationTargets != null && mRecentsAnimationTargets.hasTargets();
- }
-
- @Override
- public void onRecentsAnimationStart(RecentsAnimationController recentsAnimationController,
- RecentsAnimationTargets targets) {
- mRecentsAnimationController = recentsAnimationController;
- mRecentsAnimationTargets = targets;
- mTransformParams.setTargetSet(mRecentsAnimationTargets);
- RemoteAnimationTargetCompat runningTaskTarget = targets.findTask(
- mGestureState.getRunningTaskId());
-
- if (runningTaskTarget != null) {
- mTaskViewSimulator.setPreview(runningTaskTarget);
- }
-
- // Only initialize the device profile, if it has not been initialized before, as in some
- // configurations targets.homeContentInsets may not be correct.
- if (mActivity == null) {
- DeviceProfile dp = mTaskViewSimulator.getOrientationState().getLauncherDeviceProfile();
- if (targets.minimizedHomeBounds != null && runningTaskTarget != null) {
- Rect overviewStackBounds = mActivityInterface
- .getOverviewWindowBounds(targets.minimizedHomeBounds, runningTaskTarget);
- dp = dp.getMultiWindowProfile(mContext,
- new WindowBounds(overviewStackBounds, targets.homeContentInsets));
- } else {
- // If we are not in multi-window mode, home insets should be same as system insets.
- dp = dp.copy(mContext);
- }
- dp.updateInsets(targets.homeContentInsets);
- dp.updateIsSeascape(mContext);
- initTransitionEndpoints(dp);
- }
-
- // Notify when the animation starts
- if (!mRecentsAnimationStartCallbacks.isEmpty()) {
- for (Runnable action : new ArrayList<>(mRecentsAnimationStartCallbacks)) {
- action.run();
- }
- mRecentsAnimationStartCallbacks.clear();
- }
- }
-
- @Override
- public void onRecentsAnimationCanceled(ThumbnailData thumbnailData) {
- mRecentsAnimationController = null;
- mRecentsAnimationTargets = null;
- if (mRecentsView != null) {
- mRecentsView.setRecentsAnimationTargets(null, null);
- }
- }
-
- @Override
- public void onRecentsAnimationFinished(RecentsAnimationController controller) {
- mRecentsAnimationController = null;
- mRecentsAnimationTargets = null;
- if (mRecentsView != null) {
- mRecentsView.setRecentsAnimationTargets(null, null);
- }
- }
-
- @Override
- public void onTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {
- if (mRecentsAnimationController != null) {
- if (handleTaskAppeared(appearedTaskTarget)) {
- mRecentsAnimationController.finish(false /* toRecents */,
- null /* onFinishComplete */);
- mActivityInterface.onLaunchTaskSuccess();
- ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", false);
- }
- }
- }
-
- /** @return Whether this was the task we were waiting to appear, and thus handled it. */
- protected abstract boolean handleTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget);
-
- /**
- * @return The index of the TaskView in RecentsView whose taskId matches the task that will
- * resume if we finish the controller.
- */
- protected int getLastAppearedTaskIndex() {
- return mGestureState.getLastAppearedTaskId() != -1
- ? mRecentsView.getTaskIndexForId(mGestureState.getLastAppearedTaskId())
- : mRecentsView.getRunningTaskIndex();
- }
-
- /**
- * @return Whether we are continuing a gesture that already landed on a new task,
- * but before that task appeared.
- */
- protected boolean hasStartedNewTask() {
- return mGestureState.getLastStartedTaskId() != -1;
- }
-
- /**
- * Return true if the window should be translated horizontally if the recents view scrolls
- */
- protected abstract boolean moveWindowWithRecentsScroll();
-
- protected boolean onActivityInit(Boolean alreadyOnHome) {
- T createdActivity = mActivityInterface.getCreatedActivity();
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.PAUSE_NOT_DETECTED, "BaseSwipeUpHandler.1");
- }
- if (createdActivity != null) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.PAUSE_NOT_DETECTED, "BaseSwipeUpHandler.2");
- }
- initTransitionEndpoints(createdActivity.getDeviceProfile());
- }
- return true;
- }
-
- /**
- * Called to create a input proxy for the running task
- */
- @UiThread
- protected abstract InputConsumer createNewInputProxyHandler();
-
- /**
- * Called when the value of {@link #mCurrentShift} changes
- */
- @UiThread
- public abstract void updateFinalShift();
-
- /**
- * Called when motion pause is detected
- */
- public abstract void onMotionPauseChanged(boolean isPaused);
-
- @UiThread
- public void onGestureStarted(boolean isLikelyToStartNewTask) { }
-
- @UiThread
- public abstract void onGestureCancelled();
-
- @UiThread
- public abstract void onGestureEnded(float endVelocity, PointF velocity, PointF downPos);
-
- public abstract void onConsumerAboutToBeSwitched();
-
- public void setIsLikelyToStartNewTask(boolean isLikelyToStartNewTask) { }
-
- /**
- * Registers a callback to run when the activity is ready.
- * @param intent The intent that will be used to start the activity if it doesn't exist already.
- */
- public void initWhenReady(Intent intent) {
- // Preload the plan
- RecentsModel.INSTANCE.get(mContext).getTasks(null);
-
- mActivityInitListener.register(intent);
- }
-
- /**
- * Applies the transform on the recents animation
- */
- protected void applyWindowTransform() {
- if (mWindowTransitionController != null) {
- float progress = mCurrentShift.value / mDragLengthFactor;
- mWindowTransitionController.setPlayFraction(progress);
- }
- if (mRecentsAnimationTargets != null) {
- if (mRecentsViewScrollLinked) {
- mTaskViewSimulator.setScroll(mRecentsView.getScrollOffset());
- }
- mTaskViewSimulator.apply(mTransformParams);
- }
- }
-
- @Override
- protected RectFSpringAnim createWindowAnimationToHome(float startProgress,
- HomeAnimationFactory homeAnimationFactory) {
- RectFSpringAnim anim =
- super.createWindowAnimationToHome(startProgress, homeAnimationFactory);
- if (mRecentsAnimationTargets != null) {
- mRecentsAnimationTargets.addReleaseCheck(anim);
- }
- return anim;
- }
-
- public interface Factory {
-
- BaseSwipeUpHandler newHandler(
- GestureState gestureState, long touchTimeMs, boolean continuingLastGesture);
- }
-}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java
index f60a50b..ffb05df 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java
@@ -71,7 +71,7 @@
*/
@TargetApi(Build.VERSION_CODES.R)
public class FallbackSwipeHandler extends
- BaseSwipeUpHandlerV2<RecentsActivity, FallbackRecentsView> {
+ AbsSwipeUpHandler<RecentsActivity, FallbackRecentsView> {
/**
* Message used for receiving gesture nav contract information. We use a static messenger to
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandlerV2.java
index 052d0a6..4411455 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandlerV2.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandlerV2.java
@@ -39,7 +39,7 @@
* Temporary class to allow easier refactoring
*/
public class LauncherSwipeHandlerV2 extends
- BaseSwipeUpHandlerV2<BaseQuickstepLauncher, RecentsView> {
+ AbsSwipeUpHandler<BaseQuickstepLauncher, RecentsView> {
public LauncherSwipeHandlerV2(Context context, RecentsAnimationDeviceState deviceState,
TaskAnimationManager taskAnimationManager, GestureState gestureState, long touchTimeMs,
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java
index 07faab7..e54a21c 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java
@@ -287,7 +287,6 @@
@Override
public void onAnimationStart(Animator animation) {
- super.onAnimationStart(animation);
mHomeAnim.dispatchOnStart();
}
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 e5852be..1012ab2 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -269,9 +269,9 @@
return sIsInitialized;
}
- private final BaseSwipeUpHandler.Factory mLauncherSwipeHandlerFactory =
+ private final AbsSwipeUpHandler.Factory mLauncherSwipeHandlerFactory =
this::createLauncherSwipeHandler;
- private final BaseSwipeUpHandler.Factory mFallbackSwipeHandlerFactory =
+ private final AbsSwipeUpHandler.Factory mFallbackSwipeHandlerFactory =
this::createFallbackSwipeHandler;
private ActivityManagerWrapper mAM;
@@ -716,7 +716,7 @@
private InputConsumer createOtherActivityInputConsumer(GestureState gestureState,
MotionEvent event) {
- final BaseSwipeUpHandler.Factory factory;
+ final AbsSwipeUpHandler.Factory factory;
if (!mOverviewComponentObserver.isHomeAndOverviewSame()) {
factory = mFallbackSwipeHandlerFactory;
} else {
@@ -889,13 +889,13 @@
}
}
- private BaseSwipeUpHandler createLauncherSwipeHandler(
+ private AbsSwipeUpHandler createLauncherSwipeHandler(
GestureState gestureState, long touchTimeMs, boolean continuingLastGesture) {
return new LauncherSwipeHandlerV2(this, mDeviceState, mTaskAnimationManager,
gestureState, touchTimeMs, continuingLastGesture, mInputConsumer);
}
- private BaseSwipeUpHandler createFallbackSwipeHandler(
+ private AbsSwipeUpHandler createFallbackSwipeHandler(
GestureState gestureState, long touchTimeMs, boolean continuingLastGesture) {
return new FallbackSwipeHandler(this, mDeviceState, mTaskAnimationManager,
gestureState, touchTimeMs, continuingLastGesture, mInputConsumer);
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 a676390..db1948b 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
@@ -21,7 +21,7 @@
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.Utilities.squaredTouchSlop;
-import static com.android.quickstep.BaseSwipeUpHandlerV2.MIN_PROGRESS_FOR_OVERVIEW;
+import static com.android.quickstep.AbsSwipeUpHandler.MIN_PROGRESS_FOR_OVERVIEW;
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
import static com.android.quickstep.util.ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 6259f1f..f02e5e6 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -53,8 +53,8 @@
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.TraceHelper;
import com.android.quickstep.BaseActivityInterface;
-import com.android.quickstep.BaseSwipeUpHandler;
-import com.android.quickstep.BaseSwipeUpHandler.Factory;
+import com.android.quickstep.AbsSwipeUpHandler;
+import com.android.quickstep.AbsSwipeUpHandler.Factory;
import com.android.quickstep.GestureState;
import com.android.quickstep.InputConsumer;
import com.android.quickstep.RecentsAnimationCallbacks;
@@ -93,7 +93,7 @@
private final InputMonitorCompat mInputMonitorCompat;
private final BaseActivityInterface mActivityInterface;
- private final BaseSwipeUpHandler.Factory mHandlerFactory;
+ private final AbsSwipeUpHandler.Factory mHandlerFactory;
private final Consumer<OtherActivityInputConsumer> mOnCompleteCallback;
private final MotionPauseDetector mMotionPauseDetector;
@@ -101,7 +101,7 @@
private VelocityTracker mVelocityTracker;
- private BaseSwipeUpHandler mInteractionHandler;
+ private AbsSwipeUpHandler mInteractionHandler;
private final boolean mIsDeferredDownTarget;
private final PointF mDownPos = new PointF();
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
index 105b62a..2de4036 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -184,7 +184,7 @@
}
/**
- * Adds animation for all the components corresponding to transition from an app to overview
+ * Adds animation for all the components corresponding to transition from an app to overview.
*/
public void addAppToOverviewAnim(PendingAnimation pa, TimeInterpolator interpolator) {
pa.addFloat(fullScreenProgress, AnimatedFloat.VALUE, 1, 0, interpolator);
@@ -192,6 +192,14 @@
}
/**
+ * Adds animation for all the components corresponding to transition from overview to the app.
+ */
+ public void addOverviewToAppAnim(PendingAnimation pa, TimeInterpolator interpolator) {
+ pa.addFloat(fullScreenProgress, AnimatedFloat.VALUE, 0, 1, interpolator);
+ pa.addFloat(recentsViewScale, AnimatedFloat.VALUE, 1, getFullScreenScale(), interpolator);
+ }
+
+ /**
* Returns the current clipped/visible window bounds in the window coordinate space
*/
public RectF getCurrentCropRect() {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
index 0fcd74b..f31bc19 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -38,11 +38,9 @@
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.Hotseat;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.StateManager.StateListener;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
-import com.android.launcher3.views.ScrimView;
import com.android.quickstep.LauncherActivityInterface;
import com.android.quickstep.SysUINavigationMode;
import com.android.systemui.plugins.PluginListener;
@@ -126,29 +124,10 @@
}
anim.play(ObjectAnimator.ofFloat(
mActivity.getAllAppsController(), ALL_APPS_PROGRESS, allAppsProgressOffscreen));
-
- ObjectAnimator dragHandleAnim = ObjectAnimator.ofInt(
- mActivity.getScrimView(), ScrimView.DRAG_HANDLE_ALPHA, 0);
- dragHandleAnim.setInterpolator(Interpolators.ACCEL_2);
- anim.play(dragHandleAnim);
-
return anim;
}
@Override
- protected void onTaskLaunchAnimationUpdate(float progress, TaskView tv) {
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- if (tv.isRunningTask()) {
- mLiveTileParams.setProgress(1 - progress)
- .setSyncTransactionApplier(mSyncTransactionApplier);
- // TODO: Revisit live tiles
- } else {
- redrawLiveTile();
- }
- }
- }
-
- @Override
protected void onTaskLaunchAnimationEnd(boolean success) {
if (success) {
mActivity.getStateManager().goToState(NORMAL, false /* animate */);
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 49a9db9..b478161 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
@@ -1978,8 +1978,6 @@
? targetSysUiFlags
: 0);
- onTaskLaunchAnimationUpdate(animator.getAnimatedFraction(), tv);
-
// Passing the threshold from taskview to fullscreen app will vibrate
final boolean passed = animator.getAnimatedFraction() >=
SUCCESS_TRANSITION_PROGRESS;
@@ -2003,6 +2001,10 @@
mPendingAnimation = new PendingAnimation(duration);
mPendingAnimation.add(anim);
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ mLiveTileTaskViewSimulator.addOverviewToAppAnim(mPendingAnimation, interpolator);
+ mPendingAnimation.addOnFrameCallback(this::redrawLiveTile);
+ }
mPendingAnimation.addEndListener((endState) -> {
if (endState.isSuccess) {
Consumer<Boolean> onLaunchResult = (result) -> {
@@ -2028,9 +2030,6 @@
return mPendingAnimation;
}
- protected void onTaskLaunchAnimationUpdate(float progress, TaskView tv) {
- }
-
protected void onTaskLaunchAnimationEnd(boolean success) {
if (success) {
resetTaskVisuals();
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
index 9b2048e..8b49f2c 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
@@ -282,7 +282,6 @@
mOpenCloseAnimator.addListener(new AnimationSuccessListener() {
@Override
public void onAnimationStart(Animator animation) {
- super.onAnimationStart(animation);
setVisibility(VISIBLE);
}
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index f4a394a..0ae386f 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -20,7 +20,7 @@
import static com.android.launcher3.anim.Interpolators.INSTANT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
-import static com.android.quickstep.BaseSwipeUpHandlerV2.RECENTS_ATTACH_DURATION;
+import static com.android.quickstep.AbsSwipeUpHandler.RECENTS_ATTACH_DURATION;
import static com.android.quickstep.SysUINavigationMode.getMode;
import static com.android.quickstep.SysUINavigationMode.hideShelfInTwoButtonLandscape;
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
diff --git a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
index 0e2312b..81c4d0c 100644
--- a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
+++ b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
@@ -16,6 +16,7 @@
package com.android.quickstep.interaction;
import static com.android.launcher3.Utilities.squaredHypot;
+import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.ASSISTANT_COMPLETED;
import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.ASSISTANT_NOT_STARTED_BAD_ANGLE;
import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.ASSISTANT_NOT_STARTED_SWIPE_TOO_SHORT;
@@ -48,6 +49,7 @@
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.util.VibratorWrapper;
import com.android.quickstep.SysUINavigationMode.Mode;
+import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.util.NavBarPosition;
import com.android.quickstep.util.TriggerSwipeUpTouchTracker;
import com.android.systemui.shared.system.QuickStepContract;
@@ -74,6 +76,7 @@
private final PointF mAssistantStartDragPos = new PointF();
private final PointF mDownPos = new PointF();
private final PointF mLastPos = new PointF();
+ private final MotionPauseDetector mMotionPauseDetector;
private boolean mTouchCameFromAssistantCorner;
private boolean mTouchCameFromNavBar;
private boolean mPassedAssistantSlop;
@@ -100,6 +103,7 @@
new TriggerSwipeUpTouchTracker(context, true /*disableHorizontalSwipe*/,
new NavBarPosition(Mode.NO_BUTTON, displayRotation),
null /*onInterceptTouch*/, this);
+ mMotionPauseDetector = new MotionPauseDetector(context);
final Resources resources = context.getResources();
mBottomGestureHeight =
@@ -177,12 +181,14 @@
}
mLaunchedAssistant = false;
mSwipeUpTouchTracker.init();
+ mMotionPauseDetector.clear();
+ mMotionPauseDetector.setOnMotionPauseListener(this::onMotionPauseChanged);
break;
case MotionEvent.ACTION_MOVE:
+ mLastPos.set(event.getX(), event.getY());
if (!mAssistantGestureActive) {
break;
}
- mLastPos.set(event.getX(), event.getY());
if (!mPassedAssistantSlop) {
// Normal gesture, ensure we pass the slop before we start tracking the gesture
@@ -213,6 +219,8 @@
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
+ mMotionPauseDetector.clear();
+ mMotionPauseDetector.setOnMotionPauseListener(null);
if (mGestureCallback != null && !intercepted && mTouchCameFromNavBar) {
mGestureCallback.onNavBarGestureAttempted(
HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION, new PointF());
@@ -239,9 +247,17 @@
}
mSwipeUpTouchTracker.onMotionEvent(event);
mAssistantGestureDetector.onTouchEvent(event);
+ mMotionPauseDetector.addPosition(event);
+ mMotionPauseDetector.setDisallowPause(mLastPos.y >= mDisplaySize.y - mBottomGestureHeight);
return intercepted;
}
+ protected void onMotionPauseChanged(boolean isPaused) {
+ if (isPaused) {
+ VibratorWrapper.INSTANCE.get(mContext).vibrate(OVERVIEW_HAPTIC);
+ }
+ }
+
/**
* Determine if angle is larger than threshold for assistant detection
*/
diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
index 4110b33..044e010 100644
--- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
@@ -18,7 +18,7 @@
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
-import static com.android.quickstep.BaseSwipeUpHandlerV2.MAX_SWIPE_DURATION;
+import static com.android.quickstep.AbsSwipeUpHandler.MAX_SWIPE_DURATION;
import static com.android.quickstep.interaction.TutorialController.TutorialType.HOME_NAVIGATION_COMPLETE;
import static com.android.quickstep.interaction.TutorialController.TutorialType.OVERVIEW_NAVIGATION_COMPLETE;
diff --git a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
index 9ed2bbe..c2e67c1 100644
--- a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
+++ b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
@@ -87,20 +87,6 @@
});
}
- if (!hasReachedMaxCount(ALL_APPS_COUNT)) {
- stateManager.addStateListener(new StateListener<LauncherState>() {
- @Override
- public void onStateTransitionComplete(LauncherState finalState) {
- if (finalState == ALL_APPS) {
- if (incrementEventCount(ALL_APPS_COUNT)) {
- stateManager.removeStateListener(this);
- mLauncher.getScrimView().updateDragHandleVisibility();
- }
- }
- }
- });
- }
-
if (FeatureFlags.ENABLE_HYBRID_HOTSEAT.get() && !hasReachedMaxCount(
HOTSEAT_DISCOVERY_TIP_COUNT)) {
stateManager.addStateListener(new StateListener<LauncherState>() {
diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
index 19e278b..f1ac6a5 100644
--- a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
+++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
@@ -44,7 +44,6 @@
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.uioverrides.states.OverviewState;
-import com.android.launcher3.util.OnboardingPrefs;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ScrimView;
import com.android.quickstep.SysUINavigationMode;
@@ -77,15 +76,11 @@
private final float mRadius;
private final int mMaxScrimAlpha;
private final Paint mPaint;
- private final OnboardingPrefs mOnboardingPrefs;
// Mid point where the alpha changes
private int mMidAlpha;
private float mMidProgress;
- // The progress at which the drag handle starts moving up with the shelf.
- private float mDragHandleProgress;
-
private Interpolator mBeforeMidProgressColorInterpolator = ACCEL;
private Interpolator mAfterMidProgressColorInterpolator = ACCEL;
@@ -103,7 +98,6 @@
private boolean mRemainingScreenPathValid = false;
private Mode mSysUINavigationMode;
- private boolean mIsTwoZoneSwipeModel;
public ShelfScrimView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -112,7 +106,6 @@
mEndAlpha = Color.alpha(mEndScrim);
mRadius = BOTTOM_CORNER_RADIUS_RATIO * Themes.getDialogCornerRadius(context);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mOnboardingPrefs = mLauncher.getOnboardingPrefs();
// Just assume the easiest UI for now, until we have the proper layout information.
mDrawingFlatColor = true;
@@ -145,11 +138,9 @@
// Show the shelf more quickly before reaching overview progress.
mBeforeMidProgressColorInterpolator = ACCEL_2;
mAfterMidProgressColorInterpolator = ACCEL;
- mIsTwoZoneSwipeModel = FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get();
} else {
mBeforeMidProgressColorInterpolator = ACCEL;
mAfterMidProgressColorInterpolator = Interpolators.clampToProgress(ACCEL, 0.5f, 1f);
- mIsTwoZoneSwipeModel = false;
}
}
@@ -164,7 +155,6 @@
Context context = getContext();
if ((OVERVIEW.getVisibleElements(mLauncher) & ALL_APPS_HEADER_EXTRA) == 0) {
- mDragHandleProgress = 1;
if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()
&& SysUINavigationMode.removeShelfFromOverview(context)) {
// Fade in all apps background quickly to distinguish from swiping from nav bar.
@@ -182,29 +172,22 @@
+ hotseatPadding.bottom + hotseatPadding.top;
float dragHandleTop =
Math.min(hotseatSize, LayoutUtils.getDefaultSwipeHeight(context, dp));
- mDragHandleProgress = 1 - (dragHandleTop / mShiftRange);
}
- mTopOffset = dp.getInsets().top - mDragHandleSize.y;
+ mTopOffset = dp.getInsets().top;
mShelfTopAtThreshold = mShiftRange * SCRIM_CATCHUP_THRESHOLD + mTopOffset;
}
updateColors();
updateSysUiColors();
- updateDragHandleAlpha();
invalidate();
}
@Override
public void updateColors() {
super.updateColors();
- mDragHandleOffset = 0;
if (mDrawingFlatColor) {
return;
}
- if (mProgress < mDragHandleProgress) {
- mDragHandleOffset = mShiftRange * (mDragHandleProgress - mProgress);
- }
-
if (mProgress >= SCRIM_CATCHUP_THRESHOLD) {
mShelfTop = mShiftRange * mProgress + mTopOffset;
} else {
@@ -259,19 +242,7 @@
}
@Override
- protected boolean shouldDragHandleBeVisible() {
- boolean needsAllAppsEdu = mIsTwoZoneSwipeModel
- && !mOnboardingPrefs.hasReachedMaxCount(OnboardingPrefs.ALL_APPS_COUNT);
- return needsAllAppsEdu || super.shouldDragHandleBeVisible();
- }
-
- @Override
protected void onDraw(Canvas canvas) {
- drawBackground(canvas);
- drawDragHandle(canvas);
- }
-
- private void drawBackground(Canvas canvas) {
if (mDrawingFlatColor) {
if (mCurrentFlatColor != 0) {
canvas.drawColor(mCurrentFlatColor);
@@ -311,9 +282,4 @@
mPaint.setColor(mShelfColor);
canvas.drawRoundRect(0, mShelfTop, width, height + mRadius, mRadius, mRadius, mPaint);
}
-
- @Override
- public float getVisualTop() {
- return mShelfTop;
- }
}
diff --git a/res/drawable-v24/drag_handle_indicator_shadow.xml b/res/drawable-v24/drag_handle_indicator_shadow.xml
deleted file mode 100644
index 774bc38..0000000
--- a/res/drawable-v24/drag_handle_indicator_shadow.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.launcher3.graphics.ShadowDrawable
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/drag_handle_indicator_no_shadow"
- android:elevation="@dimen/vertical_drag_handle_elevation" />
diff --git a/res/drawable/drag_handle_indicator_no_shadow.xml b/res/drawable/drag_handle_indicator_no_shadow.xml
deleted file mode 100644
index 341e60c..0000000
--- a/res/drawable/drag_handle_indicator_no_shadow.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="@dimen/vertical_drag_handle_width"
- android:height="@dimen/vertical_drag_handle_height"
- android:viewportWidth="18.0"
- android:viewportHeight="6.0"
- android:tint="?attr/workspaceTextColor" >
-
- <path
- android:pathData="M17,6c-0.15,0-0.3-0.03-0.45-0.11L9,2.12L1.45,5.89c-0.5,0.25-1.09,
- 0.05-1.34-0.45S0.06,4.35,0.55,4.11l8-4c0.28-0.14,0.61-0.14,0.89,0l8,4c0.49,0.25,0.69,
- 0.85,0.45,1.34C17.72,5.8,17.37,6,17,6z"
- android:fillColor="@android:color/white" />
-</vector>
diff --git a/res/layout/launcher.xml b/res/layout/launcher.xml
index a137908..0c18c8a 100644
--- a/res/layout/launcher.xml
+++ b/res/layout/launcher.xml
@@ -28,6 +28,12 @@
android:clipToPadding="false"
android:importantForAccessibility="no">
+ <com.android.launcher3.views.AccessibilityActionsView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:contentDescription="@string/home_screen"
+ />
+
<!-- The workspace contains 5 screens of cells -->
<!-- DO NOT CHANGE THE ID -->
<com.android.launcher3.Workspace
diff --git a/res/layout/search_section_title.xml b/res/layout/search_section_title.xml
new file mode 100644
index 0000000..9ab27c1
--- /dev/null
+++ b/res/layout/search_section_title.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/section_title"
+ android:textSize="14sp"
+ android:fontFamily="@style/TextHeadline"
+ android:layout_width="wrap_content"
+ android:textColor="?android:attr/textColorPrimary"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:paddingTop="8dp"
+ android:layout_height="wrap_content"/>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 969765f..f59f02f 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -40,14 +40,6 @@
<dimen name="workspace_page_indicator_line_height">1dp</dimen>
<dimen name="workspace_page_indicator_overlap_workspace">0dp</dimen>
- <!-- Hotseat/all-apps scrim -->
- <dimen name="all_apps_scrim_blur">4dp</dimen>
- <dimen name="vertical_drag_handle_width">18dp</dimen>
- <dimen name="vertical_drag_handle_height">6dp</dimen>
- <dimen name="vertical_drag_handle_elevation">1dp</dimen>
- <dimen name="vertical_drag_handle_touch_size">48dp</dimen>
- <dimen name="vertical_drag_handle_padding_in_vertical_bar_layout">16dp</dimen>
-
<!-- Drop target bar -->
<dimen name="dynamic_grid_drop_target_size">48dp</dimen>
<dimen name="drop_target_vertical_gap">20dp</dimen>
diff --git a/res/values/drawables.xml b/res/values/drawables.xml
index 7d63142..9c57ec1 100644
--- a/res/values/drawables.xml
+++ b/res/values/drawables.xml
@@ -18,5 +18,4 @@
<drawable name="ic_remove_shadow">@drawable/ic_remove_no_shadow</drawable>
<drawable name="ic_uninstall_shadow">@drawable/ic_uninstall_no_shadow</drawable>
<drawable name="ic_block_shadow">@drawable/ic_block_no_shadow</drawable>
- <drawable name="all_apps_arrow_shadow">@drawable/drag_handle_indicator_no_shadow</drawable>
</resources>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 80b511a..ef47eef 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -36,7 +36,7 @@
<!-- Message shown when a shortcut is not available. It could have been temporarily disabled and may start working again after some time. -->
<string name="shortcut_not_available">Shortcut isn\'t available</string>
<!-- User visible name for the launcher/home screen. [CHAR_LIMIT=30] -->
- <string name="home_screen">Home screen</string>
+ <string name="home_screen">Home</string>
<!-- Label for showing custom action list of a shortcut or widget. [CHAR_LIMIT=30] -->
<string name="custom_actions">Custom actions</string>
@@ -67,6 +67,10 @@
<!-- Label for an icon representing any generic app. [CHAR_LIMIT=50] -->
<string name="label_application">App</string>
+ <!--All apps Search-->
+ <!-- Section title for apps [CHAR_LIMIT=50] -->
+ <string name="search_corpus_apps">Apps</string>
+
<!-- Popup items -->
<!-- Text to display as the header above notifications. [CHAR_LIMIT=30] -->
<string name="notifications_header">Notifications</string>
@@ -88,10 +92,6 @@
<string name="all_apps_button_personal_label">Personal apps list</string>
<string name="all_apps_button_work_label">Work apps list</string>
- <!-- Label for button in all applications label to go back home (to the workspace / desktop)
- for accessibilty (spoken when the button gets focus). -->
- <string name="all_apps_home_button_label">Home</string>
-
<!-- Label for remove drop target (from the homescreen only).
May appear next to uninstall_drop_target_label [CHAR_LIMIT=20] -->
<string name="remove_drop_target_label">Remove</string>
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 1123c79..db1f1b0 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -452,10 +452,10 @@
mAppsView.getAlphaProperty(APPS_VIEW_ALPHA_CHANNEL_INDEX).setValue(alpha);
} else if (finalState == OVERVIEW || finalState == OVERVIEW_PEEK) {
mAppsView.getAlphaProperty(APPS_VIEW_ALPHA_CHANNEL_INDEX).setValue(alpha);
- mScrimView.getAlphaProperty(SCRIM_VIEW_ALPHA_CHANNEL_INDEX).setValue(alpha);
+ mScrimView.setAlpha(alpha);
} else {
mAppsView.getAlphaProperty(APPS_VIEW_ALPHA_CHANNEL_INDEX).setValue(1f);
- mScrimView.getAlphaProperty(SCRIM_VIEW_ALPHA_CHANNEL_INDEX).setValue(1f);
+ mScrimView.setAlpha(1f);
}
}
});
@@ -552,7 +552,7 @@
mAppsView.getAlphaProperty(APPS_VIEW_ALPHA_CHANNEL_INDEX).setValue(alpha);
} else if (state == OVERVIEW || state == OVERVIEW_PEEK) {
mAppsView.getAlphaProperty(APPS_VIEW_ALPHA_CHANNEL_INDEX).setValue(alpha);
- mScrimView.getAlphaProperty(SCRIM_VIEW_ALPHA_CHANNEL_INDEX).setValue(alpha);
+ mScrimView.setAlpha(alpha);
}
}
@@ -1933,7 +1933,7 @@
// Populate event with a fake title based on the current state.
// TODO: When can workspace be null?
text.add(mWorkspace == null
- ? getString(R.string.all_apps_home_button_label)
+ ? getString(R.string.home_screen)
: mStateManager.getState().getDescription(this));
return result;
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 15e0daa..3be9ac7 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -3263,7 +3263,7 @@
}
if (nScreens == 0) {
// When the workspace is not loaded, we do not know how many screen will be bound.
- return getContext().getString(R.string.all_apps_home_button_label);
+ return getContext().getString(R.string.home_screen);
}
return getContext().getString(R.string.workspace_scroll_format, page + 1, nScreens);
}
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index d653160..dec92df 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -66,6 +66,8 @@
// A divider that separates the apps list and the search market button
public static final int VIEW_TYPE_ALL_APPS_DIVIDER = 1 << 4;
+ public static final int VIEW_TYPE_SEARCH_CORPUS_TITLE = 1 << 5;
+
// Common view type masks
public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER;
public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON;
@@ -274,6 +276,9 @@
case VIEW_TYPE_ALL_APPS_DIVIDER:
return new ViewHolder(mLayoutInflater.inflate(
R.layout.all_apps_divider, parent, false));
+ case VIEW_TYPE_SEARCH_CORPUS_TITLE:
+ return new ViewHolder(
+ mLayoutInflater.inflate(R.layout.search_section_title, parent, false));
default:
throw new RuntimeException("Unexpected view type");
}
@@ -302,6 +307,10 @@
searchView.setVisibility(View.GONE);
}
break;
+ case VIEW_TYPE_SEARCH_CORPUS_TITLE:
+ TextView titleView = (TextView) holder.itemView;
+ titleView.setText(mApps.getAdapterItems().get(position).searchSectionInfo.getTitle(
+ titleView.getContext()));
case VIEW_TYPE_ALL_APPS_DIVIDER:
// nothing to do
break;
diff --git a/src/com/android/launcher3/allapps/AllAppsInsetTransitionController.java b/src/com/android/launcher3/allapps/AllAppsInsetTransitionController.java
index 5af9113..d7af5f1 100644
--- a/src/com/android/launcher3/allapps/AllAppsInsetTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsInsetTransitionController.java
@@ -58,6 +58,17 @@
mApps = appsView;
}
+ public void hide() {
+ if (!BuildCompat.isAtLeastR()) return;
+
+ WindowInsets insets = mApps.getRootWindowInsets();
+ if (insets == null) return;
+
+ if (insets.isVisible(WindowInsets.Type.ime())) {
+ mApps.getWindowInsetsController().hide(WindowInsets.Type.ime());
+ }
+ }
+
/**
* Initializes member variables and requests for the {@link WindowInsetsAnimationController}
* object.
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index cbf02b7..640ef01 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -107,6 +107,7 @@
pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_ALL_APPS_DIVIDER, 1);
pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_SEARCH_MARKET, 1);
pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_ICON, approxRows * mNumAppsPerRow);
+ pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_SEARCH_CORPUS_TITLE, 1);
mViewHeights.clear();
mViewHeights.put(AllAppsGridAdapter.VIEW_TYPE_ICON, grid.allAppsCellHeightPx);
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 5b00631..0268b96 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -19,7 +19,6 @@
import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA;
import static com.android.launcher3.LauncherState.APPS_VIEW_ITEM_MASK;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.LauncherState.VERTICAL_SWIPE_INDICATOR;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
import static com.android.launcher3.anim.Interpolators.INSTANT;
@@ -37,6 +36,7 @@
import android.util.FloatProperty;
import android.view.View;
import android.view.animation.Interpolator;
+import android.widget.EditText;
import androidx.core.os.BuildCompat;
@@ -222,9 +222,6 @@
mAppsView.getSearchUiManager().setContentVisibility(visibleElements, setter, allAppsFade);
- setter.setInt(mScrimView, ScrimView.DRAG_HANDLE_ALPHA,
- (visibleElements & VERTICAL_SWIPE_INDICATOR) != 0 ? 255 : 0, allAppsFade);
-
// Set visibility of the container at the very beginning or end of the transition.
setter.setViewAlpha(mAppsView, hasAnyVisibleItem ? 1 : 0,
hasAnyVisibleItem ? INSTANT : FINAL_FRAME);
@@ -267,8 +264,16 @@
}
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && BuildCompat.isAtLeastR()) {
mInsetController.onAnimationEnd(mProgress);
+ if (Float.compare(mProgress, 0f) == 0) {
+ EditText editText = mAppsView.getSearchUiManager().getEditText();
+ if (editText != null) {
+ editText.requestFocus();
+ }
+ }
if (Float.compare(mProgress, 1f) == 0) {
- mAppsView.getSearchUiManager().setTextSearchEnabled(true).requestFocus();
+ // Called when home gesture closes all apps container.
+ // TODO: should make the controller hide synchronously
+ mInsetController.hide();
}
}
}
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index 06209bb..266bfa2 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -19,8 +19,9 @@
import android.content.Context;
import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.allapps.search.SearchSectionInfo;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.LabelComparator;
@@ -30,6 +31,7 @@
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
+import java.util.stream.Collectors;
/**
* The alphabetically sorted list of applications.
@@ -82,6 +84,8 @@
public AppInfo appInfo = null;
// The index of this app not including sections
public int appIndex = -1;
+ // Search section associated to result
+ public SearchSectionInfo searchSectionInfo = null;
public static AdapterItem asApp(int pos, String sectionName, AppInfo appInfo,
int appIndex) {
@@ -114,6 +118,17 @@
item.position = pos;
return item;
}
+
+ /**
+ * Factory method for search section title AdapterItem
+ */
+ public static AdapterItem asSearchTitle(SearchSectionInfo sectionInfo, int pos) {
+ AdapterItem item = new AdapterItem();
+ item.viewType = AllAppsGridAdapter.VIEW_TYPE_SEARCH_CORPUS_TITLE;
+ item.position = pos;
+ item.searchSectionInfo = sectionInfo;
+ return item;
+ }
}
private final BaseDraggingActivity mLauncher;
@@ -132,7 +147,7 @@
private final boolean mIsWork;
// The of ordered component names as a result of a search query
- private ArrayList<ComponentKey> mSearchResults;
+ private ArrayList<AdapterItem> mSearchResults;
private AllAppsGridAdapter mAdapter;
private AppInfoComparator mAppNameComparator;
private final int mNumAppsPerRow;
@@ -210,10 +225,10 @@
}
/**
- * Sets the sorted list of filtered components.
+ * Sets results list for search
*/
- public boolean setOrderedFilter(ArrayList<ComponentKey> f) {
- if (mSearchResults != f) {
+ public boolean setSearchResults(ArrayList<AdapterItem> f) {
+ if (f == null || mSearchResults != f) {
boolean same = mSearchResults != null && mSearchResults.equals(f);
mSearchResults = f;
onAppsUpdated();
@@ -298,35 +313,42 @@
// Recreate the filtered and sectioned apps (for convenience for the grid layout) from the
// ordered set of sections
- for (AppInfo info : getFiltersAppInfos()) {
- String sectionName = info.sectionName;
+ if (!hasFilter()) {
+ for (AppInfo info : mApps) {
+ String sectionName = info.sectionName;
- // Create a new section if the section names do not match
- if (!sectionName.equals(lastSectionName)) {
- lastSectionName = sectionName;
- lastFastScrollerSectionInfo = new FastScrollSectionInfo(sectionName);
- mFastScrollerSections.add(lastFastScrollerSectionInfo);
- }
+ // Create a new section if the section names do not match
+ if (!sectionName.equals(lastSectionName)) {
+ lastSectionName = sectionName;
+ lastFastScrollerSectionInfo = new FastScrollSectionInfo(sectionName);
+ mFastScrollerSections.add(lastFastScrollerSectionInfo);
+ }
- // Create an app item
- AdapterItem appItem = AdapterItem.asApp(position++, sectionName, info, appIndex++);
- if (lastFastScrollerSectionInfo.fastScrollToItem == null) {
- lastFastScrollerSectionInfo.fastScrollToItem = appItem;
+ // Create an app item
+ AdapterItem appItem = AdapterItem.asApp(position++, sectionName, info, appIndex++);
+ if (lastFastScrollerSectionInfo.fastScrollToItem == null) {
+ lastFastScrollerSectionInfo.fastScrollToItem = appItem;
+ }
+ mAdapterItems.add(appItem);
+ mFilteredApps.add(info);
}
- mAdapterItems.add(appItem);
- mFilteredApps.add(info);
+ } else {
+ mAdapterItems.addAll(mSearchResults);
+ List<AppInfo> appInfos = mSearchResults.stream().filter(
+ i -> AllAppsGridAdapter.isIconViewType(i.viewType)).map(i -> i.appInfo).collect(
+ Collectors.toList());
+ mFilteredApps.addAll(appInfos);
+ if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
+ // Append the search market item
+ if (hasNoFilteredResults()) {
+ mAdapterItems.add(AdapterItem.asEmptySearch(position++));
+ } else {
+ mAdapterItems.add(AdapterItem.asAllAppsDivider(position++));
+ }
+ mAdapterItems.add(AdapterItem.asMarketSearch(position++));
+
+ }
}
-
- if (hasFilter()) {
- // Append the search market item
- if (hasNoFilteredResults()) {
- mAdapterItems.add(AdapterItem.asEmptySearch(position++));
- } else {
- mAdapterItems.add(AdapterItem.asAllAppsDivider(position++));
- }
- mAdapterItems.add(AdapterItem.asMarketSearch(position++));
- }
-
if (mNumAppsPerRow != 0) {
// Update the number of rows in the adapter after we do all the merging (otherwise, we
// would have to shift the values again)
@@ -381,18 +403,4 @@
}
}
}
-
- private List<AppInfo> getFiltersAppInfos() {
- if (mSearchResults == null) {
- return mApps;
- }
- ArrayList<AppInfo> result = new ArrayList<>();
- for (ComponentKey key : mSearchResults) {
- AppInfo match = mAllAppsStore.getApp(key);
- if (match != null) {
- result.add(match);
- }
- }
- return result;
- }
}
diff --git a/src/com/android/launcher3/allapps/SearchUiManager.java b/src/com/android/launcher3/allapps/SearchUiManager.java
index 7d5363f..aa056a0 100644
--- a/src/com/android/launcher3/allapps/SearchUiManager.java
+++ b/src/com/android/launcher3/allapps/SearchUiManager.java
@@ -66,12 +66,8 @@
}
/**
- * Called to control how the search UI result should be handled.
- *
- * @param isEnabled when {@code true}, the search is all handled inside AOSP
- * and is not overlayable.
- * @return the searchbox edit text object
+ * @return the edit text object
*/
@Nullable
- EditText setTextSearchEnabled(boolean isEnabled);
+ EditText getEditText();
}
diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
index df1cd26..db94e8b 100644
--- a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
+++ b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
@@ -28,7 +28,7 @@
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.ExtendedEditText;
import com.android.launcher3.Utilities;
-import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.allapps.AlphabeticalAppsList;
import com.android.launcher3.util.PackageManagerHelper;
import java.util.ArrayList;
@@ -50,6 +50,7 @@
public void setVisibility(int visibility) {
mInput.setVisibility(visibility);
}
+
/**
* Sets the references to the apps model and the search result callback.
*/
@@ -164,9 +165,9 @@
/**
* Called when the search is complete.
*
- * @param apps sorted list of matching components or null if in case of failure.
+ * @param items sorted list of search result adapter items.
*/
- void onSearchResult(String query, ArrayList<ComponentKey> apps);
+ void onSearchResult(String query, ArrayList<AlphabeticalAppsList.AdapterItem> items);
/**
* Called when the search results should be cleared.
diff --git a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
index 356c52c..16a1efd 100644
--- a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
+++ b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
@@ -38,13 +38,13 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.ExtendedEditText;
import com.android.launcher3.Insettable;
+import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
import com.android.launcher3.allapps.AllAppsContainerView;
import com.android.launcher3.allapps.AllAppsStore;
import com.android.launcher3.allapps.AlphabeticalAppsList;
import com.android.launcher3.allapps.SearchUiManager;
import com.android.launcher3.anim.PropertySetter;
-import com.android.launcher3.util.ComponentKey;
import java.util.ArrayList;
@@ -135,7 +135,8 @@
mApps = appsView.getApps();
mAppsView = appsView;
mSearchBarController.initialize(
- new DefaultAppSearchAlgorithm(mApps.getApps()), this, mLauncher, this);
+ new DefaultAppSearchAlgorithm(LauncherAppState.getInstance(mLauncher)), this,
+ mLauncher, this);
}
@Override
@@ -168,9 +169,9 @@
}
@Override
- public void onSearchResult(String query, ArrayList<ComponentKey> apps) {
- if (apps != null) {
- mApps.setOrderedFilter(apps);
+ public void onSearchResult(String query, ArrayList<AlphabeticalAppsList.AdapterItem> items) {
+ if (items != null) {
+ mApps.setSearchResults(items);
notifyResultChanged();
mAppsView.setLastSearchQuery(query);
}
@@ -178,7 +179,7 @@
@Override
public void clearSearchResult() {
- if (mApps.setOrderedFilter(null)) {
+ if (mApps.setSearchResults(null)) {
notifyResultChanged();
}
@@ -216,7 +217,7 @@
}
@Override
- public EditText setTextSearchEnabled(boolean isEnabled) {
+ public EditText getEditText() {
return this;
}
}
diff --git a/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java b/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java
new file mode 100644
index 0000000..5beb956
--- /dev/null
+++ b/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.allapps.search;
+
+import androidx.annotation.WorkerThread;
+
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.R;
+import com.android.launcher3.allapps.AlphabeticalAppsList.AdapterItem;
+import com.android.launcher3.model.AllAppsList;
+import com.android.launcher3.model.BaseModelUpdateTask;
+import com.android.launcher3.model.BgDataModel;
+import com.android.launcher3.model.data.AppInfo;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * A device search section for handling app searches
+ */
+public class AppsSearchPipeline implements SearchPipeline {
+
+ private static final int MAX_RESULTS_COUNT = 5;
+
+ private final SearchSectionInfo mSearchSectionInfo;
+ private final LauncherAppState mLauncherAppState;
+
+ public AppsSearchPipeline(LauncherAppState launcherAppState) {
+ mLauncherAppState = launcherAppState;
+ mSearchSectionInfo = new SearchSectionInfo(R.string.search_corpus_apps);
+ }
+
+ @Override
+ @WorkerThread
+ public void performSearch(String query, Consumer<ArrayList<AdapterItem>> callback) {
+ mLauncherAppState.getModel().enqueueModelUpdateTask(new BaseModelUpdateTask() {
+ @Override
+ public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
+ callback.accept(getAdapterItems(getTitleMatchResult(apps.data, query)));
+ }
+ });
+ }
+
+ /**
+ * Filters {@link AppInfo}s matching specified query
+ */
+ public static ArrayList<AppInfo> getTitleMatchResult(List<AppInfo> apps, String query) {
+ // Do an intersection of the words in the query and each title, and filter out all the
+ // apps that don't match all of the words in the query.
+ final String queryTextLower = query.toLowerCase();
+ final ArrayList<AppInfo> result = new ArrayList<>();
+ DefaultAppSearchAlgorithm.StringMatcher matcher =
+ DefaultAppSearchAlgorithm.StringMatcher.getInstance();
+ for (AppInfo info : apps) {
+ if (DefaultAppSearchAlgorithm.matches(info, queryTextLower, matcher)) {
+ result.add(info);
+ }
+ }
+ return result;
+ }
+
+ private ArrayList<AdapterItem> getAdapterItems(List<AppInfo> matchingApps) {
+ ArrayList<AdapterItem> items = new ArrayList<>();
+ if (matchingApps.isEmpty()) {
+ return items;
+ }
+ items.add(AdapterItem.asSearchTitle(mSearchSectionInfo, 0));
+ int existingItems = items.size();
+ int searchResultsCount = Math.min(matchingApps.size(), MAX_RESULTS_COUNT);
+ for (int i = 0; i < searchResultsCount; i++) {
+ AdapterItem appItem = AdapterItem.asApp(i + existingItems, "", matchingApps.get(i), i);
+ appItem.searchSectionInfo = mSearchSectionInfo;
+ items.add(appItem);
+ }
+
+ return items;
+ }
+}
diff --git a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
index f72a988..db10311 100644
--- a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
+++ b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
@@ -17,24 +17,22 @@
import android.os.Handler;
+import com.android.launcher3.LauncherAppState;
import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.util.ComponentKey;
import java.text.Collator;
-import java.util.ArrayList;
-import java.util.List;
/**
* The default search implementation.
*/
public class DefaultAppSearchAlgorithm implements SearchAlgorithm {
- private final List<AppInfo> mApps;
protected final Handler mResultHandler;
+ private final AppsSearchPipeline mAppsSearchPipeline;
- public DefaultAppSearchAlgorithm(List<AppInfo> apps) {
- mApps = apps;
+ public DefaultAppSearchAlgorithm(LauncherAppState launcherAppState) {
mResultHandler = new Handler();
+ mAppsSearchPipeline = new AppsSearchPipeline(launcherAppState);
}
@Override
@@ -47,28 +45,8 @@
@Override
public void doSearch(final String query,
final AllAppsSearchBarController.Callbacks callback) {
- final ArrayList<ComponentKey> result = getTitleMatchResult(query);
- mResultHandler.post(new Runnable() {
-
- @Override
- public void run() {
- callback.onSearchResult(query, result);
- }
- });
- }
-
- private ArrayList<ComponentKey> getTitleMatchResult(String query) {
- // Do an intersection of the words in the query and each title, and filter out all the
- // apps that don't match all of the words in the query.
- final String queryTextLower = query.toLowerCase();
- final ArrayList<ComponentKey> result = new ArrayList<>();
- StringMatcher matcher = StringMatcher.getInstance();
- for (AppInfo info : mApps) {
- if (matches(info, queryTextLower, matcher)) {
- result.add(info.toComponentKey());
- }
- }
- return result;
+ mAppsSearchPipeline.performSearch(query,
+ results -> mResultHandler.post(() -> callback.onSearchResult(query, results)));
}
public static boolean matches(AppInfo info, String query, StringMatcher matcher) {
diff --git a/src/com/android/launcher3/allapps/search/SearchPipeline.java b/src/com/android/launcher3/allapps/search/SearchPipeline.java
new file mode 100644
index 0000000..3216740
--- /dev/null
+++ b/src/com/android/launcher3/allapps/search/SearchPipeline.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.allapps.search;
+
+import com.android.launcher3.allapps.AlphabeticalAppsList;
+
+import java.util.ArrayList;
+import java.util.function.Consumer;
+
+/**
+ * An interface for handling search within pipeline
+ */
+public interface SearchPipeline {
+
+ /**
+ * Perform query
+ */
+ void performSearch(String query, Consumer<ArrayList<AlphabeticalAppsList.AdapterItem>> cb);
+}
diff --git a/src/com/android/launcher3/allapps/search/SearchSectionInfo.java b/src/com/android/launcher3/allapps/search/SearchSectionInfo.java
new file mode 100644
index 0000000..880b246
--- /dev/null
+++ b/src/com/android/launcher3/allapps/search/SearchSectionInfo.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.allapps.search;
+
+import android.content.Context;
+
+/**
+ * Info class for a search section
+ */
+public class SearchSectionInfo {
+ private final int mTitleResId;
+
+ public SearchSectionInfo(int titleResId) {
+ mTitleResId = titleResId;
+ }
+
+ /**
+ * Returns the section's title
+ */
+ public String getTitle(Context context) {
+ return context.getString(mTitleResId);
+ }
+}
diff --git a/src/com/android/launcher3/anim/AlphaUpdateListener.java b/src/com/android/launcher3/anim/AlphaUpdateListener.java
index 69716ea..eabd283 100644
--- a/src/com/android/launcher3/anim/AlphaUpdateListener.java
+++ b/src/com/android/launcher3/anim/AlphaUpdateListener.java
@@ -46,8 +46,7 @@
}
@Override
- public void onAnimationStart(Animator animation) {
- super.onAnimationStart(animation);
+ public void onAnimationStart(Animator arg0) {
// We want the views to be visible for animation, so fade-in/out is visible
mView.setVisibility(View.VISIBLE);
}
diff --git a/src/com/android/launcher3/anim/AnimationSuccessListener.java b/src/com/android/launcher3/anim/AnimationSuccessListener.java
index b83417c..9905e81 100644
--- a/src/com/android/launcher3/anim/AnimationSuccessListener.java
+++ b/src/com/android/launcher3/anim/AnimationSuccessListener.java
@@ -19,8 +19,6 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import androidx.annotation.CallSuper;
-
/**
* Extension of {@link AnimatorListenerAdapter} for listening for non-cancelled animations
*/
@@ -29,12 +27,6 @@
protected boolean mCancelled = false;
@Override
- @CallSuper
- public void onAnimationStart(Animator animation) {
- mCancelled = false;
- }
-
- @Override
public void onAnimationCancel(Animator animation) {
mCancelled = true;
}
diff --git a/src/com/android/launcher3/anim/AnimatorPlaybackController.java b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
index 31e0418..ea0ff8b 100644
--- a/src/com/android/launcher3/anim/AnimatorPlaybackController.java
+++ b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
@@ -335,7 +335,6 @@
@Override
public void onAnimationStart(Animator animation) {
- super.onAnimationStart(animation);
mCancelled = false;
mDispatched = false;
}
diff --git a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
index 1d32d1d..30c3417 100644
--- a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
+++ b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
@@ -70,7 +70,8 @@
final Bundle parcel = new Bundle();
parcel.putInt(TestProtocol.STATE_FIELD, stateOrdinal);
- sendEventToTest(accessibilityManager, TestProtocol.SWITCHED_TO_STATE_MESSAGE, parcel);
+ sendEventToTest(
+ accessibilityManager, context, TestProtocol.SWITCHED_TO_STATE_MESSAGE, parcel);
Log.d(TestProtocol.PERMANENT_DIAG_TAG, "sendStateEventToTest: " + stateOrdinal);
}
@@ -78,22 +79,24 @@
final AccessibilityManager accessibilityManager = getAccessibilityManagerForTest(context);
if (accessibilityManager == null) return;
- sendEventToTest(accessibilityManager, TestProtocol.SCROLL_FINISHED_MESSAGE, null);
+ sendEventToTest(accessibilityManager, context, 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);
+ sendEventToTest(accessibilityManager, context, TestProtocol.PAUSE_DETECTED_MESSAGE, null);
}
private static void sendEventToTest(
- AccessibilityManager accessibilityManager, String eventTag, Bundle data) {
+ AccessibilityManager accessibilityManager,
+ Context context, String eventTag, Bundle data) {
final AccessibilityEvent e = AccessibilityEvent.obtain(
AccessibilityEvent.TYPE_ANNOUNCEMENT);
e.setClassName(eventTag);
e.setParcelableData(data);
+ e.setPackageName(context.getApplicationContext().getPackageName());
accessibilityManager.sendAccessibilityEvent(e);
}
diff --git a/src/com/android/launcher3/pm/UserCache.java b/src/com/android/launcher3/pm/UserCache.java
index 5aab41a..2d7d6b0 100644
--- a/src/com/android/launcher3/pm/UserCache.java
+++ b/src/com/android/launcher3/pm/UserCache.java
@@ -21,8 +21,10 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArrayMap;
+import android.util.Log;
import android.util.LongSparseArray;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.SafeCloseable;
import com.android.launcher3.util.SimpleBroadcastReceiver;
@@ -102,6 +104,9 @@
mUsers = null;
mUserToSerialMap = null;
}
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.WORK_PROFILE_REMOVED, "Work profile removed", new Exception());
+ }
}
}
diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
index c996748..31c3014 100644
--- a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
+++ b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
@@ -20,6 +20,7 @@
import android.app.ActivityOptions;
import android.content.Intent;
import android.os.Bundle;
+import android.view.Display;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewAnimationUtils;
@@ -168,7 +169,9 @@
@Override
public ActivityOptions getActivityLaunchOptions(View v) {
- return null;
+ final Display display = getWindow().getDecorView().getDisplay();
+ return display != null ? ActivityOptions.makeBasic().setLaunchDisplayId(
+ display.getDisplayId()) : null;
}
@Override
diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java
index f1e7f16..60b87d9 100644
--- a/src/com/android/launcher3/statemanager/StateManager.java
+++ b/src/com/android/launcher3/statemanager/StateManager.java
@@ -315,7 +315,6 @@
@Override
public void onAnimationStart(Animator animation) {
- super.onAnimationStart(animation);
// Change the internal state only when the transition actually starts
onStateTransitionStart(state);
}
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index 8165627..9816f13 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -107,4 +107,5 @@
public static final String PAUSE_NOT_DETECTED = "b/139891609";
public static final String OVERIEW_NOT_ALLAPPS = "b/156095088";
public static final String NO_SWIPE_TO_HOME = "b/158017601";
+ public static final String WORK_PROFILE_REMOVED = "b/159671700";
}
diff --git a/src/com/android/launcher3/util/OnboardingPrefs.java b/src/com/android/launcher3/util/OnboardingPrefs.java
index 26313e5..6e5e7d9 100644
--- a/src/com/android/launcher3/util/OnboardingPrefs.java
+++ b/src/com/android/launcher3/util/OnboardingPrefs.java
@@ -36,7 +36,6 @@
public static final String SHELF_BOUNCE_SEEN = "launcher.shelf_bounce_seen";
public static final String HOME_BOUNCE_COUNT = "launcher.home_bounce_count";
public static final String SHELF_BOUNCE_COUNT = "launcher.shelf_bounce_count";
- public static final String ALL_APPS_COUNT = "launcher.all_apps_count";
public static final String HOTSEAT_DISCOVERY_TIP_COUNT = "launcher.hotseat_discovery_tip_count";
public static final String HOTSEAT_LONGPRESS_TIP_SEEN = "launcher.hotseat_longpress_tip_seen";
@@ -56,7 +55,6 @@
@StringDef(value = {
HOME_BOUNCE_COUNT,
SHELF_BOUNCE_COUNT,
- ALL_APPS_COUNT,
HOTSEAT_DISCOVERY_TIP_COUNT
})
@Retention(RetentionPolicy.SOURCE)
@@ -67,7 +65,6 @@
Map<String, Integer> maxCounts = new ArrayMap<>(4);
maxCounts.put(HOME_BOUNCE_COUNT, 3);
maxCounts.put(SHELF_BOUNCE_COUNT, 3);
- maxCounts.put(ALL_APPS_COUNT, 5);
maxCounts.put(HOTSEAT_DISCOVERY_TIP_COUNT, 5);
MAX_COUNTS = Collections.unmodifiableMap(maxCounts);
}
diff --git a/src/com/android/launcher3/views/AccessibilityActionsView.java b/src/com/android/launcher3/views/AccessibilityActionsView.java
new file mode 100644
index 0000000..0eacaa3
--- /dev/null
+++ b/src/com/android/launcher3/views/AccessibilityActionsView.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.views;
+
+import static com.android.launcher3.LauncherState.ALL_APPS;
+import static com.android.launcher3.LauncherState.NORMAL;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.R;
+import com.android.launcher3.statemanager.StateManager.StateListener;
+import com.android.launcher3.views.OptionsPopupView.OptionItem;
+
+/**
+ * Placeholder view to expose additional Launcher actions via accessibility actions
+ */
+public class AccessibilityActionsView extends View implements StateListener<LauncherState> {
+
+ public AccessibilityActionsView(Context context) {
+ this(context, null);
+ }
+
+ public AccessibilityActionsView(Context context, @Nullable AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public AccessibilityActionsView(Context context, @Nullable AttributeSet attrs,
+ int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ Launcher.getLauncher(context).getStateManager().addStateListener(this);
+ setWillNotDraw(true);
+ }
+
+ @Override
+ public void onStateTransitionComplete(LauncherState finalState) {
+ setImportantForAccessibility(finalState == NORMAL
+ ? IMPORTANT_FOR_ACCESSIBILITY_YES : IMPORTANT_FOR_ACCESSIBILITY_NO);
+ }
+
+ @Override
+ public AccessibilityNodeInfo createAccessibilityNodeInfo() {
+ AccessibilityNodeInfo info = super.createAccessibilityNodeInfo();
+ Launcher l = Launcher.getLauncher(getContext());
+ info.addAction(new AccessibilityAction(
+ R.string.all_apps_button_label, l.getText(R.string.all_apps_button_label)));
+ for (OptionItem item : OptionsPopupView.getOptions(l)) {
+ info.addAction(new AccessibilityAction(item.labelRes, l.getText(item.labelRes)));
+ }
+ return info;
+ }
+
+ @Override
+ public boolean performAccessibilityAction(int action, Bundle arguments) {
+ if (super.performAccessibilityAction(action, arguments)) {
+ return true;
+ }
+ Launcher l = Launcher.getLauncher(getContext());
+ if (action == R.string.all_apps_button_label) {
+ l.getStateManager().goToState(ALL_APPS);
+ return true;
+ }
+ for (OptionItem item : OptionsPopupView.getOptions(l)) {
+ if (item.labelRes == action) {
+ if (item.eventId.getId() > 0) {
+ l.getStatsLogManager().logger().log(item.eventId);
+ }
+ if (item.clickListener.onLongClick(this)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java
index 049a1ac..e95dc5b 100644
--- a/src/com/android/launcher3/views/OptionsPopupView.java
+++ b/src/com/android/launcher3/views/OptionsPopupView.java
@@ -85,10 +85,10 @@
if (item == null) {
return false;
}
- if (item.mEventId.getId() > 0) {
- mLauncher.getStatsLogManager().logger().log(item.mEventId);
+ if (item.eventId.getId() > 0) {
+ mLauncher.getStatsLogManager().logger().log(item.eventId);
}
- if (item.mClickListener.onLongClick(view)) {
+ if (item.clickListener.onLongClick(view)) {
close(true);
return true;
}
@@ -130,8 +130,8 @@
for (OptionItem item : items) {
DeepShortcutView view =
(DeepShortcutView) popup.inflateAndAdd(R.layout.system_shortcut, popup);
- view.getIconView().setBackgroundResource(item.mIconRes);
- view.getBubbleText().setText(item.mLabelRes);
+ view.getIconView().setBackgroundResource(item.iconRes);
+ view.getBubbleText().setText(item.labelRes);
view.setDividerVisibility(View.INVISIBLE);
view.setOnClickListener(popup);
view.setOnLongClickListener(popup);
@@ -152,7 +152,13 @@
y = launcher.getDragLayer().getHeight() / 2;
}
RectF target = new RectF(x - halfSize, y - halfSize, x + halfSize, y + halfSize);
+ show(launcher, target, getOptions(launcher));
+ }
+ /**
+ * Returns the list of supported actions
+ */
+ public static ArrayList<OptionItem> getOptions(Launcher launcher) {
ArrayList<OptionItem> options = new ArrayList<>();
int resString = Utilities.existsStyleWallpapers(launcher) ?
R.string.styles_wallpaper_button_text : R.string.wallpaper_button_text;
@@ -170,10 +176,10 @@
LAUNCHER_SETTINGS_BUTTON_TAP_OR_LONGPRESS,
OptionsPopupView::startSettings));
- show(launcher, target, options);
+ return options;
}
- public static boolean onWidgetsClicked(View view) {
+ private static boolean onWidgetsClicked(View view) {
return openWidgets(Launcher.getLauncher(view.getContext())) != null;
}
@@ -188,7 +194,7 @@
}
}
- public static boolean startSettings(View view) {
+ private static boolean startSettings(View view) {
TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "start: startSettings");
Launcher launcher = Launcher.getLauncher(view.getContext());
launcher.startActivity(new Intent(Intent.ACTION_APPLICATION_PREFERENCES)
@@ -201,7 +207,7 @@
* Event handler for the wallpaper picker button that appears after a long press
* on the home screen.
*/
- public static boolean startWallpaperPicker(View v) {
+ private static boolean startWallpaperPicker(View v) {
Launcher launcher = Launcher.getLauncher(v.getContext());
if (!Utilities.isWallpaperAllowed(launcher)) {
Toast.makeText(launcher, R.string.msg_disabled_by_admin, Toast.LENGTH_SHORT).show();
@@ -233,17 +239,17 @@
public static class OptionItem {
- private final int mLabelRes;
- private final int mIconRes;
- private final EventEnum mEventId;
- private final OnLongClickListener mClickListener;
+ public final int labelRes;
+ public final int iconRes;
+ public final EventEnum eventId;
+ public final OnLongClickListener clickListener;
public OptionItem(int labelRes, int iconRes, EventEnum eventId,
OnLongClickListener clickListener) {
- mLabelRes = labelRes;
- mIconRes = iconRes;
- mEventId = eventId;
- mClickListener = clickListener;
+ this.labelRes = labelRes;
+ this.iconRes = iconRes;
+ this.eventId = eventId;
+ this.clickListener = clickListener;
}
}
}
diff --git a/src/com/android/launcher3/views/ScrimView.java b/src/com/android/launcher3/views/ScrimView.java
index 22faf97..7f0765b 100644
--- a/src/com/android/launcher3/views/ScrimView.java
+++ b/src/com/android/launcher3/views/ScrimView.java
@@ -15,119 +15,37 @@
*/
package com.android.launcher3.views;
-import static android.content.Context.ACCESSIBILITY_SERVICE;
-import static android.view.MotionEvent.ACTION_DOWN;
-
import static androidx.core.graphics.ColorUtils.compositeColors;
-import static com.android.launcher3.LauncherState.ALL_APPS;
-import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
-import static com.android.launcher3.anim.Interpolators.DEACCEL;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.clampToProgress;
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
import static com.android.launcher3.util.SystemUiController.UI_STATE_SCRIM_VIEW;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.Keyframe;
-import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
-import android.animation.RectEvaluator;
import android.content.Context;
-import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.Point;
import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
import android.util.AttributeSet;
-import android.util.IntProperty;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
import android.view.View;
-import android.view.accessibility.AccessibilityManager;
-import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.core.graphics.ColorUtils;
-import androidx.core.view.ViewCompat;
-import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
-import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat;
-import androidx.customview.widget.ExploreByTouchHelper;
-import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.statemanager.StateManager;
-import com.android.launcher3.statemanager.StateManager.StateListener;
import com.android.launcher3.uioverrides.WallpaperColorInfo;
import com.android.launcher3.uioverrides.WallpaperColorInfo.OnChangeListener;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
-import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
-import com.android.launcher3.util.MultiValueAlpha;
-import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.launcher3.util.Themes;
-import com.android.launcher3.widget.WidgetsFullSheet;
-
-import java.util.List;
/**
* Simple scrim which draws a flat color
*/
-public class ScrimView<T extends Launcher> extends View implements Insettable, OnChangeListener,
- AccessibilityStateChangeListener {
-
- public static final IntProperty<ScrimView> DRAG_HANDLE_ALPHA =
- new IntProperty<ScrimView>("dragHandleAlpha") {
-
- @Override
- public Integer get(ScrimView scrimView) {
- return scrimView.mDragHandleAlpha;
- }
-
- @Override
- public void setValue(ScrimView scrimView, int value) {
- scrimView.setDragHandleAlpha(value);
- }
- };
- private static final int WALLPAPERS = R.string.wallpaper_button_text;
- private static final int WIDGETS = R.string.widget_button_text;
- private static final int SETTINGS = R.string.settings_button_text;
- private static final int ALPHA_CHANNEL_COUNT = 1;
-
- private static final long DRAG_HANDLE_BOUNCE_DURATION_MS = 300;
- // How much to delay before repeating the bounce.
- private static final long DRAG_HANDLE_BOUNCE_DELAY_MS = 200;
- // Repeat this many times (i.e. total number of bounces is 1 + this).
- private static final int DRAG_HANDLE_BOUNCE_REPEAT_COUNT = 2;
-
- private final Rect mTempRect = new Rect();
- private final int[] mTempPos = new int[2];
+public class ScrimView<T extends Launcher> extends View implements Insettable, OnChangeListener {
protected final T mLauncher;
private final WallpaperColorInfo mWallpaperColorInfo;
- private final AccessibilityManager mAM;
protected final int mEndScrim;
protected final boolean mIsScrimDark;
- private final StateListener<LauncherState> mAccessibilityLauncherStateListener =
- new StateListener<LauncherState>() {
- @Override
- public void onStateTransitionComplete(LauncherState finalState) {
- setImportantForAccessibility(finalState == ALL_APPS
- ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
- : IMPORTANT_FOR_ACCESSIBILITY_AUTO);
- }
- };
-
protected float mMaxScrimAlpha;
protected float mProgress = 1;
@@ -137,22 +55,6 @@
protected int mEndFlatColor;
protected int mEndFlatColorAlpha;
- protected final Point mDragHandleSize;
- private final int mDragHandleTouchSize;
- private final int mDragHandlePaddingInVerticalBarLayout;
- protected float mDragHandleOffset;
- private final Rect mDragHandleBounds;
- private final RectF mHitRect = new RectF();
- private ObjectAnimator mDragHandleAnim;
-
- private final MultiValueAlpha mMultiValueAlpha;
-
- private final AccessibilityHelper mAccessibilityHelper;
- @Nullable
- protected Drawable mDragHandle;
-
- private int mDragHandleAlpha = 255;
-
public ScrimView(Context context, AttributeSet attrs) {
super(context, attrs);
mLauncher = Launcher.cast(Launcher.getLauncher(context));
@@ -161,59 +63,24 @@
mIsScrimDark = ColorUtils.calculateLuminance(mEndScrim) < 0.5f;
mMaxScrimAlpha = 0.7f;
-
- Resources res = context.getResources();
- mDragHandleSize = new Point(res.getDimensionPixelSize(R.dimen.vertical_drag_handle_width),
- res.getDimensionPixelSize(R.dimen.vertical_drag_handle_height));
- mDragHandleBounds = new Rect(0, 0, mDragHandleSize.x, mDragHandleSize.y);
- mDragHandleTouchSize = res.getDimensionPixelSize(R.dimen.vertical_drag_handle_touch_size);
- mDragHandlePaddingInVerticalBarLayout = context.getResources()
- .getDimensionPixelSize(R.dimen.vertical_drag_handle_padding_in_vertical_bar_layout);
-
- mAccessibilityHelper = createAccessibilityHelper();
- ViewCompat.setAccessibilityDelegate(this, mAccessibilityHelper);
-
- mAM = (AccessibilityManager) context.getSystemService(ACCESSIBILITY_SERVICE);
setFocusable(false);
- mMultiValueAlpha = new MultiValueAlpha(this, ALPHA_CHANNEL_COUNT);
- }
-
- public AlphaProperty getAlphaProperty(int index) {
- return mMultiValueAlpha.getProperty(index);
- }
-
- @NonNull
- protected AccessibilityHelper createAccessibilityHelper() {
- return new AccessibilityHelper();
}
@Override
- public void setInsets(Rect insets) {
- updateDragHandleBounds();
- updateDragHandleVisibility();
- }
+ public void setInsets(Rect insets) { }
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- updateDragHandleBounds();
- }
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mWallpaperColorInfo.addOnChangeListener(this);
onExtractedColorsChanged(mWallpaperColorInfo);
-
- mAM.addAccessibilityStateChangeListener(this);
- onAccessibilityStateChanged(mAM.isEnabled());
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mWallpaperColorInfo.removeOnChangeListener(this);
- mAM.removeAccessibilityStateChangeListener(this);
}
@Override
@@ -234,10 +101,8 @@
public void setProgress(float progress) {
if (mProgress != progress) {
mProgress = progress;
- stopDragHandleEducationAnim();
updateColors();
updateSysUiColors();
- updateDragHandleAlpha();
invalidate();
}
}
@@ -260,286 +125,10 @@
}
}
- protected void updateDragHandleAlpha() {
- if (mDragHandle != null) {
- mDragHandle.setAlpha(mDragHandleAlpha);
- }
- }
-
- private void setDragHandleAlpha(int alpha) {
- if (alpha != mDragHandleAlpha) {
- mDragHandleAlpha = alpha;
- if (mDragHandle != null) {
- mDragHandle.setAlpha(mDragHandleAlpha);
- invalidate();
- }
- }
- }
-
@Override
protected void onDraw(Canvas canvas) {
if (mCurrentFlatColor != 0) {
canvas.drawColor(mCurrentFlatColor);
}
- drawDragHandle(canvas);
- }
-
- protected void drawDragHandle(Canvas canvas) {
- if (mDragHandle != null) {
- canvas.translate(0, -mDragHandleOffset);
- mDragHandle.draw(canvas);
- canvas.translate(0, mDragHandleOffset);
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- boolean superHandledTouch = super.onTouchEvent(event);
- if (event.getAction() == ACTION_DOWN) {
- if (!superHandledTouch && mHitRect.contains(event.getX(), event.getY())) {
- if (startDragHandleEducationAnim()) {
- return true;
- }
- }
- stopDragHandleEducationAnim();
- }
- return superHandledTouch;
- }
-
- /**
- * Animates the drag handle to demonstrate how to get to all apps.
- * @return Whether the animation was started (false if drag handle is invisible).
- */
- public boolean startDragHandleEducationAnim() {
- stopDragHandleEducationAnim();
-
- if (mDragHandle == null || mDragHandle.getAlpha() != 255) {
- return false;
- }
-
- final Drawable drawable = mDragHandle;
- mDragHandle = null;
-
- Rect bounds = new Rect(mDragHandleBounds);
- bounds.offset(0, -(int) mDragHandleOffset);
- drawable.setBounds(bounds);
-
- Rect topBounds = new Rect(bounds);
- topBounds.offset(0, -bounds.height());
-
- Rect invalidateRegion = new Rect(bounds);
- invalidateRegion.top = topBounds.top;
-
- final float progressToReachTop = 0.6f;
- Keyframe frameTop = Keyframe.ofObject(progressToReachTop, topBounds);
- frameTop.setInterpolator(DEACCEL);
- Keyframe frameBot = Keyframe.ofObject(1, bounds);
- frameBot.setInterpolator(ACCEL_DEACCEL);
- PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe("bounds",
- Keyframe.ofObject(0, bounds), frameTop, frameBot);
- holder.setEvaluator(new RectEvaluator());
-
- mDragHandleAnim = ObjectAnimator.ofPropertyValuesHolder(drawable, holder);
- long totalBounceDuration = DRAG_HANDLE_BOUNCE_DURATION_MS + DRAG_HANDLE_BOUNCE_DELAY_MS;
- // The bounce finishes by this progress, the rest of the duration just delays next bounce.
- float delayStartProgress = 1f - (float) DRAG_HANDLE_BOUNCE_DELAY_MS / totalBounceDuration;
- mDragHandleAnim.addUpdateListener((v) -> invalidate(invalidateRegion));
- mDragHandleAnim.setDuration(totalBounceDuration);
- mDragHandleAnim.setInterpolator(clampToProgress(LINEAR, 0, delayStartProgress));
- mDragHandleAnim.setRepeatCount(DRAG_HANDLE_BOUNCE_REPEAT_COUNT);
- getOverlay().add(drawable);
-
- mDragHandleAnim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mDragHandleAnim = null;
- getOverlay().remove(drawable);
- updateDragHandleVisibility(drawable);
- }
- });
- mDragHandleAnim.start();
- return true;
- }
-
- private void stopDragHandleEducationAnim() {
- if (mDragHandleAnim != null) {
- mDragHandleAnim.end();
- }
- }
-
- protected void updateDragHandleBounds() {
- DeviceProfile grid = mLauncher.getDeviceProfile();
- final int left;
- final int width = getMeasuredWidth();
- final int top = getMeasuredHeight() - mDragHandleSize.y - grid.getInsets().bottom;
- final int topMargin;
-
- if (grid.isVerticalBarLayout()) {
- topMargin = grid.workspacePadding.bottom + mDragHandlePaddingInVerticalBarLayout;
- if (grid.isSeascape()) {
- left = width - grid.getInsets().right - mDragHandleSize.x
- - mDragHandlePaddingInVerticalBarLayout;
- } else {
- left = grid.getInsets().left + mDragHandlePaddingInVerticalBarLayout;
- }
- } else {
- left = Math.round((width - mDragHandleSize.x) / 2f);
- topMargin = grid.hotseatBarSizePx;
- }
- mDragHandleBounds.offsetTo(left, top - topMargin);
- mHitRect.set(mDragHandleBounds);
- // Inset outwards to increase touch size.
- mHitRect.inset((mDragHandleSize.x - mDragHandleTouchSize) / 2f,
- (mDragHandleSize.y - mDragHandleTouchSize) / 2f);
-
- if (mDragHandle != null) {
- mDragHandle.setBounds(mDragHandleBounds);
- }
- }
-
- @Override
- public void onAccessibilityStateChanged(boolean enabled) {
- StateManager<LauncherState> stateManager = mLauncher.getStateManager();
- stateManager.removeStateListener(mAccessibilityLauncherStateListener);
-
- if (enabled) {
- stateManager.addStateListener(mAccessibilityLauncherStateListener);
- mAccessibilityLauncherStateListener.onStateTransitionComplete(stateManager.getState());
- } else {
- setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
- }
- updateDragHandleVisibility();
- }
-
- public void updateDragHandleVisibility() {
- updateDragHandleVisibility(null);
- }
-
- private void updateDragHandleVisibility(@Nullable Drawable recycle) {
- boolean visible = shouldDragHandleBeVisible();
- boolean wasVisible = mDragHandle != null;
- if (visible != wasVisible) {
- if (visible) {
- mDragHandle = recycle != null ? recycle :
- mLauncher.getDrawable(R.drawable.drag_handle_indicator_shadow);
- mDragHandle.setBounds(mDragHandleBounds);
-
- updateDragHandleAlpha();
- } else {
- mDragHandle = null;
- }
- invalidate();
- }
- }
-
- protected boolean shouldDragHandleBeVisible() {
- return mLauncher.getDeviceProfile().isVerticalBarLayout() || mAM.isEnabled();
- }
-
- @Override
- public boolean dispatchHoverEvent(MotionEvent event) {
- return mAccessibilityHelper.dispatchHoverEvent(event) || super.dispatchHoverEvent(event);
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- return mAccessibilityHelper.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
- }
-
- @Override
- public void onFocusChanged(boolean gainFocus, int direction,
- Rect previouslyFocusedRect) {
- super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
- mAccessibilityHelper.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
- }
-
- protected class AccessibilityHelper extends ExploreByTouchHelper {
-
- private static final int DRAG_HANDLE_ID = 1;
-
- public AccessibilityHelper() {
- super(ScrimView.this);
- }
-
- @Override
- protected int getVirtualViewAt(float x, float y) {
- return mHitRect.contains((int) x, (int) y)
- ? DRAG_HANDLE_ID : INVALID_ID;
- }
-
- @Override
- protected void getVisibleVirtualViews(List<Integer> virtualViewIds) {
- virtualViewIds.add(DRAG_HANDLE_ID);
- }
-
- @Override
- protected void onPopulateNodeForVirtualView(int virtualViewId,
- AccessibilityNodeInfoCompat node) {
- node.setContentDescription(getContext().getString(R.string.all_apps_button_label));
- node.setBoundsInParent(mDragHandleBounds);
-
- getLocationOnScreen(mTempPos);
- mTempRect.set(mDragHandleBounds);
- mTempRect.offset(mTempPos[0], mTempPos[1]);
- node.setBoundsInScreen(mTempRect);
-
- node.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
- node.setClickable(true);
- node.setFocusable(true);
-
- if (mLauncher.isInState(NORMAL)) {
- Context context = getContext();
- if (Utilities.isWallpaperAllowed(context)) {
- node.addAction(
- new AccessibilityActionCompat(WALLPAPERS, context.getText(WALLPAPERS)));
- }
- node.addAction(new AccessibilityActionCompat(WIDGETS, context.getText(WIDGETS)));
- node.addAction(new AccessibilityActionCompat(SETTINGS, context.getText(SETTINGS)));
- }
- }
-
- @Override
- protected boolean onPerformActionForVirtualView(
- int virtualViewId, int action, Bundle arguments) {
- if (action == AccessibilityNodeInfoCompat.ACTION_CLICK) {
- mLauncher.getUserEventDispatcher().logActionOnControl(
- Action.Touch.TAP, ControlType.ALL_APPS_BUTTON,
- mLauncher.getStateManager().getState().containerType);
- mLauncher.getStateManager().goToState(ALL_APPS);
- return true;
- } else if (action == WALLPAPERS) {
- return OptionsPopupView.startWallpaperPicker(ScrimView.this);
- } else if (action == WIDGETS) {
- int originalImportanceForAccessibility = getImportantForAccessibility();
- setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
- WidgetsFullSheet widgetsFullSheet = OptionsPopupView.openWidgets(mLauncher);
- if (widgetsFullSheet == null) {
- setImportantForAccessibility(originalImportanceForAccessibility);
- return false;
- }
- widgetsFullSheet.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
- @Override
- public void onViewAttachedToWindow(View view) {}
-
- @Override
- public void onViewDetachedFromWindow(View view) {
- setImportantForAccessibility(originalImportanceForAccessibility);
- widgetsFullSheet.removeOnAttachStateChangeListener(this);
- }
- });
- return true;
- } else if (action == SETTINGS) {
- return OptionsPopupView.startSettings(ScrimView.this);
- }
-
- return false;
- }
- }
-
- /**
- * @return The top of this scrim view, or {@link Float#MAX_VALUE} if there's no distinct top.
- */
- public float getVisualTop() {
- return Float.MAX_VALUE;
}
}
diff --git a/tests/src/com/android/launcher3/ui/WorkTabTest.java b/tests/src/com/android/launcher3/ui/WorkTabTest.java
index 8d571ff..f5f93c4 100644
--- a/tests/src/com/android/launcher3/ui/WorkTabTest.java
+++ b/tests/src/com/android/launcher3/ui/WorkTabTest.java
@@ -24,6 +24,7 @@
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.Log;
import android.widget.TextView;
import androidx.test.filters.LargeTest;
@@ -34,6 +35,7 @@
import com.android.launcher3.allapps.AllAppsPagedView;
import com.android.launcher3.allapps.WorkModeSwitch;
import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.views.WorkEduView;
import org.junit.After;
@@ -132,6 +134,10 @@
l.getResources().getString(R.string.work_profile_edu_personal_apps));
workEduView.findViewById(R.id.proceed).callOnClick();
});
+
+ executeOnLauncher(launcher -> Log.d(TestProtocol.WORK_PROFILE_REMOVED,
+ "Work profile status: " + launcher.getAppsView().isPersonalTabVisible()));
+
// verify work edu is seen next
waitForLauncherCondition("Launcher did not show the next edu screen", l ->
((AllAppsPagedView) l.getAppsView().getContentView()).getCurrentPage() == WORK_PAGE
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index 0c4e5a9..e538f60 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -93,7 +93,7 @@
mLauncher.sendPointer(
downTime, downTime, MotionEvent.ACTION_DOWN, start, gestureScope);
- mLauncher.executeAndWaitForEvent(
+ mLauncher.executeAndWaitForLauncherEvent(
() -> mLauncher.movePointer(
downTime,
downTime,
diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index 13ecfb8..093c024 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -56,15 +56,18 @@
private Background launch(BySelector selector) {
LauncherInstrumentation.log("Launchable.launch before click " +
mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
+ final String label = mObject.getText();
mLauncher.executeAndWaitForEvent(
- () -> mLauncher.clickLauncherObject(mObject),
+ () -> {
+ mLauncher.clickLauncherObject(mObject);
+ expectActivityStartEvents();
+ },
event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
- () -> "Launching an app didn't open a new window: " + mObject.getText());
- expectActivityStartEvents();
+ () -> "Launching an app didn't open a new window: " + label);
mLauncher.assertTrue(
- "App didn't start: " + selector,
+ "App didn't start: " + label,
mLauncher.getDevice().wait(Until.hasObject(selector),
LauncherInstrumentation.WAIT_TIME_MS));
return new Background(mLauncher);
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index c74dea9..4e2ed11 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -103,6 +103,7 @@
static final Pattern EVENT_TOUCH_DOWN_TIS = getTouchEventPatternTIS("ACTION_DOWN");
static final Pattern EVENT_TOUCH_UP_TIS = getTouchEventPatternTIS("ACTION_UP");
+ private final String mLauncherPackage;
// Types for launcher containers that the user is interacting with. "Background" is a
// pseudo-container corresponding to inactive launcher covered by another app.
@@ -216,11 +217,11 @@
// Launcher package. As during inproc tests the tested launcher may not be selected as the
// current launcher, choosing target package for inproc. For out-of-proc, use the installed
// launcher package.
- final String authorityPackage = testPackage.equals(targetPackage) ?
- getLauncherPackageName() :
- targetPackage;
+ mLauncherPackage = testPackage.equals(targetPackage)
+ ? getLauncherPackageName()
+ : targetPackage;
- String testProviderAuthority = authorityPackage + ".TestInfo";
+ String testProviderAuthority = mLauncherPackage + ".TestInfo";
mTestProviderUri = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(testProviderAuthority)
@@ -450,7 +451,7 @@
}
}
- dumpDiagnostics();
+ dumpDiagnostics(message);
log("Hierarchy dump for: " + message);
dumpViewHierarchy();
@@ -458,10 +459,11 @@
return message;
}
- private void dumpDiagnostics() {
- Log.e("b/156287114", "Input:");
+ private void dumpDiagnostics(String message) {
+ log("Diagnostics for failure: " + message);
+ log("Input:");
logShellCommand("dumpsys input");
- Log.e("b/156287114", "TIS:");
+ log("TIS:");
logShellCommand("dumpsys activity service TouchInteractionService");
}
@@ -469,10 +471,10 @@
try {
for (String line : mDevice.executeShellCommand(command).split("\\n")) {
SystemClock.sleep(10);
- Log.d("b/156287114", line);
+ log(line);
}
} catch (IOException e) {
- Log.d("b/156287114", "Failed to execute " + command);
+ log("Failed to execute " + command);
}
}
@@ -628,6 +630,14 @@
fail("Launcher didn't initialize");
}
+ Parcelable executeAndWaitForLauncherEvent(Runnable command,
+ UiAutomation.AccessibilityEventFilter eventFilter, Supplier<String> message) {
+ return executeAndWaitForEvent(
+ command,
+ e -> mLauncherPackage.equals(e.getPackageName()) && eventFilter.accept(e),
+ message);
+ }
+
Parcelable executeAndWaitForEvent(Runnable command,
UiAutomation.AccessibilityEventFilter eventFilter, Supplier<String> message) {
try {
@@ -972,7 +982,7 @@
void runToState(Runnable command, int expectedState) {
final List<Integer> actualEvents = new ArrayList<>();
- executeAndWaitForEvent(
+ executeAndWaitForLauncherEvent(
command,
event -> isSwitchToStateEvent(event, expectedState, actualEvents),
() -> "Failed to receive an event for the state change: expected ["
@@ -1087,7 +1097,7 @@
return;
}
- executeAndWaitForEvent(
+ executeAndWaitForLauncherEvent(
() -> linearGesture(
startX, startY, endX, endY, steps, slowDown, GestureScope.INSIDE),
event -> TestProtocol.SCROLL_FINISHED_MESSAGE.equals(event.getClassName()),
@@ -1362,7 +1372,7 @@
if (mCheckEventsForSuccessfulGestures) {
final String message = eventChecker.verify(WAIT_TIME_MS, true);
if (message != null) {
- dumpDiagnostics();
+ dumpDiagnostics(message);
checkForAnomaly();
Assert.fail(formatSystemHealthMessage(
"http://go/tapl : successful gesture produced " + message));