Merge "Set status bar icons to dark at correct all apps progress" into ub-launcher3-edmonton
diff --git a/protos/launcher_log.proto b/protos/launcher_log.proto
index cd404d6..065663d 100644
--- a/protos/launcher_log.proto
+++ b/protos/launcher_log.proto
@@ -90,6 +90,7 @@
TASKSWITCHER = 12; // Recents UI Container (QuickStep)
APP = 13; // Foreground activity is another app (QuickStep)
TIP = 14; // Onboarding texts (QuickStep)
+ SIDELOADED_LAUNCHER = 15;
}
// Used to define what type of control a Target would represent.
@@ -148,11 +149,12 @@
enum Command {
HOME_INTENT = 0;
BACK = 1;
- ENTRY = 2; // Indicates entry to one of Launcher container type target
- // not using the HOME_INTENT
- CANCEL = 3; // Indicates that a confirmation screen was cancelled
- CONFIRM = 4; // Indicates thata confirmation screen was accepted
- STOP = 5; // Indicates onStop() was called (screen time out, power off)
+ ENTRY = 2; // Indicates entry to one of Launcher container type target
+ // not using the HOME_INTENT
+ CANCEL = 3; // Indicates that a confirmation screen was cancelled
+ CONFIRM = 4; // Indicates thata confirmation screen was accepted
+ STOP = 5; // Indicates onStop() was called (screen time out, power off)
+ RECENTS_BUTTON = 6; // Indicates that Recents button was pressed
}
optional Type type = 1;
diff --git a/quickstep/libs/sysui_shared.jar b/quickstep/libs/sysui_shared.jar
index 95bb8bb..5e25fd8 100644
--- a/quickstep/libs/sysui_shared.jar
+++ b/quickstep/libs/sysui_shared.jar
Binary files differ
diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index cf62e2e..80ee577 100644
--- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -21,7 +21,9 @@
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.Utilities.postAsyncCallback;
+import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE;
import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
import static com.android.launcher3.anim.Interpolators.LINEAR;
@@ -58,6 +60,7 @@
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.InsettableFrameLayout.LayoutParams;
+import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.dragndrop.DragLayer;
@@ -329,6 +332,30 @@
appsView.setTranslationY(startY);
appsView.setLayerType(View.LAYER_TYPE_NONE, null);
};
+ } else if (mLauncher.isInState(OVERVIEW)) {
+ AllAppsTransitionController allAppsController = mLauncher.getAllAppsController();
+ launcherAnimator.play(ObjectAnimator.ofFloat(allAppsController, ALL_APPS_PROGRESS,
+ allAppsController.getProgress(), ALL_APPS_PROGRESS_OFF_SCREEN));
+
+ View overview = mLauncher.getOverviewPanelContainer();
+ ObjectAnimator alpha = ObjectAnimator.ofFloat(overview, View.ALPHA, alphas);
+ alpha.setDuration(217);
+ alpha.setInterpolator(LINEAR);
+ launcherAnimator.play(alpha);
+
+ ObjectAnimator transY = ObjectAnimator.ofFloat(overview, View.TRANSLATION_Y, trans);
+ transY.setInterpolator(AGGRESSIVE_EASE);
+ transY.setDuration(350);
+ launcherAnimator.play(transY);
+
+ overview.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+
+ endListener = () -> {
+ overview.setLayerType(View.LAYER_TYPE_NONE, null);
+ overview.setAlpha(1f);
+ overview.setTranslationY(0f);
+ mLauncher.getStateManager().reapplyState();
+ };
} else {
mDragLayerAlpha.setValue(alphas[0]);
ObjectAnimator alpha =
diff --git a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
index dc3f79c..a405735 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
@@ -21,16 +21,17 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
-import android.util.Log;
import android.view.MotionEvent;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.touch.SwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
+import com.android.launcher3.util.FlingBlockCheck;
import com.android.launcher3.util.PendingAnimation;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.views.BaseDragLayer;
@@ -46,8 +47,6 @@
private static final String TAG = "OverviewSwipeController";
- private static final float ALLOWED_FLING_DIRECTION_CHANGE_PROGRESS = 0.1f;
-
// Progress after which the transition is assumed to be a success in case user does not fling
private static final float SUCCESS_TRANSITION_PROGRESS = 0.5f;
@@ -65,6 +64,7 @@
private float mDisplacementShift;
private float mProgressMultiplier;
private float mEndDisplacement;
+ private FlingBlockCheck mFlingBlockCheck = new FlingBlockCheck();
private TaskView mTaskBeingDragged;
@@ -93,7 +93,6 @@
@Override
public void onAnimationCancel(Animator animation) {
if (mCurrentAnimation != null && animation == mCurrentAnimation.getTarget()) {
- Log.e(TAG, "Who dare cancel the animation when I am in control", new Exception());
clearState();
}
}
@@ -158,16 +157,16 @@
return mDetector.onTouchEvent(ev);
}
- private boolean reInitAnimationController(boolean goingUp) {
+ private void reInitAnimationController(boolean goingUp) {
if (mCurrentAnimation != null && mCurrentAnimationIsGoingUp == goingUp) {
// No need to init
- return false;
+ return;
}
int scrollDirections = mDetector.getScrollDirections();
if (goingUp && ((scrollDirections & SwipeDetector.DIRECTION_POSITIVE) == 0)
|| !goingUp && ((scrollDirections & SwipeDetector.DIRECTION_NEGATIVE) == 0)) {
// Trying to re-init in an unsupported direction.
- return false;
+ return;
}
if (mCurrentAnimation != null) {
mCurrentAnimation.setPlayFraction(0);
@@ -205,7 +204,6 @@
mCurrentAnimation.getTarget().addListener(this);
mCurrentAnimation.dispatchOnStart();
mProgressMultiplier = 1 / mEndDisplacement;
- return true;
}
@Override
@@ -217,6 +215,7 @@
mDisplacementShift = mCurrentAnimation.getProgressFraction() / mProgressMultiplier;
mCurrentAnimation.pause();
}
+ mFlingBlockCheck.unblockFling();
}
@Override
@@ -226,6 +225,9 @@
totalDisplacement == 0 ? mCurrentAnimationIsGoingUp : totalDisplacement < 0;
if (isGoingUp != mCurrentAnimationIsGoingUp) {
reInitAnimationController(isGoingUp);
+ mFlingBlockCheck.blockFling();
+ } else {
+ mFlingBlockCheck.onEvent();
}
mCurrentAnimation.setPlayFraction(totalDisplacement * mProgressMultiplier);
return true;
@@ -235,22 +237,14 @@
public void onDragEnd(float velocity, boolean fling) {
final boolean goingToEnd;
final int logAction;
+ boolean blockedFling = fling && mFlingBlockCheck.isBlocked();
+ if (blockedFling) {
+ fling = false;
+ }
if (fling) {
logAction = Touch.FLING;
boolean goingUp = velocity < 0;
- if (goingUp != mCurrentAnimationIsGoingUp) {
- // In case the fling is in opposite direction, make sure if is close enough
- // from the start position
- if (mCurrentAnimation.getProgressFraction()
- >= ALLOWED_FLING_DIRECTION_CHANGE_PROGRESS) {
- // Not allowed
- goingToEnd = false;
- } else {
- goingToEnd = reInitAnimationController(goingUp);
- }
- } else {
- goingToEnd = true;
- }
+ goingToEnd = goingUp == mCurrentAnimationIsGoingUp;
} else {
logAction = Touch.SWIPE;
goingToEnd = mCurrentAnimation.getProgressFraction() > SUCCESS_TRANSITION_PROGRESS;
@@ -259,6 +253,9 @@
float progress = mCurrentAnimation.getProgressFraction();
long animationDuration = SwipeDetector.calculateDuration(
velocity, goingToEnd ? (1 - progress) : progress);
+ if (blockedFling && !goingToEnd) {
+ animationDuration *= LauncherAnimUtils.blockedFlingDurationFactor(velocity);
+ }
float nextFrameProgress = Utilities.boundToRange(
progress + velocity * SINGLE_FRAME_MS / Math.abs(mEndDisplacement), 0f, 1f);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
index 06099b9..e6030d1 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
@@ -24,7 +24,9 @@
import static com.android.launcher3.allapps.DiscoveryBounce.HOME_BOUNCE_SEEN;
import static com.android.launcher3.allapps.DiscoveryBounce.SHELF_BOUNCE_SEEN;
+import android.app.Activity;
import android.content.Context;
+import android.util.Base64;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
@@ -32,13 +34,19 @@
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager;
import com.android.launcher3.LauncherStateManager.StateHandler;
+import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.util.TouchController;
import com.android.quickstep.OverviewInteractionState;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.views.RecentsView;
+import com.android.systemui.shared.system.ActivityCompat;
import com.android.systemui.shared.system.WindowManagerWrapper;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+import java.util.zip.Deflater;
+
public class UiFactory {
public static TouchController[] createTouchControllers(Launcher launcher) {
@@ -167,6 +175,32 @@
}
}
+ public static boolean dumpActivity(Activity activity, PrintWriter writer) {
+ if (!Utilities.IS_DEBUG_DEVICE) {
+ return false;
+ }
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ if (!(new ActivityCompat(activity).encodeViewHierarchy(out))) {
+ return false;
+ }
+
+ Deflater deflater = new Deflater();
+ deflater.setInput(out.toByteArray());
+ deflater.finish();
+
+ out.reset();
+ byte[] buffer = new byte[1024];
+ while (!deflater.finished()) {
+ int count = deflater.deflate(buffer); // returns the generated code... index
+ out.write(buffer, 0, count);
+ }
+
+ writer.println("--encoded-view-dump-v0--");
+ writer.println(Base64.encodeToString(
+ out.toByteArray(), Base64.NO_WRAP | Base64.NO_PADDING));
+ return true;
+ }
+
private static class LauncherTaskViewController extends TaskViewTouchController<Launcher> {
public LauncherTaskViewController(Launcher activity) {
diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
index f9dcee0..ae0affe 100644
--- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java
+++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
@@ -48,6 +48,7 @@
import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.RemoteAnimationProvider;
@@ -99,7 +100,7 @@
RecentsView getVisibleRecentsView();
@UiThread
- boolean switchToRecentsIfVisible();
+ boolean switchToRecentsIfVisible(boolean fromRecentsButton);
Rect getOverviewWindowBounds(Rect homeBounds, RemoteAnimationTargetCompat target);
@@ -120,6 +121,11 @@
*/
LongSwipeHelper getLongSwipeController(T activity, RemoteAnimationTargetSet targetSet);
+ /**
+ * Used for containerType in {@link com.android.launcher3.logging.UserEventDispatcher}
+ */
+ int getContainerType();
+
class LauncherActivityControllerHelper implements ActivityControlHelper<Launcher> {
@Override
@@ -277,9 +283,15 @@
}
@Override
- public boolean switchToRecentsIfVisible() {
+ public boolean switchToRecentsIfVisible(boolean fromRecentsButton) {
Launcher launcher = getVisibleLaucher();
if (launcher != null) {
+ if (fromRecentsButton) {
+ launcher.getUserEventDispatcher().logActionCommand(
+ LauncherLogProto.Action.Command.RECENTS_BUTTON,
+ getContainerType(),
+ LauncherLogProto.ContainerType.TASKSWITCHER);
+ }
launcher.getStateManager().goToState(OVERVIEW);
return true;
}
@@ -319,6 +331,13 @@
public AlphaProperty getAlphaProperty(Launcher activity) {
return activity.getDragLayer().getAlphaProperty(DragLayer.ALPHA_INDEX_SWIPE_UP);
}
+
+ @Override
+ public int getContainerType() {
+ final Launcher launcher = getVisibleLaucher();
+ return launcher != null ? launcher.getStateManager().getState().containerType
+ : LauncherLogProto.ContainerType.APP;
+ }
}
class FallbackActivityControllerHelper implements ActivityControlHelper<RecentsActivity> {
@@ -457,7 +476,7 @@
}
@Override
- public boolean switchToRecentsIfVisible() {
+ public boolean switchToRecentsIfVisible(boolean fromRecentsButton) {
return false;
}
@@ -495,6 +514,10 @@
return activity.getDragLayer().getAlphaProperty(0);
}
+ @Override
+ public int getContainerType() {
+ return LauncherLogProto.ContainerType.SIDELOADED_LAUNCHER;
+ }
}
interface LayoutListener {
diff --git a/quickstep/src/com/android/quickstep/LongSwipeHelper.java b/quickstep/src/com/android/quickstep/LongSwipeHelper.java
index edc7457..fbcde8b 100644
--- a/quickstep/src/com/android/quickstep/LongSwipeHelper.java
+++ b/quickstep/src/com/android/quickstep/LongSwipeHelper.java
@@ -15,6 +15,7 @@
*/
package com.android.quickstep;
+import static com.android.launcher3.LauncherAnimUtils.MIN_PROGRESS_TO_ALL_APPS;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
@@ -26,6 +27,7 @@
import android.view.Surface;
import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.R;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.allapps.DiscoveryBounce;
@@ -33,7 +35,9 @@
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.FlingBlockCheck;
import com.android.quickstep.util.RemoteAnimationTargetSet;
+import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.TransactionCompat;
@@ -44,7 +48,6 @@
*/
public class LongSwipeHelper {
- private static final float MIN_PROGRESS_TO_ALL_APPS = 0.35f;
private static final float SWIPE_DURATION_MULTIPLIER =
Math.min(1 / MIN_PROGRESS_TO_ALL_APPS, 1 / (1 - MIN_PROGRESS_TO_ALL_APPS));
@@ -53,6 +56,7 @@
private float mMaxSwipeDistance = 1;
private AnimatorPlaybackController mAnimator;
+ private FlingBlockCheck mFlingBlockCheck = new FlingBlockCheck();
LongSwipeHelper(Launcher launcher, RemoteAnimationTargetSet targetSet) {
mLauncher = launcher;
@@ -62,6 +66,7 @@
private void init() {
setTargetAlpha(0, true);
+ mFlingBlockCheck.blockFling();
// Init animations
AllAppsTransitionController controller = mLauncher.getAllAppsController();
@@ -74,6 +79,7 @@
public void onMove(float displacement) {
mAnimator.setPlayFraction(displacement / mMaxSwipeDistance);
+ mFlingBlockCheck.onEvent();
}
public void destroy() {
@@ -90,6 +96,11 @@
final boolean toAllApps;
float endProgress;
+ boolean blockedFling = isFling && mFlingBlockCheck.isBlocked();
+ if (blockedFling) {
+ isFling = false;
+ }
+
if (!isFling) {
toAllApps = currentFraction > MIN_PROGRESS_TO_ALL_APPS;
endProgress = toAllApps ? 1 : 0;
@@ -114,7 +125,11 @@
}
}
- mAnimator.setEndAction(() -> onSwipeAnimationComplete(toAllApps, isFling, callback));
+ if (blockedFling && !toAllApps) {
+ duration *= LauncherAnimUtils.blockedFlingDurationFactor(0);
+ }
+ final boolean finalIsFling = isFling;
+ mAnimator.setEndAction(() -> onSwipeAnimationComplete(toAllApps, finalIsFling, callback));
ValueAnimator animator = mAnimator.getAnimationPlayer();
animator.setDuration(duration).setInterpolator(DEACCEL);
animator.setFloatValues(currentFraction, endProgress);
@@ -150,6 +165,7 @@
mLauncher.getStateManager().goToState(toAllApps ? ALL_APPS : OVERVIEW, false);
if (!toAllApps) {
DiscoveryBounce.showForOverviewIfNeeded(mLauncher);
+ mLauncher.<RecentsView>getOverviewPanel().setSwipeDownShouldLaunchApp(true);
}
mLauncher.getUserEventDispatcher().logStateChangeAction(
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 81a73fc..7b29323 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -52,6 +52,8 @@
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.logging.UserEventDispatcher;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
+import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
import com.android.quickstep.ActivityControlHelper.AnimationFactory;
import com.android.quickstep.ActivityControlHelper.FallbackActivityControllerHelper;
@@ -224,6 +226,7 @@
private T mActivity;
private RecentsView mRecentsView;
private final long mToggleClickedTime = SystemClock.uptimeMillis();
+ private boolean mUserEventLogged;
public RecentsActivityCommand() {
mHelper = getActivityControlHelper();
@@ -241,7 +244,7 @@
if (!handleCommand(elapsedTime)) {
// Start overview
- if (!mHelper.switchToRecentsIfVisible()) {
+ if (!mHelper.switchToRecentsIfVisible(true)) {
mListener = mHelper.createActivityInitListener(this::onActivityReady);
mListener.registerAndStartActivity(overviewIntent, this::createWindowAnimation,
mContext, mMainThreadExecutor.getHandler(), RECENTS_LAUNCH_DURATION);
@@ -284,6 +287,11 @@
mActivity = activity;
mRecentsView = mActivity.getOverviewPanel();
mRecentsView.setRunningTaskIconScaledDown(true /* isScaledDown */, false /* animate */);
+ if (!mUserEventLogged) {
+ activity.getUserEventDispatcher().logActionCommand(Action.Command.RECENTS_BUTTON,
+ mHelper.getContainerType(), ContainerType.TASKSWITCHER);
+ mUserEventLogged = true;
+ }
return false;
}
diff --git a/quickstep/src/com/android/quickstep/QuickScrubController.java b/quickstep/src/com/android/quickstep/QuickScrubController.java
index 8398c48..28b06fb 100644
--- a/quickstep/src/com/android/quickstep/QuickScrubController.java
+++ b/quickstep/src/com/android/quickstep/QuickScrubController.java
@@ -26,9 +26,8 @@
import com.android.launcher3.BaseActivity;
import com.android.launcher3.OnAlarmListener;
import com.android.launcher3.Utilities;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
-import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
-import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
@@ -124,9 +123,9 @@
mOnFinishedTransitionToQuickScrubRunnable = launchTaskRunnable;
}
}
- mActivity.getUserEventDispatcher().logActionOnControl(Touch.DRAGDROP,
- ControlType.QUICK_SCRUB_BUTTON, null, mStartedFromHome ?
- ContainerType.WORKSPACE : ContainerType.APP);
+ mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(Touch.DRAGDROP,
+ LauncherLogProto.Action.Direction.NONE, page,
+ TaskUtils.getComponentKeyForTask(mRecentsView.getPageAt(page).getTask().key));
}
/**
@@ -134,7 +133,7 @@
*/
private void breakOutOfQuickScrub() {
if (mRecentsView.getChildCount() == 0 || mActivityControlHelper == null
- || !mActivityControlHelper.switchToRecentsIfVisible()) {
+ || !mActivityControlHelper.switchToRecentsIfVisible(false)) {
mActivity.onBackPressed();
}
}
diff --git a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
index c28a6bd..8c7f104 100644
--- a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
+++ b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
@@ -259,10 +259,11 @@
taskHeight = taskHeight / 2 - halfDividerSize;
}
+ // Align the task to bottom left/right edge (closer to nav bar).
+ int left = activity.getDeviceProfile().isSeascape() ? insets.left
+ : (insets.left + fullDp.availableWidthPx - taskWidth);
mSourceStackBounds.set(0, 0, taskWidth, taskHeight);
- // Align the task to bottom right (probably not true for seascape).
- mSourceStackBounds.offset(insets.left + fullDp.availableWidthPx - taskWidth,
- insets.top + fullDp.availableHeightPx - taskHeight);
+ mSourceStackBounds.offset(left, insets.top + fullDp.availableHeightPx - taskHeight);
}
public void drawForProgress(TaskThumbnailView ttv, Canvas canvas, float progress) {
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 05793f1..01e5cba 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -345,14 +345,22 @@
private float calculateClearAllButtonAlpha() {
final int childCount = getChildCount();
- if (mShowEmptyMessage || childCount == 0) return 0;
+ if (mShowEmptyMessage || childCount == 0 || mPageScrolls == null
+ || childCount != mPageScrolls.length) {
+ return 0;
+ }
final int scrollEnd = getScrollEnd();
final int oldestChildScroll = getScrollForPage(childCount - 1);
- return Utilities.boundToRange(
- ((float) (getScrollX() - oldestChildScroll)) /
- (scrollEnd - oldestChildScroll), 0, 1);
+ final int clearAllButtonMotionRange = scrollEnd - oldestChildScroll;
+ if (clearAllButtonMotionRange == 0) return 0;
+
+ final float alphaUnbound = ((float) (getScrollX() - oldestChildScroll)) /
+ clearAllButtonMotionRange;
+ if (alphaUnbound > 1) return 0;
+
+ return Math.max(alphaUnbound, 0);
}
private void updateClearAllButtonAlpha() {
@@ -745,13 +753,13 @@
duration, LINEAR, anim);
}
- private void removeTask(Task task, PendingAnimation.OnEndListener onEndListener,
- boolean shouldLog) {
+ private void removeTask(Task task, int index, PendingAnimation.OnEndListener onEndListener,
+ boolean shouldLog) {
if (task != null) {
ActivityManagerWrapper.getInstance().removeTask(task.key.id);
if (shouldLog) {
mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
- onEndListener.logAction, Direction.UP,
+ onEndListener.logAction, Direction.UP, index,
TaskUtils.getComponentKeyForTask(task.key));
}
}
@@ -836,7 +844,7 @@
mPendingAnimation.addEndListener((onEndListener) -> {
if (onEndListener.isSuccess) {
if (shouldRemoveTask) {
- removeTask(taskView.getTask(), onEndListener, true);
+ removeTask(taskView.getTask(), draggedIndex, onEndListener, true);
}
int pageToSnapTo = mCurrentPage;
if (draggedIndex < pageToSnapTo) {
@@ -872,7 +880,7 @@
if (onEndListener.isSuccess) {
while (getChildCount() != 0) {
TaskView taskView = getPageAt(getChildCount() - 1);
- removeTask(taskView.getTask(), onEndListener, false);
+ removeTask(taskView.getTask(), -1, onEndListener, false);
removeView(taskView);
}
onAllTasksRemoved();
@@ -1204,7 +1212,7 @@
Task task = tv.getTask();
if (task != null) {
mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
- onEndListener.logAction, Direction.DOWN,
+ onEndListener.logAction, Direction.DOWN, indexOfChild(tv),
TaskUtils.getComponentKeyForTask(task.key));
}
} else {
@@ -1228,6 +1236,7 @@
if (currChild != null) {
currChild.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
}
+ loadVisibleTaskData();
}
@Override
diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
index 69b77b4..24afd48 100644
--- a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
+++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
@@ -28,6 +28,9 @@
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.Path.Op;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.util.AttributeSet;
import com.android.launcher3.DeviceProfile;
@@ -48,6 +51,7 @@
private static final int THRESHOLD_ALPHA_DARK = 102;
private static final int THRESHOLD_ALPHA_LIGHT = 46;
private static final int THRESHOLD_ALPHA_SUPER_LIGHT = 128;
+ private static final int CLEAR_ALL_TASKS = R.string.recents_clear_all;
// In transposed layout, we simply draw a flat color.
private boolean mDrawingFlatColor;
@@ -213,4 +217,43 @@
mRadius, mRadius, mPaint);
return minTop - mDragHandleSize - top;
}
+
+ @NonNull
+ @Override
+ protected AccessibilityHelper createAccessibilityHelper() {
+ return new ShelfScrimAccessibilityHelper();
+ }
+
+ protected class ShelfScrimAccessibilityHelper extends AccessibilityHelper {
+ @Override
+ protected void onPopulateNodeForVirtualView(int virtualViewId,
+ AccessibilityNodeInfoCompat node) {
+ super.onPopulateNodeForVirtualView(virtualViewId, node);
+
+ if (mLauncher.isInState(OVERVIEW)) {
+ final RecentsView overviewPanel = mLauncher.getOverviewPanel();
+ if (overviewPanel.getChildCount() != 0) {
+ node.addAction(
+ new AccessibilityNodeInfoCompat.AccessibilityActionCompat(
+ CLEAR_ALL_TASKS,
+ getContext().getText(CLEAR_ALL_TASKS)));
+ }
+ }
+ }
+
+ @Override
+ protected boolean onPerformActionForVirtualView(
+ int virtualViewId, int action, Bundle arguments) {
+ if (super.onPerformActionForVirtualView(virtualViewId, action, arguments)) return true;
+
+ if (action == CLEAR_ALL_TASKS) {
+ if (mLauncher.isInState(OVERVIEW)) {
+ mLauncher.<RecentsView>getOverviewPanel().dismissAllTasks();
+ }
+ return true;
+ }
+
+ return false;
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 4b2ca45..82aa45a 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -111,11 +111,13 @@
public TaskView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setOnClickListener((view) -> {
- if (mTask != null) {
- launchTask(true /* animate */);
- BaseActivity.fromContext(context).getUserEventDispatcher().logTaskLaunchOrDismiss(
- Touch.TAP, Direction.NONE, TaskUtils.getComponentKeyForTask(mTask.key));
+ if (getTask() == null) {
+ return;
}
+ launchTask(true /* animate */);
+ BaseActivity.fromContext(context).getUserEventDispatcher().logTaskLaunchOrDismiss(
+ Touch.TAP, Direction.NONE, ((RecentsView) getParent()).indexOfChild(this),
+ TaskUtils.getComponentKeyForTask(getTask().key));
});
setOutlineProvider(new TaskOutlineProvider(getResources()));
}
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 65fffd3..7bc11c3 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -244,6 +244,11 @@
<!-- Title for a bottom sheet that shows widgets for a particular app -->
<string name="widgets_bottom_sheet_title"><xliff:g id="name" example="Messenger">%1$s</xliff:g> widgets</string>
+ <!-- Accessibility title for the popup containing a list of widgets. [CHAR_LIMIT=50] -->
+ <string name="widgets_list">Widgets list</string>
+ <!-- Text announced by accessibility when the popup containing the list of widgets is closed. [CHAR_LIMIT=100] -->
+ <string name="widgets_list_closed">Widgets list closed</string>
+
<!-- Strings for accessibility actions -->
<!-- Accessibility action to add an app to workspace. [CHAR_LIMIT=30] -->
<string name="action_add_to_workspace">Add to Home screen</string>
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index 097c341..5a1c158 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -16,10 +16,18 @@
package com.android.launcher3;
+import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED;
+import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
+import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
+
+import static com.android.launcher3.compat.AccessibilityManagerCompat.isAccessibilityEnabled;
+import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
+
import android.annotation.SuppressLint;
import android.content.Context;
import android.support.annotation.IntDef;
import android.util.AttributeSet;
+import android.util.Pair;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
@@ -123,6 +131,25 @@
return false;
}
+ protected void announceAccessibilityChanges() {
+ Pair<View, String> targetInfo = getAccessibilityTarget();
+ if (targetInfo == null || !isAccessibilityEnabled(getContext())) {
+ return;
+ }
+ sendCustomAccessibilityEvent(
+ targetInfo.first, TYPE_WINDOW_STATE_CHANGED, targetInfo.second);
+
+ if (mIsOpen) {
+ sendAccessibilityEvent(TYPE_VIEW_FOCUSED);
+ }
+ BaseDraggingActivity.fromContext(getContext()).getDragLayer()
+ .sendAccessibilityEvent(TYPE_WINDOW_CONTENT_CHANGED);
+ }
+
+ protected Pair<View, String> getAccessibilityTarget() {
+ return null;
+ }
+
protected static <T extends AbstractFloatingView> T getOpenView(
BaseDraggingActivity activity, @FloatingViewType int type) {
BaseDragLayer dragLayer = activity.getDragLayer();
diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java
index 3e4589d..4219667 100644
--- a/src/com/android/launcher3/BaseActivity.java
+++ b/src/com/android/launcher3/BaseActivity.java
@@ -30,8 +30,10 @@
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.logging.UserEventDispatcher;
+import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.util.SystemUiController;
+import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.util.ArrayList;
@@ -224,6 +226,13 @@
void onMultiWindowModeChanged(boolean isInMultiWindowMode);
}
+ @Override
+ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ if (!UiFactory.dumpActivity(this, writer)) {
+ super.dump(prefix, fd, writer, args);
+ }
+ }
+
protected void dumpMisc(PrintWriter writer) {
writer.println(" deviceProfile isTransposed=" + getDeviceProfile().isVerticalBarLayout());
writer.println(" orientation=" + getResources().getConfiguration().orientation);
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index bf73149..e851499 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -240,7 +240,6 @@
private PendingRequestArgs mPendingRequestArgs;
public ViewGroupFocusHelper mFocusHandler;
- private boolean mAppLaunchSuccess;
private RotationHelper mRotationHelper;
@@ -730,10 +729,8 @@
}
mAppWidgetHost.setListenIfResumed(false);
- if (!mAppLaunchSuccess) {
- getUserEventDispatcher().logActionCommand(Action.Command.STOP,
- mStateManager.getState().containerType, -1);
- }
+ getUserEventDispatcher().logActionCommand(Action.Command.STOP,
+ mStateManager.getState().containerType, -1);
NotificationListener.removeNotificationsChangedListener();
getStateManager().moveToRestState();
@@ -760,7 +757,6 @@
super.onResume();
TraceHelper.partitionSection("ON_RESUME", "superCall");
- mAppLaunchSuccess = false;
getUserEventDispatcher().resetElapsedSessionMillis();
setOnResumeCallback(null);
// Process any items that were added while Launcher was away.
@@ -1634,8 +1630,8 @@
}
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
- mAppLaunchSuccess = super.startActivitySafely(v, intent, item);
- if (mAppLaunchSuccess && v instanceof BubbleTextView) {
+ boolean success = super.startActivitySafely(v, intent, item);
+ if (success && v instanceof BubbleTextView) {
// This is set to the view that launched the activity that navigated the user away
// from launcher. Since there is no callback for when the activity has finished
// launching, enable the press state and keep this reference to reset the press
@@ -1644,7 +1640,7 @@
btv.setStayPressed(true);
setOnResumeCallback(btv);
}
- return mAppLaunchSuccess;
+ return success;
}
boolean isHotseatLayout(View layout) {
diff --git a/src/com/android/launcher3/LauncherAnimUtils.java b/src/com/android/launcher3/LauncherAnimUtils.java
index 9869fdf..03ffded 100644
--- a/src/com/android/launcher3/LauncherAnimUtils.java
+++ b/src/com/android/launcher3/LauncherAnimUtils.java
@@ -39,6 +39,9 @@
public static final int SPRING_LOADED_TRANSITION_MS = 150;
public static final int SPRING_LOADED_EXIT_DELAY = 500;
+ // The progress of an animation to all apps must be at least this far along to snap to all apps.
+ public static final float MIN_PROGRESS_TO_ALL_APPS = 0.5f;
+
static WeakHashMap<Animator, Object> sAnimators = new WeakHashMap<Animator, Object>();
static Animator.AnimatorListener sEndAnimListener = new Animator.AnimatorListener() {
public void onAnimationStart(Animator animation) {
@@ -165,16 +168,8 @@
}
};
- public static final Property<View, Float> ELEVATION =
- new Property<View, Float>(Float.class, "elevation") {
- @Override
- public Float get(View view) {
- return view.getElevation();
- }
-
- @Override
- public void set(View view, Float elevation) {
- view.setElevation(elevation);
- }
- };
+ /** Increase the duration if we prevented the fling, as we are going against a high velocity. */
+ public static int blockedFlingDurationFactor(float velocity) {
+ return (int) Utilities.boundToRange(Math.abs(velocity) / 2, 2f, 6f);
+ }
}
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index eb816c5..a98867d 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -109,7 +109,7 @@
private float mLastMotionXRemainder;
private float mTotalMotionX;
- private int[] mPageScrolls;
+ protected int[] mPageScrolls;
protected final static int TOUCH_STATE_REST = 0;
protected final static int TOUCH_STATE_SCROLLING = 1;
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index 7fef904..53e9e2d 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -28,8 +28,6 @@
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -126,18 +124,6 @@
return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
}
- public boolean isEventOverHotseat(MotionEvent ev) {
- return isEventOverView(mActivity.getHotseat(), ev);
- }
-
- private boolean isEventOverFolder(Folder folder, MotionEvent ev) {
- return isEventOverView(folder, ev);
- }
-
- private boolean isEventOverDropTargetBar(MotionEvent ev) {
- return isEventOverView(mActivity.getDropTargetBar(), ev);
- }
-
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
ViewScrim scrim = ViewScrim.get(child);
@@ -157,24 +143,29 @@
return super.findActiveController(ev);
}
+ private boolean isEventOverAccessibleDropTargetBar(MotionEvent ev) {
+ return isInAccessibleDrag() && isEventOverView(mActivity.getDropTargetBar(), ev);
+ }
+
@Override
public boolean onInterceptHoverEvent(MotionEvent ev) {
if (mActivity == null || mActivity.getWorkspace() == null) {
return false;
}
- Folder currentFolder = Folder.getOpen(mActivity);
- if (currentFolder == null) {
+ AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
+ if (!(topView instanceof Folder)) {
return false;
} else {
AccessibilityManager accessibilityManager = (AccessibilityManager)
getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
if (accessibilityManager.isTouchExplorationEnabled()) {
+ Folder currentFolder = (Folder) topView;
final int action = ev.getAction();
boolean isOverFolderOrSearchBar;
switch (action) {
case MotionEvent.ACTION_HOVER_ENTER:
- isOverFolderOrSearchBar = isEventOverFolder(currentFolder, ev) ||
- (isInAccessibleDrag() && isEventOverDropTargetBar(ev));
+ isOverFolderOrSearchBar = isEventOverView(topView, ev) ||
+ isEventOverAccessibleDropTargetBar(ev);
if (!isOverFolderOrSearchBar) {
sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
mHoverPointClosesFolder = true;
@@ -183,8 +174,8 @@
mHoverPointClosesFolder = false;
break;
case MotionEvent.ACTION_HOVER_MOVE:
- isOverFolderOrSearchBar = isEventOverFolder(currentFolder, ev) ||
- (isInAccessibleDrag() && isEventOverDropTargetBar(ev));
+ isOverFolderOrSearchBar = isEventOverView(topView, ev) ||
+ isEventOverAccessibleDropTargetBar(ev);
if (!isOverFolderOrSearchBar && !mHoverPointClosesFolder) {
sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
mHoverPointClosesFolder = true;
@@ -219,18 +210,8 @@
@Override
public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
- // Shortcuts can appear above folder
- View topView = AbstractFloatingView.getTopOpenView(mActivity);
- if (topView != null) {
- if (child == topView) {
- return super.onRequestSendAccessibilityEvent(child, event);
- }
- if (isInAccessibleDrag() && child instanceof DropTargetBar) {
- return super.onRequestSendAccessibilityEvent(child, event);
- }
- // Skip propagating onRequestSendAccessibilityEvent for all other children
- // which are not topView
- return false;
+ if (isInAccessibleDrag() && child instanceof DropTargetBar) {
+ return true;
}
return super.onRequestSendAccessibilityEvent(child, event);
}
@@ -239,11 +220,9 @@
public void addChildrenForAccessibility(ArrayList<View> childrenForAccessibility) {
View topView = AbstractFloatingView.getTopOpenView(mActivity);
if (topView != null) {
- // Only add the top view as a child for accessibility when it is open
- childrenForAccessibility.add(topView);
-
+ addAccessibleChildToList(topView, childrenForAccessibility);
if (isInAccessibleDrag()) {
- childrenForAccessibility.add(mActivity.getDropTargetBar());
+ addAccessibleChildToList(mActivity.getDropTargetBar(), childrenForAccessibility);
}
} else {
super.addChildrenForAccessibility(childrenForAccessibility);
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 99c800d..b49952f 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -31,6 +31,7 @@
import android.text.Selection;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.Pair;
import android.view.ActionMode;
import android.view.FocusFinder;
import android.view.KeyEvent;
@@ -516,15 +517,11 @@
public void onAnimationStart(Animator animation) {
mFolderIcon.setBackgroundVisible(false);
mFolderIcon.drawLeaveBehindIfExists();
-
- sendCustomAccessibilityEvent(
- Folder.this,
- AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
- mContent.getAccessibilityDescription());
}
@Override
public void onAnimationEnd(Animator animation) {
mState = STATE_OPEN;
+ announceAccessibilityChanges();
mLauncher.getUserEventDispatcher().resetElapsedContainerMillis("folder opened");
mContent.setFocusOnFirstChild();
@@ -574,11 +571,6 @@
}
mContent.verifyVisibleHighResIcons(mContent.getNextPage());
-
- // Notify the accessibility manager that this folder "window" has appeared and occluded
- // the workspace items
- sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
- dragLayer.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
}
public void beginExternalDrag() {
@@ -612,6 +604,7 @@
animateClosed();
} else {
closeComplete(false);
+ post(this::announceAccessibilityChanges);
}
// Notify the accessibility manager that this folder "window" has disappeared and no
@@ -626,18 +619,18 @@
@Override
public void onAnimationEnd(Animator animation) {
closeComplete(true);
- }
- @Override
- public void onAnimationStart(Animator animation) {
- sendCustomAccessibilityEvent(
- Folder.this,
- AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
- getContext().getString(R.string.folder_closed));
+ announceAccessibilityChanges();
}
});
startAnimation(a);
}
+ @Override
+ protected Pair<View, String> getAccessibilityTarget() {
+ return Pair.create(mContent, mIsOpen ? mContent.getAccessibilityDescription()
+ : getContext().getString(R.string.folder_closed));
+ }
+
private void closeComplete(boolean wasAnimated) {
// TODO: Clear all active animations.
DragLayer parent = (DragLayer) getParent();
diff --git a/src/com/android/launcher3/logging/LoggerUtils.java b/src/com/android/launcher3/logging/LoggerUtils.java
index 442691f..83593aa 100644
--- a/src/com/android/launcher3/logging/LoggerUtils.java
+++ b/src/com/android/launcher3/logging/LoggerUtils.java
@@ -131,6 +131,9 @@
+ "), pageIdx=" + t.pageIndex;
}
+ if (t.itemType == ItemType.TASK) {
+ typeStr += ", pageIdx=" + t.pageIndex;
+ }
return typeStr;
}
diff --git a/src/com/android/launcher3/logging/UserEventDispatcher.java b/src/com/android/launcher3/logging/UserEventDispatcher.java
index 07e1315..850c948 100644
--- a/src/com/android/launcher3/logging/UserEventDispatcher.java
+++ b/src/com/android/launcher3/logging/UserEventDispatcher.java
@@ -132,6 +132,7 @@
private boolean mIsInLandscapeMode;
private String mUuidStr;
protected InstantAppResolver mInstantAppResolver;
+ private boolean mAppOrTaskLaunch;
// APP_ICON SHORTCUT WIDGET
// --------------------------------------------------------------
@@ -163,11 +164,13 @@
fillIntentInfo(event.srcTarget[0], intent);
}
dispatchUserEvent(event, intent);
+ mAppOrTaskLaunch = true;
}
public void logActionTip(int actionType, int viewType) { }
- public void logTaskLaunchOrDismiss(int action, int direction, ComponentKey componentKey) {
+ public void logTaskLaunchOrDismiss(int action, int direction, int taskIndex,
+ ComponentKey componentKey) {
LauncherEvent event = newLauncherEvent(newTouchAction(action), // TAP or SWIPE or FLING
newTarget(Target.Type.ITEM));
if (action == Action.Touch.SWIPE || action == Action.Touch.FLING) {
@@ -175,8 +178,10 @@
event.action.dir = direction;
}
event.srcTarget[0].itemType = LauncherLogProto.ItemType.TASK;
+ event.srcTarget[0].pageIndex = taskIndex;
fillComponentInfo(event.srcTarget[0], componentKey.componentName);
dispatchUserEvent(event, null);
+ mAppOrTaskLaunch = true;
}
protected void fillIntentInfo(Target target, Intent intent) {
@@ -211,6 +216,11 @@
public void logActionCommand(int command, Target srcTarget, Target dstTarget) {
LauncherEvent event = newLauncherEvent(newCommandAction(command), srcTarget);
+ if (command == Action.Command.STOP && mAppOrTaskLaunch) {
+ // Prevent double logging by skipping STOP when app or task has been launched.
+ return;
+ }
+
if (dstTarget != null) {
event.destTarget = new Target[1];
event.destTarget[0] = dstTarget;
@@ -405,6 +415,7 @@
}
public void dispatchUserEvent(LauncherEvent ev, Intent intent) {
+ mAppOrTaskLaunch = false;
ev.isInLandscapeMode = mIsInLandscapeMode;
ev.isInMultiWindowMode = mIsInMultiWindowMode;
ev.elapsedContainerMillis = SystemClock.uptimeMillis() - mElapsedContainerMillis;
@@ -413,7 +424,8 @@
if (!IS_VERBOSE) {
return;
}
- String log = "\n\naction:" + LoggerUtils.getActionStr(ev.action);
+ String log = "\n-----------------------------------------------------"
+ + "\naction:" + LoggerUtils.getActionStr(ev.action);
if (ev.srcTarget != null && ev.srcTarget.length > 0) {
log += "\n Source " + getTargetsStr(ev.srcTarget);
}
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index 5589f17..9098777 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -367,6 +367,7 @@
openAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
+ announceAccessibilityChanges();
mOpenCloseAnimator = null;
}
});
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 763eb6f..f276fbf 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -34,6 +34,7 @@
import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
+import android.util.Pair;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
@@ -263,9 +264,7 @@
ItemInfo originalItemInfo = (ItemInfo) originalIcon.getTag();
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
- setAccessibilityPaneTitle(getContext().getString(mNumNotifications == 0 ?
- R.string.action_deep_shortcut :
- R.string.shortcuts_menu_with_notifications_description));
+ setAccessibilityPaneTitle(getTitleForAccessibility());
}
mLauncher.getDragController().addDragListener(this);
@@ -281,6 +280,17 @@
this, shortcutIds, mShortcuts, notificationKeys));
}
+ private String getTitleForAccessibility() {
+ return getContext().getString(mNumNotifications == 0 ?
+ R.string.action_deep_shortcut :
+ R.string.shortcuts_menu_with_notifications_description);
+ }
+
+ @Override
+ protected Pair<View, String> getAccessibilityTarget() {
+ return Pair.create(this, "");
+ }
+
@Override
protected void getTargetObjectLocation(Rect outPos) {
mLauncher.getDragLayer().getDescendantRectRelativeToSelf(mOriginalIcon, outPos);
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 6e48c36..087549e 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.touch;
+import static com.android.launcher3.LauncherAnimUtils.MIN_PROGRESS_TO_ALL_APPS;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
@@ -32,6 +33,7 @@
import android.view.MotionEvent;
import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.AnimationComponents;
import com.android.launcher3.LauncherStateManager.AnimationConfig;
@@ -43,6 +45,7 @@
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.FlingBlockCheck;
import com.android.launcher3.util.PendingAnimation;
import com.android.launcher3.util.TouchController;
@@ -80,7 +83,7 @@
private float mProgressMultiplier;
private float mDisplacementShift;
private boolean mCanBlockFling;
- private boolean mBlockFling;
+ private FlingBlockCheck mFlingBlockCheck = new FlingBlockCheck();
private AnimatorSet mAtomicAnim;
private boolean mPassedOverviewAtomicThreshold;
@@ -241,7 +244,7 @@
mStartProgress = mCurrentAnimation.getProgressFraction();
}
mCanBlockFling = mFromState == NORMAL;
- mBlockFling = false;
+ mFlingBlockCheck.unblockFling();
}
@Override
@@ -253,16 +256,19 @@
if (progress <= 0) {
if (reinitCurrentAnimation(false, isDragTowardPositive)) {
mDisplacementShift = displacement;
- mBlockFling = mCanBlockFling;
+ if (mCanBlockFling) {
+ mFlingBlockCheck.blockFling();
+ }
}
} else if (progress >= 1) {
if (reinitCurrentAnimation(true, isDragTowardPositive)) {
mDisplacementShift = displacement;
- mBlockFling = mCanBlockFling;
+ if (mCanBlockFling) {
+ mFlingBlockCheck.blockFling();
+ }
}
- } else if (Math.abs(velocity) < SwipeDetector.RELEASE_VELOCITY_PX_MS) {
- // We prevent flinging after passing a state, but allow it if the user pauses briefly.
- mBlockFling = false;
+ } else {
+ mFlingBlockCheck.onEvent();
}
return true;
@@ -325,7 +331,7 @@
final LauncherState targetState;
final float progress = mCurrentAnimation.getProgressFraction();
- boolean blockedFling = fling && mBlockFling;
+ boolean blockedFling = fling && mFlingBlockCheck.isBlocked();
if (blockedFling) {
fling = false;
}
@@ -338,14 +344,17 @@
// snap to top or bottom using the release velocity
} else {
logAction = Touch.SWIPE;
- targetState = (progress > SUCCESS_TRANSITION_PROGRESS) ? mToState : mFromState;
+ float successProgress = mToState == ALL_APPS
+ ? MIN_PROGRESS_TO_ALL_APPS : SUCCESS_TRANSITION_PROGRESS;
+ targetState = (progress > successProgress) ? mToState : mFromState;
}
final float endProgress;
final float startProgress;
final long duration;
// Increase the duration if we prevented the fling, as we are going against a high velocity.
- final long durationMultiplier = blockedFling && targetState == mFromState ? 6 : 1;
+ final int durationMultiplier = blockedFling && targetState == mFromState
+ ? LauncherAnimUtils.blockedFlingDurationFactor(velocity) : 1;
if (targetState == mToState) {
endProgress = 1;
diff --git a/src/com/android/launcher3/util/FlingBlockCheck.java b/src/com/android/launcher3/util/FlingBlockCheck.java
new file mode 100644
index 0000000..f9575b9
--- /dev/null
+++ b/src/com/android/launcher3/util/FlingBlockCheck.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.util;
+
+import android.os.SystemClock;
+
+/**
+ * Determines whether a fling should be blocked. Currently we block flings when crossing thresholds
+ * to new states, and unblock after a short duration.
+ */
+public class FlingBlockCheck {
+ // Allow flinging to a new state after waiting this many milliseconds.
+ private static final long UNBLOCK_FLING_PAUSE_DURATION = 200;
+
+ private boolean mBlockFling;
+ private long mBlockFlingTime;
+
+ public void blockFling() {
+ mBlockFling = true;
+ mBlockFlingTime = SystemClock.uptimeMillis();
+ }
+
+ public void unblockFling() {
+ mBlockFling = false;
+ mBlockFlingTime = 0;
+ }
+
+ public void onEvent() {
+ // We prevent flinging after passing a state, but allow it if the user pauses briefly.
+ if (SystemClock.uptimeMillis() - mBlockFlingTime >= UNBLOCK_FLING_PAUSE_DURATION) {
+ mBlockFling = false;
+ }
+ }
+
+ public boolean isBlocked() {
+ return mBlockFling;
+ }
+}
diff --git a/src/com/android/launcher3/views/AbstractSlideInView.java b/src/com/android/launcher3/views/AbstractSlideInView.java
index 7c4529d..c8d1457 100644
--- a/src/com/android/launcher3/views/AbstractSlideInView.java
+++ b/src/com/android/launcher3/views/AbstractSlideInView.java
@@ -81,6 +81,7 @@
@Override
public void onAnimationEnd(Animator animation) {
mSwipeDetector.finishedScrolling();
+ announceAccessibilityChanges();
}
});
}
diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java
index 66d9498..2f142ac 100644
--- a/src/com/android/launcher3/views/BaseDragLayer.java
+++ b/src/com/android/launcher3/views/BaseDragLayer.java
@@ -117,12 +117,20 @@
View topView = AbstractFloatingView.getTopOpenView(mActivity);
if (topView != null) {
// Only add the top view as a child for accessibility when it is open
- childrenForAccessibility.add(topView);
+ addAccessibleChildToList(topView, childrenForAccessibility);
} else {
super.addChildrenForAccessibility(childrenForAccessibility);
}
}
+ protected void addAccessibleChildToList(View child, ArrayList<View> outList) {
+ if (child.isImportantForAccessibility()) {
+ outList.add(child);
+ } else {
+ child.addChildrenForAccessibility(outList);
+ }
+ }
+
@Override
public void onViewRemoved(View child) {
super.onViewRemoved(child);
diff --git a/src/com/android/launcher3/views/ScrimView.java b/src/com/android/launcher3/views/ScrimView.java
index a8fab5f..6bbce00 100644
--- a/src/com/android/launcher3/views/ScrimView.java
+++ b/src/com/android/launcher3/views/ScrimView.java
@@ -38,6 +38,7 @@
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
@@ -113,12 +114,17 @@
.getDimensionPixelSize(R.dimen.vertical_drag_handle_size);
mDragHandleBounds = new Rect(0, 0, mDragHandleSize, mDragHandleSize);
- mAccessibilityHelper = new AccessibilityHelper();
+ mAccessibilityHelper = createAccessibilityHelper();
ViewCompat.setAccessibilityDelegate(this, mAccessibilityHelper);
mAM = (AccessibilityManager) context.getSystemService(ACCESSIBILITY_SERVICE);
}
+ @NonNull
+ protected AccessibilityHelper createAccessibilityHelper() {
+ return new AccessibilityHelper();
+ }
+
@Override
public void setInsets(Rect insets) {
updateDragHandleBounds();
@@ -190,6 +196,9 @@
if (mCurrentFlatColor != 0) {
canvas.drawColor(mCurrentFlatColor);
}
+ if (mDragHandle != null) {
+ mDragHandle.draw(canvas);
+ }
}
@Override
@@ -323,7 +332,7 @@
: IMPORTANT_FOR_ACCESSIBILITY_AUTO);
}
- private class AccessibilityHelper extends ExploreByTouchHelper {
+ protected class AccessibilityHelper extends ExploreByTouchHelper {
private static final int DRAG_HANDLE_ID = 1;
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index a258485..5ce7e04 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
+import android.util.Pair;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@@ -72,7 +73,7 @@
mLauncher.getDragLayer().addView(this);
mIsOpen = false;
- open(true);
+ animateOpen();
}
@Override
@@ -129,20 +130,16 @@
return widget;
}
- private void open(boolean animate) {
+ private void animateOpen() {
if (mIsOpen || mOpenCloseAnimator.isRunning()) {
return;
}
mIsOpen = true;
setupNavBarColor();
- if (animate) {
- mOpenCloseAnimator.setValues(
- PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
- mOpenCloseAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
- mOpenCloseAnimator.start();
- } else {
- setTranslationShift(TRANSLATION_SHIFT_OPENED);
- }
+ mOpenCloseAnimator.setValues(
+ PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
+ mOpenCloseAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ mOpenCloseAnimator.start();
}
@Override
@@ -170,4 +167,10 @@
protected int getElementsRowCount() {
return 1;
}
+
+ @Override
+ protected Pair<View, String> getAccessibilityTarget() {
+ return Pair.create(findViewById(R.id.title), getContext().getString(
+ mIsOpen ? R.string.widgets_list : R.string.widgets_list_closed));
+ }
}
diff --git a/src/com/android/launcher3/widget/WidgetsFullSheet.java b/src/com/android/launcher3/widget/WidgetsFullSheet.java
index a622624..e94d81d 100644
--- a/src/com/android/launcher3/widget/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsFullSheet.java
@@ -21,8 +21,10 @@
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
+import android.util.Pair;
import android.view.LayoutInflater;
import android.view.MotionEvent;
+import android.view.View;
import android.view.animation.AnimationUtils;
import com.android.launcher3.Insettable;
@@ -55,6 +57,7 @@
mAdapter = new WidgetsListAdapter(context,
LayoutInflater.from(context), apps.getWidgetCache(), apps.getIconCache(),
this, this);
+
}
public WidgetsFullSheet(Context context, AttributeSet attrs) {
@@ -77,6 +80,12 @@
}
@Override
+ protected Pair<View, String> getAccessibilityTarget() {
+ return Pair.create(mRecyclerView, getContext().getString(
+ mIsOpen ? R.string.widgets_list : R.string.widgets_list_closed));
+ }
+
+ @Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mLauncher.getAppWidgetHost().addProviderChangeListener(this);
@@ -149,10 +158,6 @@
}
private void open(boolean animate) {
- if (mIsOpen) {
- return;
- }
- mIsOpen = true;
if (animate) {
if (mLauncher.getDragLayer().getInsets().bottom > 0) {
mContent.setAlpha(0);
@@ -180,6 +185,7 @@
} else {
setTranslationShift(TRANSLATION_SHIFT_OPENED);
mAdapter.setApplyBitmapDeferred(false, mRecyclerView);
+ post(this::announceAccessibilityChanges);
}
}
@@ -212,6 +218,7 @@
public static WidgetsFullSheet show(Launcher launcher, boolean animate) {
WidgetsFullSheet sheet = (WidgetsFullSheet) launcher.getLayoutInflater()
.inflate(R.layout.widgets_full_sheet, launcher.getDragLayer(), false);
+ sheet.mIsOpen = true;
launcher.getDragLayer().addView(sheet);
sheet.open(animate);
return sheet;
diff --git a/src/com/android/launcher3/widget/WidgetsRowViewHolder.java b/src/com/android/launcher3/widget/WidgetsRowViewHolder.java
index bc85db6..8f269a6 100644
--- a/src/com/android/launcher3/widget/WidgetsRowViewHolder.java
+++ b/src/com/android/launcher3/widget/WidgetsRowViewHolder.java
@@ -29,7 +29,8 @@
public WidgetsRowViewHolder(ViewGroup v) {
super(v);
- cellContainer = (ViewGroup) v.findViewById(R.id.widgets_cell_list);
- title = (BubbleTextView) v.findViewById(R.id.section);
+ cellContainer = v.findViewById(R.id.widgets_cell_list);
+ title = v.findViewById(R.id.section);
+ title.setAccessibilityDelegate(null);
}
}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsSwipeController.java b/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsSwipeController.java
index 80c2485..e9dc800 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsSwipeController.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsSwipeController.java
@@ -58,7 +58,7 @@
@Override
protected int getLogContainerTypeForNormalState() {
- return mLauncher.getDragLayer().isEventOverHotseat(mTouchDownEvent) ?
+ return mLauncher.getDragLayer().isEventOverView(mLauncher.getHotseat(), mTouchDownEvent) ?
ContainerType.HOTSEAT : ContainerType.WORKSPACE;
}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
index b8cd035..e9a47a7 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
@@ -16,12 +16,15 @@
package com.android.launcher3.uioverrides;
+import android.app.Activity;
import android.content.Context;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherStateManager.StateHandler;
import com.android.launcher3.util.TouchController;
+import java.io.PrintWriter;
+
public class UiFactory {
public static TouchController[] createTouchControllers(Launcher launcher) {
@@ -47,4 +50,9 @@
public static void onLauncherStateOrResumeChanged(Launcher launcher) { }
public static void onTrimMemory(Launcher launcher, int level) { }
+
+ public static boolean dumpActivity(Activity activity, PrintWriter writer) {
+ return false;
+ }
+
}