Merging ub-launcher3-qt-dev, build 5508646
Test: Manual Bug:112934365 [STOP SHIP BUG] Sysui Navigation Bar Prototype Tracking Bug:114136250 Have a more spartan RecentsActivity on android go Bug:118758133 Add logging to track undo box usage Bug:119992316 Widget screen won't close when tapping back or home button Bug:128857973 With dark display and black accent device theme, App list header not visible on all apps screen. Bug:129279637 [Logging] Long press|tap on app icon from Task should be logged Bug:129497226 Remove setInteractionState from the contract Bug:129723135 Broken tests: swipe from killed launcher doesn't open overview Bug:129806241 [a11y][Qt] Remove an app icon in Home screen, the popup "Item removed" with UNDO doesn't follow the settings of Time to take action. Bug:129985827 [Fully Gestural Navigation] Delay Recents animation when swiping up Bug:130851537 Recents and notification shelf both became nonresponsive after I "palmed" the screen while it was on. Bug:131095241 Recents Go should support landscape app => landscape thumbnail transition Bug:131303610 Backedup shortcut icons are not badged Bug:131339235 Don't layout empty task views if we have the real content Bug:131364673 [Failing test] FallbackRecentsTest Change-Id: I04018e14bd6d9ba77005e72fe20f4a3ede886abf
This commit is contained in:
@@ -18,5 +18,5 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@android:color/darker_gray"/>
|
||||
<corners android:radius="2dp"/>
|
||||
<corners android:radius="@dimen/task_thumbnail_corner_radius"/>
|
||||
</shape>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2019 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<dimen name="task_thumbnail_corner_radius">3dp</dimen>
|
||||
</resources>
|
||||
@@ -161,6 +161,13 @@ public final class ContentFillItemAnimator extends SimpleItemAnimator {
|
||||
|
||||
private void animateChangeImpl(ViewHolder viewHolder, long startDelay) {
|
||||
TaskItemView itemView = (TaskItemView) viewHolder.itemView;
|
||||
if (itemView.getAlpha() == 0) {
|
||||
// View is still not visible, so we can finish the change immediately.
|
||||
CONTENT_TRANSITION_PROGRESS.set(itemView, 1.0f);
|
||||
dispatchChangeFinished(viewHolder, true /* oldItem */);
|
||||
dispatchFinishedWhenDone();
|
||||
return;
|
||||
}
|
||||
final ObjectAnimator anim =
|
||||
ObjectAnimator.ofFloat(itemView, CONTENT_TRANSITION_PROGRESS, 0.0f, 1.0f);
|
||||
anim.setDuration(ITEM_CHANGE_DURATION).setStartDelay(startDelay);
|
||||
|
||||
@@ -16,17 +16,23 @@
|
||||
|
||||
package com.android.quickstep;
|
||||
|
||||
import static android.graphics.Shader.TileMode.CLAMP;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapShader;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
|
||||
/**
|
||||
@@ -39,11 +45,18 @@ public final class ThumbnailDrawable extends Drawable {
|
||||
private final Paint mPaint = new Paint();
|
||||
private final Matrix mMatrix = new Matrix();
|
||||
private final ThumbnailData mThumbnailData;
|
||||
private final BitmapShader mShader;
|
||||
private final RectF mDestRect = new RectF();
|
||||
private final int mCornerRadius;
|
||||
private int mRequestedOrientation;
|
||||
|
||||
public ThumbnailDrawable(@NonNull ThumbnailData thumbnailData, int requestedOrientation) {
|
||||
public ThumbnailDrawable(Resources res, @NonNull ThumbnailData thumbnailData,
|
||||
int requestedOrientation) {
|
||||
mThumbnailData = thumbnailData;
|
||||
mRequestedOrientation = requestedOrientation;
|
||||
mCornerRadius = (int) res.getDimension(R.dimen.task_thumbnail_corner_radius);
|
||||
mShader = new BitmapShader(mThumbnailData.thumbnail, CLAMP, CLAMP);
|
||||
mPaint.setShader(mShader);
|
||||
updateMatrix();
|
||||
}
|
||||
|
||||
@@ -64,12 +77,13 @@ public final class ThumbnailDrawable extends Drawable {
|
||||
if (mThumbnailData.thumbnail == null) {
|
||||
return;
|
||||
}
|
||||
canvas.drawBitmap(mThumbnailData.thumbnail, mMatrix, mPaint);
|
||||
canvas.drawRoundRect(mDestRect, mCornerRadius, mCornerRadius, mPaint);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBoundsChange(Rect bounds) {
|
||||
super.onBoundsChange(bounds);
|
||||
mDestRect.set(bounds);
|
||||
updateMatrix();
|
||||
}
|
||||
|
||||
@@ -125,5 +139,6 @@ public final class ThumbnailDrawable extends Drawable {
|
||||
}
|
||||
// Scale to fill.
|
||||
mMatrix.postScale(scaleX, scaleY);
|
||||
mShader.setLocalMatrix(mMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +177,8 @@ public final class TaskItemView extends LinearLayout {
|
||||
return mDefaultThumbnail;
|
||||
}
|
||||
int orientation = getResources().getConfiguration().orientation;
|
||||
return new ThumbnailDrawable(thumbnailData, orientation /* requestedOrientation */);
|
||||
return new ThumbnailDrawable(getResources(), thumbnailData,
|
||||
orientation /* requestedOrientation */);
|
||||
}
|
||||
|
||||
private @NonNull String getSafeLabel(@Nullable String label) {
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.quickstep.views;
|
||||
|
||||
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
|
||||
import static android.view.View.MeasureSpec.makeMeasureSpec;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
@@ -53,15 +56,20 @@ final class TaskThumbnailIconView extends ViewGroup {
|
||||
int width = height;
|
||||
setMeasuredDimension(width, height);
|
||||
|
||||
|
||||
int subItemSize = (int) (SUBITEM_FRAME_RATIO * height);
|
||||
if (mThumbnailView.getVisibility() != GONE) {
|
||||
int thumbnailHeightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
|
||||
int thumbnailWidthSpec = MeasureSpec.makeMeasureSpec(subItemSize, MeasureSpec.EXACTLY);
|
||||
boolean isPortrait =
|
||||
(getResources().getConfiguration().orientation == ORIENTATION_PORTRAIT);
|
||||
int thumbnailHeightSpec =
|
||||
makeMeasureSpec(isPortrait ? height : subItemSize, MeasureSpec.EXACTLY);
|
||||
int thumbnailWidthSpec =
|
||||
makeMeasureSpec(isPortrait ? subItemSize : width, MeasureSpec.EXACTLY);
|
||||
measureChild(mThumbnailView, thumbnailWidthSpec, thumbnailHeightSpec);
|
||||
}
|
||||
if (mIconView.getVisibility() != GONE) {
|
||||
int iconHeightSpec = MeasureSpec.makeMeasureSpec(subItemSize, MeasureSpec.EXACTLY);
|
||||
int iconWidthSpec = MeasureSpec.makeMeasureSpec(subItemSize, MeasureSpec.EXACTLY);
|
||||
int iconHeightSpec = makeMeasureSpec(subItemSize, MeasureSpec.EXACTLY);
|
||||
int iconWidthSpec = makeMeasureSpec(subItemSize, MeasureSpec.EXACTLY);
|
||||
measureChild(mIconView, iconWidthSpec, iconHeightSpec);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ enum ItemType {
|
||||
NOTIFICATION = 8;
|
||||
TASK = 9; // Each page of Recents UI (QuickStep)
|
||||
WEB_APP = 10;
|
||||
TASK_ICON = 11;
|
||||
}
|
||||
|
||||
// Used to define what type of container a Target would represent.
|
||||
@@ -115,6 +116,7 @@ enum ControlType {
|
||||
REMOTE_ACTION_SHORTCUT = 17;
|
||||
APP_USAGE_SETTINGS = 18;
|
||||
BACK_GESTURE = 19;
|
||||
UNDO = 20;
|
||||
}
|
||||
|
||||
enum TipType {
|
||||
|
||||
+2
-2
@@ -45,7 +45,7 @@ import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.systemui.shared.recents.ISystemUiProxy;
|
||||
import com.android.systemui.shared.system.InputMonitorCompat;
|
||||
import com.android.systemui.shared.system.NavigationBarCompat;
|
||||
import com.android.systemui.shared.system.QuickStepContract;
|
||||
|
||||
/**
|
||||
* Touch consumer for handling events to launch assistant from launcher
|
||||
@@ -103,7 +103,7 @@ public class AssistantTouchConsumer implements InputConsumer {
|
||||
mDistThreshold = res.getDimension(R.dimen.gestures_assistant_drag_threshold);
|
||||
mTimeThreshold = res.getInteger(R.integer.assistant_gesture_min_time_threshold);
|
||||
mAngleThreshold = res.getInteger(R.integer.assistant_gesture_corner_deg_threshold);
|
||||
mSlop = NavigationBarCompat.getQuickStepDragSlopPx();
|
||||
mSlop = QuickStepContract.getQuickStepDragSlopPx();
|
||||
mInputMonitorCompat = inputMonitorCompat;
|
||||
mActivityControlHelper = activityControlHelper;
|
||||
mState = STATE_INACTIVE;
|
||||
|
||||
+26
-1
@@ -16,14 +16,15 @@
|
||||
package com.android.quickstep;
|
||||
|
||||
import static android.view.View.TRANSLATION_Y;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.allapps.AllAppsTransitionController.SPRING_DAMPING_RATIO;
|
||||
import static com.android.launcher3.allapps.AllAppsTransitionController.SPRING_STIFFNESS;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.quickstep.WindowTransformSwipeHandler.RECENTS_ATTACH_DURATION;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
@@ -177,6 +178,8 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
|
||||
return new AnimationFactory() {
|
||||
private Animator mShelfAnim;
|
||||
private ShelfAnimState mShelfState;
|
||||
private Animator mAttachToWindowAnim;
|
||||
private boolean mIsAttachedToWindow;
|
||||
|
||||
@Override
|
||||
public void createActivityController(long transitionLength) {
|
||||
@@ -221,6 +224,28 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
|
||||
mShelfAnim.setDuration(duration);
|
||||
mShelfAnim.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecentsAttachedToAppWindow(boolean attached, boolean animate) {
|
||||
if (mIsAttachedToWindow == attached && animate) {
|
||||
return;
|
||||
}
|
||||
mIsAttachedToWindow = attached;
|
||||
if (mAttachToWindowAnim != null) {
|
||||
mAttachToWindowAnim.cancel();
|
||||
}
|
||||
mAttachToWindowAnim = ObjectAnimator.ofFloat(activity.getOverviewPanel(),
|
||||
RecentsView.CONTENT_ALPHA, attached ? 1 : 0);
|
||||
mAttachToWindowAnim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mAttachToWindowAnim = null;
|
||||
}
|
||||
});
|
||||
mAttachToWindowAnim.setInterpolator(ACCEL_DEACCEL);
|
||||
mAttachToWindowAnim.setDuration(animate ? RECENTS_ATTACH_DURATION : 0);
|
||||
mAttachToWindowAnim.start();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -60,7 +60,7 @@ import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.BackgroundExecutor;
|
||||
import com.android.systemui.shared.system.InputConsumerController;
|
||||
import com.android.systemui.shared.system.InputMonitorCompat;
|
||||
import com.android.systemui.shared.system.NavigationBarCompat;
|
||||
import com.android.systemui.shared.system.QuickStepContract;
|
||||
import com.android.systemui.shared.system.WindowManagerWrapper;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
@@ -152,8 +152,8 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
mDisplayRotation = display.getRotation();
|
||||
WindowManagerWrapper.getInstance().getStableInsets(mStableInsets);
|
||||
|
||||
mDragSlop = NavigationBarCompat.getQuickStepDragSlopPx();
|
||||
mTouchSlop = NavigationBarCompat.getQuickStepTouchSlopPx();
|
||||
mDragSlop = QuickStepContract.getQuickStepDragSlopPx();
|
||||
mTouchSlop = QuickStepContract.getQuickStepTouchSlopPx();
|
||||
|
||||
mPassedTouchSlop = mPassedDragSlop = continuingPreviousGesture;
|
||||
}
|
||||
@@ -267,6 +267,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
mMotionPauseDetector.setDisallowPause(upDist < mMotionPauseMinDisplacement
|
||||
|| isLikelyToStartNewTask);
|
||||
mMotionPauseDetector.addPosition(displacement, ev.getEventTime());
|
||||
mInteractionHandler.setIsLikelyToStartNewTask(isLikelyToStartNewTask);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
+88
-8
@@ -43,6 +43,7 @@ import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.TimeInterpolator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.content.Context;
|
||||
@@ -111,6 +112,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
implements SwipeAnimationListener, OnApplyWindowInsetsListener {
|
||||
private static final String TAG = WindowTransformSwipeHandler.class.getSimpleName();
|
||||
|
||||
private static final Rect TEMP_RECT = new Rect();
|
||||
|
||||
private static final String[] STATE_NAMES = DEBUG_STATES ? new String[16] : null;
|
||||
|
||||
private static int getFlagForIndex(int index, String name) {
|
||||
@@ -162,22 +165,23 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_LAUNCHER_STARTED;
|
||||
|
||||
enum GestureEndTarget {
|
||||
HOME(1, STATE_SCALED_CONTROLLER_HOME, true, false, ContainerType.WORKSPACE),
|
||||
HOME(1, STATE_SCALED_CONTROLLER_HOME, true, false, ContainerType.WORKSPACE, false),
|
||||
|
||||
RECENTS(1, STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT
|
||||
| STATE_SCREENSHOT_VIEW_SHOWN, true, false, ContainerType.TASKSWITCHER),
|
||||
| STATE_SCREENSHOT_VIEW_SHOWN, true, false, ContainerType.TASKSWITCHER, true),
|
||||
|
||||
NEW_TASK(0, STATE_START_NEW_TASK, false, true, ContainerType.APP),
|
||||
NEW_TASK(0, STATE_START_NEW_TASK, false, true, ContainerType.APP, true),
|
||||
|
||||
LAST_TASK(0, STATE_RESUME_LAST_TASK, false, true, ContainerType.APP);
|
||||
LAST_TASK(0, STATE_RESUME_LAST_TASK, false, true, ContainerType.APP, false);
|
||||
|
||||
GestureEndTarget(float endShift, int endState, boolean isLauncher, boolean canBeContinued,
|
||||
int containerType) {
|
||||
int containerType, boolean recentsAttachedToAppWindow) {
|
||||
this.endShift = endShift;
|
||||
this.endState = endState;
|
||||
this.isLauncher = isLauncher;
|
||||
this.canBeContinued = canBeContinued;
|
||||
this.containerType = containerType;
|
||||
this.recentsAttachedToAppWindow = recentsAttachedToAppWindow;
|
||||
}
|
||||
|
||||
/** 0 is app, 1 is overview */
|
||||
@@ -190,6 +194,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
public final boolean canBeContinued;
|
||||
/** Used to log where the user ended up after the gesture ends */
|
||||
public final int containerType;
|
||||
/** Whether RecentsView should be attached to the window as we animate to this target */
|
||||
public final boolean recentsAttachedToAppWindow;
|
||||
}
|
||||
|
||||
public static final long MAX_SWIPE_DURATION = 350;
|
||||
@@ -202,6 +208,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
private static final String SCREENSHOT_CAPTURED_EVT = "ScreenshotCaptured";
|
||||
|
||||
private static final long SHELF_ANIM_DURATION = 120;
|
||||
public static final long RECENTS_ATTACH_DURATION = 300;
|
||||
|
||||
/**
|
||||
* Used as the page index for logging when we return to the last task at the end of the gesture.
|
||||
@@ -254,6 +261,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
private int mLogAction = Touch.SWIPE;
|
||||
private int mLogDirection = Direction.UP;
|
||||
private PointF mDownPos;
|
||||
private boolean mIsLikelyToStartNewTask;
|
||||
|
||||
private final RecentsAnimationWrapper mRecentsAnimationWrapper;
|
||||
|
||||
@@ -277,6 +285,9 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
|
||||
mMode = SysUINavigationMode.getMode(context);
|
||||
initStateCallbacks();
|
||||
|
||||
DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(mContext).getDeviceProfile(mContext);
|
||||
initTransitionEndpoints(dp);
|
||||
}
|
||||
|
||||
private void initStateCallbacks() {
|
||||
@@ -434,6 +445,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
mAnimationFactory = mActivityControlHelper.prepareRecentsUI(mActivity,
|
||||
mWasLauncherAlreadyVisible, true,
|
||||
this::onAnimatorPlaybackControllerCreated);
|
||||
maybeUpdateRecentsAttachedState(false /* animate */);
|
||||
};
|
||||
if (mWasLauncherAlreadyVisible) {
|
||||
// Launcher is visible, but might be about to stop. Thus, if we prepare recents
|
||||
@@ -538,10 +550,65 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
setShelfState(isPaused ? PEEK : HIDE, FAST_OUT_SLOW_IN, SHELF_ANIM_DURATION);
|
||||
}
|
||||
|
||||
public void maybeUpdateRecentsAttachedState() {
|
||||
maybeUpdateRecentsAttachedState(true /* animate */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether to show or hide RecentsView. The window is always
|
||||
* synchronized with its corresponding TaskView in RecentsView, so if
|
||||
* RecentsView is shown, it will appear to be attached to the window.
|
||||
*
|
||||
* Note this method has no effect unless the navigation mode is NO_BUTTON.
|
||||
*/
|
||||
private void maybeUpdateRecentsAttachedState(boolean animate) {
|
||||
if (mMode != Mode.NO_BUTTON || mRecentsView == null) {
|
||||
return;
|
||||
}
|
||||
RemoteAnimationTargetCompat runningTaskTarget = mRecentsAnimationWrapper.targetSet == null
|
||||
? null
|
||||
: mRecentsAnimationWrapper.targetSet.findTask(mRunningTaskId);
|
||||
final boolean recentsAttachedToAppWindow;
|
||||
int runningTaskIndex = mRecentsView.getRunningTaskIndex();
|
||||
if (mContinuingLastGesture) {
|
||||
recentsAttachedToAppWindow = true;
|
||||
animate = false;
|
||||
} else if (runningTaskTarget != null && isNotInRecents(runningTaskTarget)) {
|
||||
// The window is going away so make sure recents is always visible in this case.
|
||||
recentsAttachedToAppWindow = true;
|
||||
animate = false;
|
||||
} else {
|
||||
if (mGestureEndTarget != null) {
|
||||
recentsAttachedToAppWindow = mGestureEndTarget.recentsAttachedToAppWindow;
|
||||
} else {
|
||||
recentsAttachedToAppWindow = mIsShelfPeeking || mIsLikelyToStartNewTask;
|
||||
}
|
||||
if (animate) {
|
||||
// Only animate if an adjacent task view is visible on screen.
|
||||
TaskView adjacentTask1 = mRecentsView.getTaskViewAt(runningTaskIndex + 1);
|
||||
TaskView adjacentTask2 = mRecentsView.getTaskViewAt(runningTaskIndex - 1);
|
||||
animate = (adjacentTask1 != null && adjacentTask1.getGlobalVisibleRect(TEMP_RECT))
|
||||
|| (adjacentTask2 != null && adjacentTask2.getGlobalVisibleRect(TEMP_RECT));
|
||||
}
|
||||
}
|
||||
mAnimationFactory.setRecentsAttachedToAppWindow(recentsAttachedToAppWindow, animate);
|
||||
}
|
||||
|
||||
public void setIsLikelyToStartNewTask(boolean isLikelyToStartNewTask) {
|
||||
if (mIsLikelyToStartNewTask != isLikelyToStartNewTask) {
|
||||
mIsLikelyToStartNewTask = isLikelyToStartNewTask;
|
||||
maybeUpdateRecentsAttachedState();
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator, long duration) {
|
||||
mAnimationFactory.setShelfState(shelfState, interpolator, duration);
|
||||
boolean wasShelfPeeking = mIsShelfPeeking;
|
||||
mIsShelfPeeking = shelfState == PEEK;
|
||||
if (mIsShelfPeeking != wasShelfPeeking) {
|
||||
maybeUpdateRecentsAttachedState();
|
||||
}
|
||||
if (mRecentsView != null && shelfState.shouldPreformHaptic) {
|
||||
mRecentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
|
||||
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
|
||||
@@ -869,6 +936,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
Interpolator interpolator, GestureEndTarget target, PointF velocityPxPerMs) {
|
||||
mGestureEndTarget = target;
|
||||
|
||||
maybeUpdateRecentsAttachedState();
|
||||
|
||||
if (mGestureEndTarget == HOME) {
|
||||
HomeAnimationFactory homeAnimFactory;
|
||||
if (mActivity != null) {
|
||||
@@ -902,8 +971,15 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
windowAnim.start(velocityPxPerMs);
|
||||
mLauncherTransitionController = null;
|
||||
} else {
|
||||
Animator windowAnim = mCurrentShift.animateToValue(start, end);
|
||||
ValueAnimator windowAnim = mCurrentShift.animateToValue(start, end);
|
||||
windowAnim.setDuration(duration).setInterpolator(interpolator);
|
||||
windowAnim.addUpdateListener(valueAnimator -> {
|
||||
if (mRecentsView != null && mRecentsView.getVisibility() != View.VISIBLE) {
|
||||
// Views typically don't compute scroll when invisible as an optimization,
|
||||
// but in our case we need to since the window offset depends on the scroll.
|
||||
mRecentsView.computeScroll();
|
||||
}
|
||||
});
|
||||
windowAnim.addListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
@@ -1177,10 +1253,14 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||
}
|
||||
|
||||
public static float getHiddenTargetAlpha(RemoteAnimationTargetCompat app, Float expectedAlpha) {
|
||||
if (!(app.isNotInRecents
|
||||
|| app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME)) {
|
||||
if (!isNotInRecents(app)) {
|
||||
return 0;
|
||||
}
|
||||
return expectedAlpha;
|
||||
}
|
||||
|
||||
private static boolean isNotInRecents(RemoteAnimationTargetCompat app) {
|
||||
return app.isNotInRecents
|
||||
|| app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,8 @@ import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.launcher3.util.PendingAnimation;
|
||||
@@ -365,9 +367,11 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean showTaskMenu() {
|
||||
private boolean showTaskMenu(int action) {
|
||||
getRecentsView().snapToPage(getRecentsView().indexOfChild(this));
|
||||
mMenuView = TaskMenuView.showForTask(this);
|
||||
UserEventDispatcher.newInstance(getContext()).logActionOnItem(action, Direction.NONE,
|
||||
LauncherLogProto.ItemType.TASK_ICON);
|
||||
if (mMenuView != null) {
|
||||
mMenuView.addOnAttachStateChangeListener(mTaskMenuStateListener);
|
||||
}
|
||||
@@ -377,10 +381,10 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
private void setIcon(Drawable icon) {
|
||||
if (icon != null) {
|
||||
mIconView.setDrawable(icon);
|
||||
mIconView.setOnClickListener(v -> showTaskMenu());
|
||||
mIconView.setOnClickListener(v -> showTaskMenu(Touch.TAP));
|
||||
mIconView.setOnLongClickListener(v -> {
|
||||
requestDisallowInterceptTouchEvent(true);
|
||||
return showTaskMenu();
|
||||
return showTaskMenu(Touch.LONGPRESS);
|
||||
});
|
||||
} else {
|
||||
mIconView.setDrawable(null);
|
||||
|
||||
+12
@@ -32,6 +32,8 @@ import com.android.launcher3.util.TouchController;
|
||||
import com.android.quickstep.RecentsModel;
|
||||
import com.android.systemui.shared.recents.ISystemUiProxy;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* TouchController for handling touch events that get sent to the StatusBar. Once the
|
||||
* Once the event delta y passes the touch slop, the events start getting forwarded.
|
||||
@@ -45,6 +47,7 @@ public class StatusBarTouchController implements TouchController {
|
||||
protected final TouchEventTranslator mTranslator;
|
||||
private final float mTouchSlop;
|
||||
private ISystemUiProxy mSysUiProxy;
|
||||
private int mLastAction;
|
||||
|
||||
/* If {@code false}, this controller should not handle the input {@link MotionEvent}.*/
|
||||
private boolean mCanIntercept;
|
||||
@@ -56,9 +59,18 @@ public class StatusBarTouchController implements TouchController {
|
||||
mTranslator = new TouchEventTranslator((MotionEvent ev)-> dispatchTouchEvent(ev));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(String prefix, PrintWriter writer) {
|
||||
writer.println(prefix + "mCanIntercept:" + mCanIntercept);
|
||||
writer.println(prefix + "mLastAction:" + MotionEvent.actionToString(mLastAction));
|
||||
writer.println(prefix + "mSysUiProxy available:" + (mSysUiProxy != null));
|
||||
|
||||
}
|
||||
|
||||
private void dispatchTouchEvent(MotionEvent ev) {
|
||||
try {
|
||||
if (mSysUiProxy != null) {
|
||||
mLastAction = ev.getActionMasked();
|
||||
mSysUiProxy.onStatusBarMotionEvent(ev);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
|
||||
@@ -27,6 +27,10 @@ import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
@@ -37,10 +41,6 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
/**
|
||||
* Utility class which abstracts out the logical differences between Launcher and RecentsActivity.
|
||||
*/
|
||||
@@ -122,6 +122,13 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
|
||||
|
||||
default void setShelfState(ShelfAnimState animState, Interpolator interpolator,
|
||||
long duration) { }
|
||||
|
||||
/**
|
||||
* @param attached Whether to show RecentsView alongside the app window. If false, recents
|
||||
* will be hidden by some property we can animate, e.g. alpha.
|
||||
* @param animate Whether to animate recents to/from its new attached state.
|
||||
*/
|
||||
default void setRecentsAttachedToAppWindow(boolean attached, boolean animate) { }
|
||||
}
|
||||
|
||||
interface HomeAnimationFactory {
|
||||
|
||||
@@ -15,10 +15,6 @@
|
||||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_QUICK_SCRUB;
|
||||
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_SWIPE_UP;
|
||||
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
@@ -34,13 +30,7 @@ import com.android.systemui.shared.recents.ISystemUiProxy;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
/**
|
||||
* Sets overview interaction flags, such as:
|
||||
*
|
||||
* - FLAG_DISABLE_QUICK_SCRUB
|
||||
* - FLAG_DISABLE_SWIPE_UP
|
||||
* - FLAG_SHOW_OVERVIEW_BUTTON
|
||||
*
|
||||
* @see com.android.systemui.shared.system.NavigationBarCompat.InteractionType and associated flags.
|
||||
* Sets alpha for the back button
|
||||
*/
|
||||
public class OverviewInteractionState {
|
||||
|
||||
@@ -50,11 +40,10 @@ public class OverviewInteractionState {
|
||||
|
||||
// We do not need any synchronization for this variable as its only written on UI thread.
|
||||
public static final MainThreadInitializedObject<OverviewInteractionState> INSTANCE =
|
||||
new MainThreadInitializedObject<>((c) -> new OverviewInteractionState(c));
|
||||
new MainThreadInitializedObject<>(OverviewInteractionState::new);
|
||||
|
||||
private static final int MSG_SET_PROXY = 200;
|
||||
private static final int MSG_SET_BACK_BUTTON_ALPHA = 201;
|
||||
private static final int MSG_APPLY_FLAGS = 202;
|
||||
|
||||
private final Context mContext;
|
||||
private final Handler mUiHandler;
|
||||
@@ -62,7 +51,6 @@ public class OverviewInteractionState {
|
||||
|
||||
// These are updated on the background thread
|
||||
private ISystemUiProxy mISystemUiProxy;
|
||||
private boolean mSwipeUpEnabled;
|
||||
private float mBackButtonAlpha = 1;
|
||||
|
||||
private OverviewInteractionState(Context context) {
|
||||
@@ -83,7 +71,7 @@ public class OverviewInteractionState {
|
||||
}
|
||||
|
||||
public void setBackButtonAlpha(float alpha, boolean animate) {
|
||||
if (!mSwipeUpEnabled) {
|
||||
if (!modeSupportsGestures()) {
|
||||
alpha = 1;
|
||||
}
|
||||
mUiHandler.removeMessages(MSG_SET_BACK_BUTTON_ALPHA);
|
||||
@@ -111,30 +99,10 @@ public class OverviewInteractionState {
|
||||
case MSG_SET_BACK_BUTTON_ALPHA:
|
||||
applyBackButtonAlpha((float) msg.obj, msg.arg1 == 1);
|
||||
return true;
|
||||
case MSG_APPLY_FLAGS:
|
||||
break;
|
||||
}
|
||||
applyFlags();
|
||||
return true;
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private void applyFlags() {
|
||||
if (mISystemUiProxy == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int flags = FLAG_DISABLE_QUICK_SCRUB;
|
||||
if (!mSwipeUpEnabled) {
|
||||
flags = FLAG_DISABLE_SWIPE_UP | FLAG_DISABLE_QUICK_SCRUB | FLAG_SHOW_OVERVIEW_BUTTON;
|
||||
}
|
||||
try {
|
||||
mISystemUiProxy.setInteractionState(flags);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Unable to update overview interaction flags", e);
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private void applyBackButtonAlpha(float alpha, boolean animate) {
|
||||
if (mISystemUiProxy == null) {
|
||||
@@ -148,18 +116,20 @@ public class OverviewInteractionState {
|
||||
}
|
||||
|
||||
private void onNavigationModeChanged(SysUINavigationMode.Mode mode) {
|
||||
mSwipeUpEnabled = mode.hasGestures;
|
||||
resetHomeBounceSeenOnQuickstepEnabledFirstTime();
|
||||
mBgHandler.obtainMessage(MSG_APPLY_FLAGS).sendToTarget();
|
||||
}
|
||||
|
||||
private void resetHomeBounceSeenOnQuickstepEnabledFirstTime() {
|
||||
if (mSwipeUpEnabled && !Utilities.getPrefs(mContext).getBoolean(
|
||||
if (modeSupportsGestures() && !Utilities.getPrefs(mContext).getBoolean(
|
||||
HAS_ENABLED_QUICKSTEP_ONCE, true)) {
|
||||
Utilities.getPrefs(mContext).edit()
|
||||
.putBoolean(HAS_ENABLED_QUICKSTEP_ONCE, true)
|
||||
.putBoolean(DiscoveryBounce.HOME_BOUNCE_SEEN, false)
|
||||
.apply();
|
||||
.putBoolean(HAS_ENABLED_QUICKSTEP_ONCE, true)
|
||||
.putBoolean(DiscoveryBounce.HOME_BOUNCE_SEEN, false)
|
||||
.apply();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean modeSupportsGestures() {
|
||||
return SysUINavigationMode.getMode(mContext).hasGestures;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,21 +12,29 @@ import android.app.PendingIntent;
|
||||
import android.app.usage.UsageStatsManager;
|
||||
import android.content.Intent;
|
||||
|
||||
import androidx.test.filters.LargeTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.quickstep.views.DigitalWellBeingToast;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
@LargeTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class DigitalWellBeingToastTest extends AbstractQuickStepTest {
|
||||
private static final String CALCULATOR_PACKAGE =
|
||||
resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR);
|
||||
|
||||
@Test
|
||||
public void testToast() throws Exception {
|
||||
startAppFast(CALCULATOR_PACKAGE);
|
||||
|
||||
final UsageStatsManager usageStatsManager =
|
||||
mTargetContext.getSystemService(UsageStatsManager.class);
|
||||
final int observerId = 0;
|
||||
|
||||
@@ -32,6 +32,7 @@ import android.app.Instrumentation;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import androidx.test.filters.LargeTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
@@ -65,10 +66,11 @@ public class FallbackRecentsTest {
|
||||
|
||||
@Rule public final TestRule mSetLauncherCommand;
|
||||
|
||||
public FallbackRecentsTest() {
|
||||
public FallbackRecentsTest() throws RemoteException {
|
||||
Instrumentation instrumentation = getInstrumentation();
|
||||
Context context = instrumentation.getContext();
|
||||
mDevice = UiDevice.getInstance(instrumentation);
|
||||
mDevice.setOrientationNatural();
|
||||
mLauncher = new LauncherInstrumentation(instrumentation);
|
||||
|
||||
mQuickstepOnOffExecutor = new NavigationModeSwitchRule(mLauncher);
|
||||
|
||||
@@ -88,7 +88,6 @@ public class StartLauncherViaGestureTests extends AbstractQuickStepTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore // b/129723135
|
||||
@NavigationModeSwitch
|
||||
public void testStressSwipeToOverview() {
|
||||
for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) {
|
||||
|
||||
@@ -19,12 +19,13 @@
|
||||
|
||||
<resources>
|
||||
<!-- Launcher theme -->
|
||||
<style name="BaseLauncherTheme" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar">
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
<style name="BaseLauncherTheme" parent="@android:style/Theme.DeviceDefault.DayNight">
|
||||
<item name="android:colorBackgroundCacheHint">@null</item>
|
||||
<item name="android:windowShowWallpaper">true</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:colorEdgeEffect">#FF757575</item>
|
||||
<item name="android:windowActionBar">false</item>
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowShowWallpaper">true</item>
|
||||
</style>
|
||||
|
||||
<style name="LauncherTheme" parent="@style/BaseLauncherTheme">
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.UNDO;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
@@ -121,8 +124,12 @@ public class DeleteDropTarget extends ButtonDropTarget {
|
||||
int itemPage = mLauncher.getWorkspace().getCurrentPage();
|
||||
onAccessibilityDrop(null, item);
|
||||
ModelWriter modelWriter = mLauncher.getModelWriter();
|
||||
Runnable onUndoClicked = () -> {
|
||||
modelWriter.abortDelete(itemPage);
|
||||
mLauncher.getUserEventDispatcher().logActionOnControl(TAP, UNDO);
|
||||
};
|
||||
Snackbar.show(mLauncher, R.string.item_removed, R.string.undo,
|
||||
modelWriter::commitDelete, () -> modelWriter.abortDelete(itemPage));
|
||||
modelWriter::commitDelete, onUndoClicked);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -75,6 +75,8 @@ import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.animation.OvershootInterpolator;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.DropTarget.DragObject;
|
||||
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
|
||||
import com.android.launcher3.allapps.AllAppsContainerView;
|
||||
@@ -150,9 +152,6 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Default launcher application.
|
||||
*/
|
||||
@@ -2198,7 +2197,9 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
InstallShortcutReceiver.FLAG_LOADER_RUNNING, this);
|
||||
|
||||
// When undoing the removal of the last item on a page, return to that page.
|
||||
mWorkspace.setCurrentPage(pageBoundFirst);
|
||||
// Since we are just resetting the current page without user interaction,
|
||||
// override the previous page so we don't log the page switch.
|
||||
mWorkspace.setCurrentPage(pageBoundFirst, pageBoundFirst /* overridePrevPage */);
|
||||
|
||||
TraceHelper.endSection("finishBindingItems");
|
||||
}
|
||||
@@ -2345,7 +2346,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
writer.println(" mPendingActivityResult=" + mPendingActivityResult);
|
||||
writer.println(" mRotationHelper: " + mRotationHelper);
|
||||
// Extra logging for b/116853349
|
||||
mDragLayer.dumpAlpha(writer);
|
||||
mDragLayer.dump(prefix, writer);
|
||||
mStateManager.dump(prefix, writer);
|
||||
dumpMisc(writer);
|
||||
|
||||
try {
|
||||
|
||||
@@ -50,6 +50,7 @@ import com.android.launcher3.anim.PropertySetter;
|
||||
import com.android.launcher3.anim.PropertySetter.AnimatedPropertySetter;
|
||||
import com.android.launcher3.uioverrides.UiFactory;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
@@ -144,6 +145,15 @@ public class LauncherStateManager {
|
||||
return mCurrentStableState;
|
||||
}
|
||||
|
||||
public void dump(String prefix, PrintWriter writer) {
|
||||
writer.println(prefix + "LauncherState");
|
||||
writer.println(prefix + "\tmLastStableState:" + mLastStableState);
|
||||
writer.println(prefix + "\tmCurrentStableState:" + mCurrentStableState);
|
||||
writer.println(prefix + "\tmState:" + mState);
|
||||
writer.println(prefix + "\tmRestState:" + mRestState);
|
||||
writer.println(prefix + "\tisInTransition:" + (mConfig.mCurrentAnimation != null));
|
||||
}
|
||||
|
||||
public StateHandler[] getStateHandlers() {
|
||||
if (mStateHandlers == null) {
|
||||
mStateHandlers = UiFactory.getStateHandler(mLauncher);
|
||||
|
||||
@@ -300,10 +300,14 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
return page;
|
||||
}
|
||||
|
||||
public void setCurrentPage(int currentPage) {
|
||||
setCurrentPage(currentPage, INVALID_PAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current page.
|
||||
*/
|
||||
public void setCurrentPage(int currentPage) {
|
||||
public void setCurrentPage(int currentPage, int overridePrevPage) {
|
||||
if (!mScroller.isFinished()) {
|
||||
abortScrollerAnimation(true);
|
||||
}
|
||||
@@ -312,7 +316,7 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
if (getChildCount() == 0) {
|
||||
return;
|
||||
}
|
||||
int prevPage = mCurrentPage;
|
||||
int prevPage = overridePrevPage != INVALID_PAGE ? overridePrevPage : mCurrentPage;
|
||||
mCurrentPage = validateNewPage(currentPage);
|
||||
updateCurrentPageScroll();
|
||||
notifyPageSwitchListener(prevPage);
|
||||
|
||||
@@ -106,4 +106,11 @@ public class AccessibilityManagerCompat {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int getRecommendedTimeoutMillis(Context context, int originalTimeout, int flags) {
|
||||
if (Utilities.ATLEAST_Q) {
|
||||
return getManager(context).getRecommendedTimeoutMillis(originalTimeout, flags);
|
||||
}
|
||||
return originalTimeout;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -696,5 +696,4 @@ public class DragController implements DragDriver.EventListener, TouchController
|
||||
public void removeDropTarget(DropTarget target) {
|
||||
mDropTargets.remove(target);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Class for handling model updates.
|
||||
@@ -151,15 +152,13 @@ public class ModelWriter {
|
||||
public void moveItemInDatabase(final ItemInfo item,
|
||||
int container, int screenId, int cellX, int cellY) {
|
||||
updateItemInfoProps(item, container, screenId, cellX, cellY);
|
||||
|
||||
final ContentWriter writer = new ContentWriter(mContext)
|
||||
.put(Favorites.CONTAINER, item.container)
|
||||
.put(Favorites.CELLX, item.cellX)
|
||||
.put(Favorites.CELLY, item.cellY)
|
||||
.put(Favorites.RANK, item.rank)
|
||||
.put(Favorites.SCREEN, item.screenId);
|
||||
|
||||
enqueueDeleteRunnable(new UpdateItemRunnable(item, writer));
|
||||
enqueueDeleteRunnable(new UpdateItemRunnable(item, () ->
|
||||
new ContentWriter(mContext)
|
||||
.put(Favorites.CONTAINER, item.container)
|
||||
.put(Favorites.CELLX, item.cellX)
|
||||
.put(Favorites.CELLY, item.cellY)
|
||||
.put(Favorites.RANK, item.rank)
|
||||
.put(Favorites.SCREEN, item.screenId)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,25 +194,26 @@ public class ModelWriter {
|
||||
item.spanX = spanX;
|
||||
item.spanY = spanY;
|
||||
|
||||
final ContentWriter writer = new ContentWriter(mContext)
|
||||
.put(Favorites.CONTAINER, item.container)
|
||||
.put(Favorites.CELLX, item.cellX)
|
||||
.put(Favorites.CELLY, item.cellY)
|
||||
.put(Favorites.RANK, item.rank)
|
||||
.put(Favorites.SPANX, item.spanX)
|
||||
.put(Favorites.SPANY, item.spanY)
|
||||
.put(Favorites.SCREEN, item.screenId);
|
||||
|
||||
mWorkerExecutor.execute(new UpdateItemRunnable(item, writer));
|
||||
mWorkerExecutor.execute(new UpdateItemRunnable(item, () ->
|
||||
new ContentWriter(mContext)
|
||||
.put(Favorites.CONTAINER, item.container)
|
||||
.put(Favorites.CELLX, item.cellX)
|
||||
.put(Favorites.CELLY, item.cellY)
|
||||
.put(Favorites.RANK, item.rank)
|
||||
.put(Favorites.SPANX, item.spanX)
|
||||
.put(Favorites.SPANY, item.spanY)
|
||||
.put(Favorites.SCREEN, item.screenId)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an item to the database in a specified container.
|
||||
*/
|
||||
public void updateItemInDatabase(ItemInfo item) {
|
||||
ContentWriter writer = new ContentWriter(mContext);
|
||||
item.onAddToDatabase(writer);
|
||||
mWorkerExecutor.execute(new UpdateItemRunnable(item, writer));
|
||||
mWorkerExecutor.execute(new UpdateItemRunnable(item, () -> {
|
||||
ContentWriter writer = new ContentWriter(mContext);
|
||||
item.onAddToDatabase(writer);
|
||||
return writer;
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,17 +224,18 @@ public class ModelWriter {
|
||||
int container, int screenId, int cellX, int cellY) {
|
||||
updateItemInfoProps(item, container, screenId, cellX, cellY);
|
||||
|
||||
final ContentWriter writer = new ContentWriter(mContext);
|
||||
final ContentResolver cr = mContext.getContentResolver();
|
||||
item.onAddToDatabase(writer);
|
||||
|
||||
item.id = Settings.call(cr, Settings.METHOD_NEW_ITEM_ID).getInt(Settings.EXTRA_VALUE);
|
||||
writer.put(Favorites._ID, item.id);
|
||||
|
||||
ModelVerifier verifier = new ModelVerifier();
|
||||
|
||||
final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
|
||||
mWorkerExecutor.execute(() -> {
|
||||
// Write the item on background thread, as some properties might have been updated in
|
||||
// the background.
|
||||
final ContentWriter writer = new ContentWriter(mContext);
|
||||
item.onAddToDatabase(writer);
|
||||
writer.put(Favorites._ID, item.id);
|
||||
|
||||
cr.insert(Favorites.CONTENT_URI, writer.getValues(mContext));
|
||||
|
||||
synchronized (mBgDataModel) {
|
||||
@@ -354,10 +355,10 @@ public class ModelWriter {
|
||||
|
||||
private class UpdateItemRunnable extends UpdateItemBaseRunnable {
|
||||
private final ItemInfo mItem;
|
||||
private final ContentWriter mWriter;
|
||||
private final Supplier<ContentWriter> mWriter;
|
||||
private final int mItemId;
|
||||
|
||||
UpdateItemRunnable(ItemInfo item, ContentWriter writer) {
|
||||
UpdateItemRunnable(ItemInfo item, Supplier<ContentWriter> writer) {
|
||||
mItem = item;
|
||||
mWriter = writer;
|
||||
mItemId = item.id;
|
||||
@@ -366,7 +367,8 @@ public class ModelWriter {
|
||||
@Override
|
||||
public void run() {
|
||||
Uri uri = Favorites.getContentUri(mItemId);
|
||||
mContext.getContentResolver().update(uri, mWriter.getValues(mContext), null, null);
|
||||
mContext.getContentResolver().update(uri, mWriter.get().getValues(mContext),
|
||||
null, null);
|
||||
updateItemArrays(mItem, mItemId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,12 +16,18 @@
|
||||
|
||||
package com.android.launcher3.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Supports various IO utility functions
|
||||
@@ -52,4 +58,23 @@ public class IOUtils {
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to debug binary data
|
||||
*/
|
||||
public static String createTempFile(Context context, byte[] data) {
|
||||
if (!FeatureFlags.IS_DOGFOOD_BUILD) {
|
||||
throw new IllegalStateException("Method only allowed in development mode");
|
||||
}
|
||||
|
||||
String name = UUID.randomUUID().toString();
|
||||
File file = new File(context.getCacheDir(), name);
|
||||
try (FileOutputStream fo = new FileOutputStream(file)) {
|
||||
fo.write(data);
|
||||
fo.flush();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return file.getAbsolutePath();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ package com.android.launcher3.util;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
public interface TouchController {
|
||||
|
||||
/**
|
||||
@@ -29,4 +31,6 @@ public interface TouchController {
|
||||
* Called when the draglayer receives a intercept touch event.
|
||||
*/
|
||||
boolean onControllerInterceptTouchEvent(MotionEvent ev);
|
||||
|
||||
default void dump(String prefix, PrintWriter writer) { }
|
||||
}
|
||||
|
||||
@@ -383,8 +383,13 @@ public abstract class BaseDragLayer<T extends Context & ActivityContext>
|
||||
return mMultiValueAlpha.getProperty(index);
|
||||
}
|
||||
|
||||
public void dumpAlpha(PrintWriter writer) {
|
||||
writer.println(" dragLayerAlpha : " + mMultiValueAlpha );
|
||||
public void dump(String prefix, PrintWriter writer) {
|
||||
writer.println(prefix + "DragLayer");
|
||||
if (mActiveController != null) {
|
||||
writer.println(prefix + "\tactiveController: " + mActiveController);
|
||||
mActiveController.dump(prefix + "\t", writer);
|
||||
}
|
||||
writer.println(prefix + "\tdragLayerAlpha : " + mMultiValueAlpha );
|
||||
}
|
||||
|
||||
public static class LayoutParams extends InsettableFrameLayout.LayoutParams {
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.launcher3.views;
|
||||
|
||||
import static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_CONTROLS;
|
||||
import static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_TEXT;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Rect;
|
||||
@@ -29,6 +32,7 @@ import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
|
||||
/**
|
||||
@@ -38,7 +42,7 @@ public class Snackbar extends AbstractFloatingView {
|
||||
|
||||
private static final long SHOW_DURATION_MS = 180;
|
||||
private static final long HIDE_DURATION_MS = 180;
|
||||
private static final long TIMEOUT_DURATION_MS = 4000;
|
||||
private static final int TIMEOUT_DURATION_MS = 4000;
|
||||
|
||||
private final Launcher mLauncher;
|
||||
private Runnable mOnDismissed;
|
||||
@@ -131,7 +135,9 @@ public class Snackbar extends AbstractFloatingView {
|
||||
.setDuration(SHOW_DURATION_MS)
|
||||
.setInterpolator(Interpolators.ACCEL_DEACCEL)
|
||||
.start();
|
||||
snackbar.postDelayed(() -> snackbar.close(true), TIMEOUT_DURATION_MS);
|
||||
int timeout = AccessibilityManagerCompat.getRecommendedTimeoutMillis(launcher,
|
||||
TIMEOUT_DURATION_MS, FLAG_CONTENT_TEXT | FLAG_CONTENT_CONTROLS);
|
||||
snackbar.postDelayed(() -> snackbar.close(true), timeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user