Merging from ub-launcher3-rvc-dev @ build 6492476
Bug: 150504032 Test: manual, presubmit on the source branch x20/teams/android-launcher/merge/ub-launcher3-rvc-dev_rvc-dev_6492476.html Change-Id: I96b36965f7b471eb77aa78a8b923ed9298e8a02f
This commit is contained in:
commit
6e0d05fc41
|
@ -129,6 +129,7 @@ LOCAL_AAPT2_ONLY := true
|
|||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
LOCAL_STATIC_JAVA_LIBRARIES := \
|
||||
SystemUI-statsd \
|
||||
SystemUISharedLib \
|
||||
launcherprotosnano \
|
||||
launcher_log_protos_lite
|
||||
|
@ -201,6 +202,7 @@ LOCAL_USE_AAPT2 := true
|
|||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
LOCAL_STATIC_JAVA_LIBRARIES := \
|
||||
SystemUI-statsd \
|
||||
SystemUISharedLib \
|
||||
launcherprotosnano \
|
||||
launcher_log_protos_lite
|
||||
|
|
|
@ -26,6 +26,7 @@ message ItemInfo {
|
|||
Task task = 2;
|
||||
Shortcut shortcut = 3;
|
||||
Widget widget = 4;
|
||||
FolderIcon folder_icon = 9;
|
||||
}
|
||||
// When used for launch event, stores the global predictive rank
|
||||
optional int32 rank = 5;
|
||||
|
@ -92,6 +93,11 @@ message Task {
|
|||
optional int32 index = 3;
|
||||
}
|
||||
|
||||
// Represents folder in a closed state.
|
||||
message FolderIcon {
|
||||
optional int32 cardinality = 1;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// Containers
|
||||
|
||||
|
|
|
@ -24,13 +24,13 @@
|
|||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="32dp"
|
||||
android:backgroundTint="?android:attr/colorAccent"
|
||||
android:backgroundTint="?attr/eduHalfSheetBGColor"
|
||||
android:background="@drawable/bottom_sheet_top_border" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/colorAccent"
|
||||
android:background="?attr/eduHalfSheetBGColor"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
|
|
|
@ -16,39 +16,24 @@
|
|||
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
||||
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_SCALE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
|
||||
import static com.android.quickstep.TaskViewUtils.findTaskViewToLaunch;
|
||||
import static com.android.quickstep.TaskViewUtils.getRecentsWindowAnimator;
|
||||
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.LauncherState.ScaleAndTranslation;
|
||||
import com.android.launcher3.allapps.AllAppsTransitionController;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.anim.SpringAnimationBuilder;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
|
@ -59,13 +44,6 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
|||
*/
|
||||
public final class LauncherAppTransitionManagerImpl extends QuickstepAppTransitionManagerImpl {
|
||||
|
||||
public static final int INDEX_SHELF_ANIM = 0;
|
||||
public static final int INDEX_RECENTS_FADE_ANIM = 1;
|
||||
public static final int INDEX_RECENTS_TRANSLATE_X_ANIM = 2;
|
||||
public static final int INDEX_PAUSE_TO_OVERVIEW_ANIM = 3;
|
||||
|
||||
public static final long ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW = 300;
|
||||
|
||||
public LauncherAppTransitionManagerImpl(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
@ -151,77 +129,4 @@ public final class LauncherAppTransitionManagerImpl extends QuickstepAppTransiti
|
|||
mLauncher.getStateManager().reapplyState();
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStateElementAnimationsCount() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Animator createStateElementAnimation(int index, float... values) {
|
||||
switch (index) {
|
||||
case INDEX_SHELF_ANIM: {
|
||||
AllAppsTransitionController aatc = mLauncher.getAllAppsController();
|
||||
Animator springAnim = aatc.createSpringAnimation(values);
|
||||
|
||||
if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
|
||||
// Translate hotseat with the shelf until reaching overview.
|
||||
float overviewProgress = OVERVIEW.getVerticalProgress(mLauncher);
|
||||
ScaleAndTranslation sat = OVERVIEW.getHotseatScaleAndTranslation(mLauncher);
|
||||
float shiftRange = aatc.getShiftRange();
|
||||
if (values.length == 1) {
|
||||
values = new float[] {aatc.getProgress(), values[0]};
|
||||
}
|
||||
ValueAnimator hotseatAnim = ValueAnimator.ofFloat(values);
|
||||
hotseatAnim.addUpdateListener(anim -> {
|
||||
float progress = (Float) anim.getAnimatedValue();
|
||||
if (progress >= overviewProgress || mLauncher.isInState(BACKGROUND_APP)) {
|
||||
float hotseatShift = (progress - overviewProgress) * shiftRange;
|
||||
mLauncher.getHotseat().setTranslationY(hotseatShift + sat.translationY);
|
||||
}
|
||||
});
|
||||
hotseatAnim.setInterpolator(LINEAR);
|
||||
hotseatAnim.setDuration(springAnim.getDuration());
|
||||
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
anim.play(hotseatAnim);
|
||||
anim.play(springAnim);
|
||||
return anim;
|
||||
}
|
||||
|
||||
return springAnim;
|
||||
}
|
||||
case INDEX_RECENTS_FADE_ANIM:
|
||||
return ObjectAnimator.ofFloat(mLauncher.getOverviewPanel(),
|
||||
RecentsView.CONTENT_ALPHA, values);
|
||||
case INDEX_RECENTS_TRANSLATE_X_ANIM: {
|
||||
RecentsView rv = mLauncher.getOverviewPanel();
|
||||
return new SpringAnimationBuilder(mLauncher)
|
||||
.setMinimumVisibleChange(1f / rv.getPageOffsetScale())
|
||||
.setDampingRatio(0.8f)
|
||||
.setStiffness(250)
|
||||
.setValues(values)
|
||||
.build(rv, ADJACENT_PAGE_OFFSET);
|
||||
}
|
||||
case INDEX_PAUSE_TO_OVERVIEW_ANIM: {
|
||||
StateAnimationConfig config = new StateAnimationConfig();
|
||||
config.duration = ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW;
|
||||
|
||||
config.setInterpolator(ANIM_VERTICAL_PROGRESS, OVERSHOOT_1_2);
|
||||
config.setInterpolator(ANIM_ALL_APPS_FADE, DEACCEL_3);
|
||||
if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
|
||||
config.setInterpolator(ANIM_HOTSEAT_SCALE, OVERSHOOT_1_2);
|
||||
config.setInterpolator(ANIM_HOTSEAT_TRANSLATE, OVERSHOOT_1_2);
|
||||
}
|
||||
|
||||
|
||||
LauncherStateManager stateManager = mLauncher.getStateManager();
|
||||
return stateManager.createAtomicAnimation(
|
||||
stateManager.getCurrentStableState(), OVERVIEW, config);
|
||||
}
|
||||
|
||||
default:
|
||||
return super.createStateElementAnimation(index, values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,10 +26,10 @@ import android.os.UserManager;
|
|||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.allapps.FloatingHeaderView;
|
||||
import com.android.launcher3.statemanager.StateManager.StateListener;
|
||||
import com.android.launcher3.views.ArrowTipView;
|
||||
import com.android.systemui.shared.system.LauncherEventUtil;
|
||||
|
||||
|
@ -71,17 +71,16 @@ public class AllAppsTipView {
|
|||
|
||||
public static void scheduleShowIfNeeded(Launcher launcher) {
|
||||
if (!hasSeenAllAppsTip(launcher)) {
|
||||
launcher.getStateManager().addStateListener(
|
||||
new LauncherStateManager.StateListener() {
|
||||
@Override
|
||||
public void onStateTransitionComplete(LauncherState finalState) {
|
||||
if (finalState == ALL_APPS) {
|
||||
if (showAllAppsTipIfNecessary(launcher)) {
|
||||
launcher.getStateManager().removeStateListener(this);
|
||||
}
|
||||
}
|
||||
launcher.getStateManager().addStateListener(new StateListener<LauncherState>() {
|
||||
@Override
|
||||
public void onStateTransitionComplete(LauncherState finalState) {
|
||||
if (finalState == ALL_APPS) {
|
||||
if (showAllAppsTipIfNecessary(launcher)) {
|
||||
launcher.getStateManager().removeStateListener(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,18 +38,18 @@ import androidx.core.content.ContextCompat;
|
|||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.allapps.FloatingHeaderRow;
|
||||
import com.android.launcher3.allapps.FloatingHeaderView;
|
||||
import com.android.launcher3.anim.PropertySetter;
|
||||
import com.android.launcher3.statemanager.StateManager.StateListener;
|
||||
import com.android.launcher3.util.Themes;
|
||||
|
||||
/**
|
||||
* A view which shows a horizontal divider
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class AppsDividerView extends View implements LauncherStateManager.StateListener,
|
||||
public class AppsDividerView extends View implements StateListener<LauncherState>,
|
||||
FloatingHeaderRow {
|
||||
|
||||
private static final String ALL_APPS_VISITED_COUNT = "launcher.all_apps_visited_count";
|
||||
|
|
|
@ -32,7 +32,6 @@ import com.android.launcher3.Launcher;
|
|||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager.StateListener;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.allapps.AllAppsContainerView;
|
||||
import com.android.launcher3.allapps.AllAppsStore.OnUpdateListener;
|
||||
|
@ -41,6 +40,7 @@ import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
|
|||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.shortcuts.ShortcutKey;
|
||||
import com.android.launcher3.statemanager.StateManager.StateListener;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
import com.android.launcher3.util.MainThreadInitializedObject;
|
||||
|
@ -63,8 +63,8 @@ import java.util.stream.IntStream;
|
|||
* 4) Maintains the current active client id (for the predictions) and all updates are performed on
|
||||
* that client id.
|
||||
*/
|
||||
public class PredictionUiStateManager implements StateListener, ItemInfoUpdateReceiver,
|
||||
OnIDPChangeListener, OnUpdateListener {
|
||||
public class PredictionUiStateManager implements StateListener<LauncherState>,
|
||||
ItemInfoUpdateReceiver, OnIDPChangeListener, OnUpdateListener {
|
||||
|
||||
public static final String LAST_PREDICTION_ENABLED_STATE = "last_prediction_enabled_state";
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ import com.android.launcher3.model.data.ItemInfo;
|
|||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.touch.ItemClickHandler;
|
||||
import com.android.launcher3.touch.ItemLongClickListener;
|
||||
import com.android.launcher3.util.SafeCloseable;
|
||||
import com.android.launcher3.views.DoubleShadowBubbleTextView;
|
||||
|
||||
/**
|
||||
|
@ -65,6 +66,7 @@ public class PredictedAppIcon extends DoubleShadowBubbleTextView implements
|
|||
private final int mNormalizedIconRadius;
|
||||
private final BlurMaskFilter mShadowFilter;
|
||||
private int mPlateColor;
|
||||
boolean mDrawForDrag = false;
|
||||
|
||||
|
||||
public PredictedAppIcon(Context context) {
|
||||
|
@ -188,6 +190,10 @@ public class PredictedAppIcon extends DoubleShadowBubbleTextView implements
|
|||
}
|
||||
|
||||
private void drawEffect(Canvas canvas, boolean isBadged) {
|
||||
// Don't draw ring effect if item is about to be dragged.
|
||||
if (mDrawForDrag) {
|
||||
return;
|
||||
}
|
||||
mRingPath.reset();
|
||||
getShape().addToPath(mRingPath, getOutlineOffsetX(), getOutlineOffsetY(),
|
||||
mNormalizedIconRadius);
|
||||
|
@ -208,6 +214,26 @@ public class PredictedAppIcon extends DoubleShadowBubbleTextView implements
|
|||
canvas.drawPath(mRingPath, mIconRingPaint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getSourceVisualDragBounds(Rect bounds) {
|
||||
super.getSourceVisualDragBounds(bounds);
|
||||
if (!mIsPinned) {
|
||||
int internalSize = (int) (bounds.width() * RING_EFFECT_RATIO);
|
||||
bounds.inset(internalSize, internalSize);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SafeCloseable prepareDrawDragView() {
|
||||
mDrawForDrag = true;
|
||||
invalidate();
|
||||
SafeCloseable r = super.prepareDrawDragView();
|
||||
return () -> {
|
||||
r.close();
|
||||
mDrawForDrag = false;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a new instance of PredictedAppIcon from WorkspaceItemInfo
|
||||
*/
|
||||
|
|
|
@ -30,6 +30,7 @@ import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
|
|||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
@ -48,6 +49,9 @@ import com.android.launcher3.model.data.AppInfo;
|
|||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.popup.SystemShortcut;
|
||||
import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory;
|
||||
import com.android.launcher3.uioverrides.touchcontrollers.FlingAndHoldTouchController;
|
||||
import com.android.launcher3.uioverrides.touchcontrollers.LandscapeEdgeSwipeController;
|
||||
import com.android.launcher3.uioverrides.touchcontrollers.NavBarToHomeTouchController;
|
||||
|
@ -243,6 +247,9 @@ public class QuickstepLauncher extends BaseQuickstepLauncher {
|
|||
|
||||
@Override
|
||||
public TouchController[] createTouchControllers() {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "createTouchControllers.1");
|
||||
}
|
||||
Mode mode = SysUINavigationMode.getMode(this);
|
||||
|
||||
ArrayList<TouchController> list = new ArrayList<>();
|
||||
|
@ -250,7 +257,13 @@ public class QuickstepLauncher extends BaseQuickstepLauncher {
|
|||
if (mode == NO_BUTTON) {
|
||||
list.add(new NoButtonQuickSwitchTouchController(this));
|
||||
list.add(new NavBarToHomeTouchController(this));
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "createTouchControllers.2");
|
||||
}
|
||||
if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "createTouchControllers.3");
|
||||
}
|
||||
list.add(new NoButtonNavbarToOverviewTouchController(this));
|
||||
} else {
|
||||
list.add(new FlingAndHoldTouchController(this));
|
||||
|
@ -279,6 +292,11 @@ public class QuickstepLauncher extends BaseQuickstepLauncher {
|
|||
return list.toArray(new TouchController[list.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AtomicAnimationFactory createAtomicAnimationFactory() {
|
||||
return new QuickstepAtomicAnimationFactory(this);
|
||||
}
|
||||
|
||||
private static final class LauncherTaskViewController extends
|
||||
TaskViewTouchController<Launcher> {
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ package com.android.launcher3.uioverrides.states;
|
|||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.allapps.AllAppsTransitionController;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
|
@ -54,11 +55,7 @@ public class BackgroundAppState extends OverviewState {
|
|||
|
||||
@Override
|
||||
public float[] getOverviewScaleAndOffset(Launcher launcher) {
|
||||
return new float[] {getOverviewScale(launcher), NO_OFFSET};
|
||||
}
|
||||
|
||||
private float getOverviewScale(Launcher launcher) {
|
||||
return ((RecentsView) launcher.getOverviewPanel()).getMaxScaleForFullScreen();
|
||||
return getOverviewScaleAndOffsetForBackgroundState(launcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -88,4 +85,11 @@ public class BackgroundAppState extends OverviewState {
|
|||
protected float getDepthUnchecked(Context context) {
|
||||
return 1f;
|
||||
}
|
||||
|
||||
public static float[] getOverviewScaleAndOffsetForBackgroundState(
|
||||
BaseDraggingActivity activity) {
|
||||
return new float[] {
|
||||
((RecentsView) activity.getOverviewPanel()).getMaxScaleForFullScreen(),
|
||||
NO_OFFSET};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@ import android.content.Context;
|
|||
import android.content.res.Resources;
|
||||
import android.graphics.Rect;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
||||
|
@ -49,22 +49,25 @@ public class OverviewModalTaskState extends OverviewState {
|
|||
|
||||
@Override
|
||||
public float[] getOverviewScaleAndOffset(Launcher launcher) {
|
||||
Resources res = launcher.getBaseContext().getResources();
|
||||
|
||||
Rect out = new Rect();
|
||||
launcher.<RecentsView>getOverviewPanel().getTaskSize(out);
|
||||
int taskHeight = out.height();
|
||||
|
||||
float topMargin = res.getDimension(R.dimen.task_thumbnail_top_margin);
|
||||
float bottomMargin = res.getDimension(R.dimen.task_thumbnail_bottom_margin_with_actions);
|
||||
float newHeight = taskHeight + topMargin + bottomMargin;
|
||||
float scale = newHeight / taskHeight;
|
||||
|
||||
return new float[] {scale, 0};
|
||||
return getOverviewScaleAndOffsetForModalState(launcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getOverviewModalness() {
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
public static float[] getOverviewScaleAndOffsetForModalState(BaseDraggingActivity activity) {
|
||||
Resources res = activity.getResources();
|
||||
|
||||
Rect out = new Rect();
|
||||
activity.<RecentsView>getOverviewPanel().getTaskSize(out);
|
||||
int taskHeight = out.height();
|
||||
activity.<RecentsView>getOverviewPanel().getModalTaskSize(out);
|
||||
int newHeight = out.height();
|
||||
|
||||
float scale = (float) newHeight / taskHeight;
|
||||
|
||||
return new float[] {scale, NO_OFFSET};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,16 +15,7 @@
|
|||
*/
|
||||
package com.android.launcher3.uioverrides.states;
|
||||
|
||||
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
|
||||
import static com.android.launcher3.anim.Interpolators.INSTANT;
|
||||
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_7;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCRIM_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
|
||||
public class OverviewPeekState extends OverviewState {
|
||||
private static final float OVERVIEW_OFFSET = 0.7f;
|
||||
|
@ -37,14 +28,4 @@ public class OverviewPeekState extends OverviewState {
|
|||
public float[] getOverviewScaleAndOffset(Launcher launcher) {
|
||||
return new float[] {NO_SCALE, OVERVIEW_OFFSET};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareForAtomicAnimation(Launcher launcher, LauncherState fromState,
|
||||
StateAnimationConfig config) {
|
||||
if (this == OVERVIEW_PEEK && fromState == NORMAL) {
|
||||
config.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
|
||||
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_1_7);
|
||||
config.setInterpolator(ANIM_OVERVIEW_SCRIM_FADE, FAST_OUT_SLOW_IN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,36 +15,21 @@
|
|||
*/
|
||||
package com.android.launcher3.uioverrides.states;
|
||||
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
|
||||
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
|
||||
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_7;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
|
||||
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
|
||||
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.quickstep.SysUINavigationMode;
|
||||
|
@ -57,9 +42,6 @@ import com.android.quickstep.views.TaskView;
|
|||
*/
|
||||
public class OverviewState extends LauncherState {
|
||||
|
||||
// Scale recents takes before animating in
|
||||
private static final float RECENTS_PREPARE_SCALE = 1.33f;
|
||||
|
||||
protected static final Rect sTempRect = new Rect();
|
||||
|
||||
private static final int STATE_FLAGS = FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED
|
||||
|
@ -202,35 +184,6 @@ public class OverviewState extends LauncherState {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareForAtomicAnimation(Launcher launcher, LauncherState fromState,
|
||||
StateAnimationConfig config) {
|
||||
if ((fromState == NORMAL || fromState == HINT_STATE) && this == OVERVIEW) {
|
||||
if (SysUINavigationMode.getMode(launcher) == NO_BUTTON) {
|
||||
config.setInterpolator(ANIM_WORKSPACE_SCALE,
|
||||
fromState == NORMAL ? ACCEL : OVERSHOOT_1_2);
|
||||
config.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL);
|
||||
} else {
|
||||
config.setInterpolator(ANIM_WORKSPACE_SCALE, OVERSHOOT_1_2);
|
||||
|
||||
// Scale up the recents, if it is not coming from the side
|
||||
RecentsView overview = launcher.getOverviewPanel();
|
||||
if (overview.getVisibility() != VISIBLE || overview.getContentAlpha() == 0) {
|
||||
SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE);
|
||||
}
|
||||
}
|
||||
config.setInterpolator(ANIM_WORKSPACE_FADE, OVERSHOOT_1_2);
|
||||
config.setInterpolator(ANIM_OVERVIEW_SCALE, OVERSHOOT_1_2);
|
||||
Interpolator translationInterpolator = ENABLE_OVERVIEW_ACTIONS.get()
|
||||
&& removeShelfFromOverview(launcher)
|
||||
? OVERSHOOT_1_2
|
||||
: OVERSHOOT_1_7;
|
||||
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, translationInterpolator);
|
||||
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, translationInterpolator);
|
||||
config.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2);
|
||||
}
|
||||
}
|
||||
|
||||
public static OverviewState newBackgroundState(int id) {
|
||||
return new BackgroundAppState(id);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.uioverrides.states;
|
||||
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
||||
import static com.android.launcher3.LauncherState.HINT_STATE;
|
||||
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW_PEEK;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
|
||||
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
|
||||
import static com.android.launcher3.anim.Interpolators.INSTANT;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
|
||||
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_7;
|
||||
import static com.android.launcher3.anim.Interpolators.clampToProgress;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_SCALE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCRIM_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
|
||||
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
|
||||
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.view.View;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import com.android.launcher3.CellLayout;
|
||||
import com.android.launcher3.Hotseat;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherState.ScaleAndTranslation;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.allapps.AllAppsContainerView;
|
||||
import com.android.launcher3.allapps.AllAppsTransitionController;
|
||||
import com.android.launcher3.anim.SpringAnimationBuilder;
|
||||
import com.android.launcher3.statemanager.StateManager;
|
||||
import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.uioverrides.QuickstepLauncher;
|
||||
import com.android.quickstep.SysUINavigationMode;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
||||
/**
|
||||
* Animation factory for quickstep specific transitions
|
||||
*/
|
||||
public class QuickstepAtomicAnimationFactory extends AtomicAnimationFactory<LauncherState> {
|
||||
|
||||
// Scale recents takes before animating in
|
||||
private static final float RECENTS_PREPARE_SCALE = 1.33f;
|
||||
|
||||
public static final int INDEX_SHELF_ANIM = 0;
|
||||
public static final int INDEX_RECENTS_FADE_ANIM = 1;
|
||||
public static final int INDEX_RECENTS_TRANSLATE_X_ANIM = 2;
|
||||
public static final int INDEX_PAUSE_TO_OVERVIEW_ANIM = 3;
|
||||
private static final int ANIM_COUNT = 4;
|
||||
|
||||
public static final long ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW = 300;
|
||||
|
||||
private final QuickstepLauncher mLauncher;
|
||||
|
||||
public QuickstepAtomicAnimationFactory(QuickstepLauncher launcher) {
|
||||
super(ANIM_COUNT);
|
||||
mLauncher = launcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Animator createStateElementAnimation(int index, float... values) {
|
||||
switch (index) {
|
||||
case INDEX_SHELF_ANIM: {
|
||||
AllAppsTransitionController aatc = mLauncher.getAllAppsController();
|
||||
Animator springAnim = aatc.createSpringAnimation(values);
|
||||
|
||||
if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
|
||||
// Translate hotseat with the shelf until reaching overview.
|
||||
float overviewProgress = OVERVIEW.getVerticalProgress(mLauncher);
|
||||
ScaleAndTranslation sat = OVERVIEW.getHotseatScaleAndTranslation(mLauncher);
|
||||
float shiftRange = aatc.getShiftRange();
|
||||
if (values.length == 1) {
|
||||
values = new float[] {aatc.getProgress(), values[0]};
|
||||
}
|
||||
ValueAnimator hotseatAnim = ValueAnimator.ofFloat(values);
|
||||
hotseatAnim.addUpdateListener(anim -> {
|
||||
float progress = (Float) anim.getAnimatedValue();
|
||||
if (progress >= overviewProgress || mLauncher.isInState(BACKGROUND_APP)) {
|
||||
float hotseatShift = (progress - overviewProgress) * shiftRange;
|
||||
mLauncher.getHotseat().setTranslationY(hotseatShift + sat.translationY);
|
||||
}
|
||||
});
|
||||
hotseatAnim.setInterpolator(LINEAR);
|
||||
hotseatAnim.setDuration(springAnim.getDuration());
|
||||
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
anim.play(hotseatAnim);
|
||||
anim.play(springAnim);
|
||||
return anim;
|
||||
}
|
||||
|
||||
return springAnim;
|
||||
}
|
||||
case INDEX_RECENTS_FADE_ANIM:
|
||||
return ObjectAnimator.ofFloat(mLauncher.getOverviewPanel(),
|
||||
RecentsView.CONTENT_ALPHA, values);
|
||||
case INDEX_RECENTS_TRANSLATE_X_ANIM: {
|
||||
RecentsView rv = mLauncher.getOverviewPanel();
|
||||
return new SpringAnimationBuilder(mLauncher)
|
||||
.setMinimumVisibleChange(1f / rv.getPageOffsetScale())
|
||||
.setDampingRatio(0.8f)
|
||||
.setStiffness(250)
|
||||
.setValues(values)
|
||||
.build(rv, ADJACENT_PAGE_OFFSET);
|
||||
}
|
||||
case INDEX_PAUSE_TO_OVERVIEW_ANIM: {
|
||||
StateAnimationConfig config = new StateAnimationConfig();
|
||||
config.duration = ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW;
|
||||
|
||||
config.setInterpolator(ANIM_VERTICAL_PROGRESS, OVERSHOOT_1_2);
|
||||
config.setInterpolator(ANIM_ALL_APPS_FADE, DEACCEL_3);
|
||||
if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
|
||||
config.setInterpolator(ANIM_HOTSEAT_SCALE, OVERSHOOT_1_2);
|
||||
config.setInterpolator(ANIM_HOTSEAT_TRANSLATE, OVERSHOOT_1_2);
|
||||
}
|
||||
|
||||
StateManager<LauncherState> stateManager = mLauncher.getStateManager();
|
||||
return stateManager.createAtomicAnimation(
|
||||
stateManager.getCurrentStableState(), OVERVIEW, config);
|
||||
}
|
||||
|
||||
default:
|
||||
return super.createStateElementAnimation(index, values);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareForAtomicAnimation(LauncherState fromState, LauncherState toState,
|
||||
StateAnimationConfig config) {
|
||||
if (toState == NORMAL && fromState == OVERVIEW) {
|
||||
config.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL);
|
||||
config.setInterpolator(ANIM_WORKSPACE_FADE, ACCEL);
|
||||
config.setInterpolator(ANIM_OVERVIEW_SCALE, clampToProgress(ACCEL, 0, 0.9f));
|
||||
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL);
|
||||
config.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7);
|
||||
Workspace workspace = mLauncher.getWorkspace();
|
||||
|
||||
// Start from a higher workspace scale, but only if we're invisible so we don't jump.
|
||||
boolean isWorkspaceVisible = workspace.getVisibility() == VISIBLE;
|
||||
if (isWorkspaceVisible) {
|
||||
CellLayout currentChild = (CellLayout) workspace.getChildAt(
|
||||
workspace.getCurrentPage());
|
||||
isWorkspaceVisible = currentChild.getVisibility() == VISIBLE
|
||||
&& currentChild.getShortcutsAndWidgets().getAlpha() > 0;
|
||||
}
|
||||
if (!isWorkspaceVisible) {
|
||||
workspace.setScaleX(0.92f);
|
||||
workspace.setScaleY(0.92f);
|
||||
}
|
||||
Hotseat hotseat = mLauncher.getHotseat();
|
||||
boolean isHotseatVisible = hotseat.getVisibility() == VISIBLE && hotseat.getAlpha() > 0;
|
||||
if (!isHotseatVisible) {
|
||||
hotseat.setScaleX(0.92f);
|
||||
hotseat.setScaleY(0.92f);
|
||||
if (ENABLE_OVERVIEW_ACTIONS.get()) {
|
||||
AllAppsContainerView qsbContainer = mLauncher.getAppsView();
|
||||
View qsb = qsbContainer.getSearchView();
|
||||
boolean qsbVisible = qsb.getVisibility() == VISIBLE && qsb.getAlpha() > 0;
|
||||
if (!qsbVisible) {
|
||||
qsbContainer.setScaleX(0.92f);
|
||||
qsbContainer.setScaleY(0.92f);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (toState == NORMAL && fromState == OVERVIEW_PEEK) {
|
||||
// Keep fully visible until the very end (when overview is offscreen) to make invisible.
|
||||
config.setInterpolator(ANIM_OVERVIEW_FADE, t -> t < 1 ? 0 : 1);
|
||||
} else if (toState == OVERVIEW_PEEK && fromState == NORMAL) {
|
||||
config.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
|
||||
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_1_7);
|
||||
config.setInterpolator(ANIM_OVERVIEW_SCRIM_FADE, FAST_OUT_SLOW_IN);
|
||||
} else if ((fromState == NORMAL || fromState == HINT_STATE) && toState == OVERVIEW) {
|
||||
if (SysUINavigationMode.getMode(mLauncher) == NO_BUTTON) {
|
||||
config.setInterpolator(ANIM_WORKSPACE_SCALE,
|
||||
fromState == NORMAL ? ACCEL : OVERSHOOT_1_2);
|
||||
config.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL);
|
||||
} else {
|
||||
config.setInterpolator(ANIM_WORKSPACE_SCALE, OVERSHOOT_1_2);
|
||||
|
||||
// Scale up the recents, if it is not coming from the side
|
||||
RecentsView overview = mLauncher.getOverviewPanel();
|
||||
if (overview.getVisibility() != VISIBLE || overview.getContentAlpha() == 0) {
|
||||
SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE);
|
||||
}
|
||||
}
|
||||
config.setInterpolator(ANIM_WORKSPACE_FADE, OVERSHOOT_1_2);
|
||||
config.setInterpolator(ANIM_OVERVIEW_SCALE, OVERSHOOT_1_2);
|
||||
Interpolator translationInterpolator = ENABLE_OVERVIEW_ACTIONS.get()
|
||||
&& removeShelfFromOverview(mLauncher)
|
||||
? OVERSHOOT_1_2
|
||||
: OVERSHOOT_1_7;
|
||||
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, translationInterpolator);
|
||||
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, translationInterpolator);
|
||||
config.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package com.android.launcher3.uioverrides.touchcontrollers;
|
||||
|
||||
import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_PAUSE_TO_OVERVIEW_ANIM;
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
|
@ -31,23 +30,26 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_S
|
|||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
|
||||
import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_PAUSE_TO_OVERVIEW_ANIM;
|
||||
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppTransitionManagerImpl;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.launcher3.util.VibratorWrapper;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
|
@ -82,7 +84,7 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
|
|||
|
||||
@Override
|
||||
protected long getAtomicDuration() {
|
||||
return LauncherAppTransitionManagerImpl.ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW;
|
||||
return QuickstepAtomicAnimationFactory.ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -178,6 +180,9 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
|
|||
|
||||
@Override
|
||||
public boolean onDrag(float displacement, MotionEvent event) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "FlingAndHoldTouchController");
|
||||
}
|
||||
float upDisplacement = -displacement;
|
||||
mMotionPauseDetector.setDisallowPause(!handlingOverviewAnim()
|
||||
|| upDisplacement < mMotionPauseMinDisplacement
|
||||
|
@ -206,8 +211,8 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
|
|||
mPeekAnim.cancel();
|
||||
}
|
||||
|
||||
Animator overviewAnim = mLauncher.getAppTransitionManager().createStateElementAnimation(
|
||||
INDEX_PAUSE_TO_OVERVIEW_ANIM);
|
||||
Animator overviewAnim = mLauncher.createAtomicAnimationFactory()
|
||||
.createStateElementAnimation(INDEX_PAUSE_TO_OVERVIEW_ANIM);
|
||||
mAtomicAnim = new AnimatorSet();
|
||||
mAtomicAnim.addListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
|
|
|
@ -25,6 +25,7 @@ import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
|
|||
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
|
@ -41,6 +42,7 @@ import com.android.launcher3.anim.PendingAnimation;
|
|||
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.touch.SingleAxisSwipeDetector;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
|
@ -94,18 +96,37 @@ public class NavBarToHomeTouchController implements TouchController,
|
|||
}
|
||||
|
||||
private boolean canInterceptTouch(MotionEvent ev) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "NavBarToHomeTouchController.canInterceptTouch "
|
||||
+ ev);
|
||||
}
|
||||
boolean cameFromNavBar = (ev.getEdgeFlags() & Utilities.EDGE_NAV_BAR) != 0;
|
||||
if (!cameFromNavBar) {
|
||||
return false;
|
||||
}
|
||||
if (mStartState.overviewUi || mStartState == ALL_APPS) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.PAUSE_NOT_DETECTED,
|
||||
"NavBarToHomeTouchController.canInterceptTouch true 1 "
|
||||
+ mStartState.overviewUi + " " + (mStartState == ALL_APPS));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (AbstractFloatingView.getTopOpenView(mLauncher) != null) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.PAUSE_NOT_DETECTED,
|
||||
"NavBarToHomeTouchController.canInterceptTouch true 2 "
|
||||
+ AbstractFloatingView.getTopOpenView(mLauncher).getClass()
|
||||
.getSimpleName());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (FeatureFlags.ASSISTANT_GIVES_LAUNCHER_FOCUS.get()
|
||||
&& AssistantUtilities.isExcludedAssistantRunning()) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.PAUSE_NOT_DETECTED,
|
||||
"NavBarToHomeTouchController.canInterceptTouch true 3");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -27,14 +27,16 @@ import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
|
|||
import android.animation.AnimatorSet;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.graphics.PointF;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.statemanager.StateManager;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.launcher3.util.VibratorWrapper;
|
||||
import com.android.quickstep.util.StaggeredWorkspaceAnim;
|
||||
|
@ -63,6 +65,9 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo
|
|||
public NoButtonNavbarToOverviewTouchController(Launcher l) {
|
||||
super(l);
|
||||
mRecentsView = l.getOverviewPanel();
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "NoButtonNavbarToOverviewTouchController.ctor");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -146,6 +151,9 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo
|
|||
|
||||
@Override
|
||||
public boolean onDrag(float yDisplacement, float xDisplacement, MotionEvent event) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "NoButtonNavbarToOverviewTouchController");
|
||||
}
|
||||
if (mMotionPauseDetector.isPaused()) {
|
||||
if (!mReachedOverview) {
|
||||
mStartDisplacement.set(xDisplacement, yDisplacement);
|
||||
|
@ -165,7 +173,7 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo
|
|||
protected void goToOverviewOnDragEnd(float velocity) {
|
||||
float velocityDp = dpiFromPx(velocity);
|
||||
boolean isFling = Math.abs(velocityDp) > 1;
|
||||
LauncherStateManager stateManager = mLauncher.getStateManager();
|
||||
StateManager<LauncherState> stateManager = mLauncher.getStateManager();
|
||||
boolean goToHomeInsteadOfOverview = isFling;
|
||||
if (goToHomeInsteadOfOverview) {
|
||||
if (velocity > 0) {
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
package com.android.launcher3.uioverrides.touchcontrollers;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_PAUSE_TO_OVERVIEW_ANIM;
|
||||
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
|
@ -35,6 +34,7 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_T
|
|||
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
|
||||
import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_RIGHT;
|
||||
import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_UP;
|
||||
import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_PAUSE_TO_OVERVIEW_ANIM;
|
||||
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
|
||||
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
|
||||
import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.CANCEL;
|
||||
|
@ -312,8 +312,8 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
|
|||
if (mMotionPauseDetector.isPaused() && noFling) {
|
||||
cancelAnimations();
|
||||
|
||||
Animator overviewAnim = mLauncher.getAppTransitionManager().createStateElementAnimation(
|
||||
INDEX_PAUSE_TO_OVERVIEW_ANIM);
|
||||
Animator overviewAnim = mLauncher.createAtomicAnimationFactory()
|
||||
.createStateElementAnimation(INDEX_PAUSE_TO_OVERVIEW_ANIM);
|
||||
overviewAnim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
|
|
|
@ -58,6 +58,7 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
|
|||
private final SingleAxisSwipeDetector mDetector;
|
||||
private final RecentsView mRecentsView;
|
||||
private final int[] mTempCords = new int[2];
|
||||
private final boolean mIsRtl;
|
||||
|
||||
private PendingAnimation mPendingAnimation;
|
||||
private AnimatorPlaybackController mCurrentAnimation;
|
||||
|
@ -75,6 +76,7 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
|
|||
public TaskViewTouchController(T activity) {
|
||||
mActivity = activity;
|
||||
mRecentsView = activity.getOverviewPanel();
|
||||
mIsRtl = Utilities.isRtl(activity.getResources());
|
||||
SingleAxisSwipeDetector.Direction dir =
|
||||
mRecentsView.getPagedOrientationHandler().getOppositeSwipeDirection();
|
||||
mDetector = new SingleAxisSwipeDetector(activity, this, dir);
|
||||
|
@ -201,8 +203,8 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
|
|||
mCurrentAnimationIsGoingUp = goingUp;
|
||||
BaseDragLayer dl = mActivity.getDragLayer();
|
||||
final int secondaryLayerDimension = orientationHandler.getSecondaryDimension(dl);
|
||||
long maxDuration = (long) (2 * secondaryLayerDimension);
|
||||
int verticalFactor = -orientationHandler.getTaskDismissDirectionFactor();
|
||||
long maxDuration = 2 * secondaryLayerDimension;
|
||||
int verticalFactor = orientationHandler.getTaskDragDisplacementFactor(mIsRtl);
|
||||
int secondaryTaskDimension = orientationHandler.getSecondaryDimension(mTaskBeingDragged);
|
||||
if (goingUp) {
|
||||
mPendingAnimation = mRecentsView.createTaskDismissAnimation(mTaskBeingDragged,
|
||||
|
@ -236,7 +238,7 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
|
|||
public void onDragStart(boolean start, float startDisplacement) {
|
||||
PagedOrientationHandler orientationHandler = mRecentsView.getPagedOrientationHandler();
|
||||
if (mCurrentAnimation == null) {
|
||||
reInitAnimationController(orientationHandler.isGoingUp(startDisplacement));
|
||||
reInitAnimationController(orientationHandler.isGoingUp(startDisplacement, mIsRtl));
|
||||
mDisplacementShift = 0;
|
||||
} else {
|
||||
mDisplacementShift = mCurrentAnimation.getProgressFraction() / mProgressMultiplier;
|
||||
|
@ -250,7 +252,7 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
|
|||
PagedOrientationHandler orientationHandler = mRecentsView.getPagedOrientationHandler();
|
||||
float totalDisplacement = displacement + mDisplacementShift;
|
||||
boolean isGoingUp = totalDisplacement == 0 ? mCurrentAnimationIsGoingUp :
|
||||
orientationHandler.isGoingUp(totalDisplacement);
|
||||
orientationHandler.isGoingUp(totalDisplacement, mIsRtl);
|
||||
if (isGoingUp != mCurrentAnimationIsGoingUp) {
|
||||
reInitAnimationController(isGoingUp);
|
||||
mFlingBlockCheck.blockFling();
|
||||
|
@ -282,7 +284,7 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
|
|||
float interpolatedProgress = mCurrentAnimation.getInterpolatedProgress();
|
||||
if (fling) {
|
||||
logAction = Touch.FLING;
|
||||
boolean goingUp = orientationHandler.isGoingUp(velocity);
|
||||
boolean goingUp = orientationHandler.isGoingUp(velocity, mIsRtl);
|
||||
goingToEnd = goingUp == mCurrentAnimationIsGoingUp;
|
||||
} else {
|
||||
logAction = Touch.SWIPE;
|
||||
|
|
|
@ -17,7 +17,6 @@ package com.android.quickstep;
|
|||
|
||||
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
|
||||
import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
|
||||
import static com.android.launcher3.statehandlers.DepthController.DEPTH;
|
||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
|
||||
|
@ -36,8 +35,8 @@ import com.android.launcher3.BaseDraggingActivity;
|
|||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.statehandlers.DepthController;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper.TransformParams;
|
||||
import com.android.quickstep.util.RemoteAnimationProvider;
|
||||
import com.android.quickstep.util.TransformParams;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
|
||||
|
@ -75,14 +74,10 @@ final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> exten
|
|||
boolean onActivityReady(T activity, Boolean wasVisible) {
|
||||
activity.<RecentsView>getOverviewPanel().showCurrentTask(mTargetTaskId);
|
||||
AbstractFloatingView.closeAllOpenViews(activity, wasVisible);
|
||||
BaseActivityInterface.AnimationFactory factory =
|
||||
mActivityInterface.prepareRecentsUI(wasVisible,
|
||||
false /* animate activity */, (controller) -> {
|
||||
BaseActivityInterface.AnimationFactory factory = mActivityInterface.prepareRecentsUI(
|
||||
wasVisible, (controller) -> {
|
||||
controller.dispatchOnStart();
|
||||
ValueAnimator anim = controller.getAnimationPlayer()
|
||||
.setDuration(RECENTS_LAUNCH_DURATION);
|
||||
anim.setInterpolator(FAST_OUT_SLOW_IN);
|
||||
anim.start();
|
||||
controller.getAnimationPlayer().end();
|
||||
});
|
||||
factory.onRemoteAnimationReceived(null);
|
||||
factory.createActivityInterface(RECENTS_LAUNCH_DURATION);
|
||||
|
@ -164,9 +159,7 @@ final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> exten
|
|||
valueAnimator.setDuration(RECENTS_LAUNCH_DURATION);
|
||||
valueAnimator.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
|
||||
valueAnimator.addUpdateListener((v) -> {
|
||||
params.setProgress((float) v.getAnimatedValue())
|
||||
.setTargetSet(targets)
|
||||
.setLauncherOnTop(true);
|
||||
params.setProgress((float) v.getAnimatedValue()).setTargetSet(targets);
|
||||
clipHelper.applyTransform(params);
|
||||
});
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
|
||||
|
@ -23,44 +25,49 @@ import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
|
|||
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Matrix.ScaleToFit;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Build;
|
||||
import android.util.Pair;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
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.InvariantDeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.launcher3.util.VibratorWrapper;
|
||||
import com.android.launcher3.views.FloatingIconView;
|
||||
import com.android.quickstep.BaseActivityInterface.HomeAnimationFactory;
|
||||
import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener;
|
||||
import com.android.quickstep.util.ActiveGestureLog;
|
||||
import com.android.quickstep.util.ActivityInitListener;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper.TransformParams;
|
||||
import com.android.quickstep.util.RecentsOrientedState;
|
||||
import com.android.quickstep.util.RectFSpringAnim;
|
||||
import com.android.quickstep.util.TaskViewSimulator;
|
||||
import com.android.quickstep.util.TransformParams;
|
||||
import com.android.quickstep.util.TransformParams.BuilderProxy;
|
||||
import com.android.quickstep.util.WindowSizeStrategy;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.InputConsumerController;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams.Builder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.Consumer;
|
||||
|
@ -93,7 +100,9 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
|||
protected final BaseActivityInterface<T> mActivityInterface;
|
||||
protected final InputConsumerController mInputConsumer;
|
||||
|
||||
protected AppWindowAnimationHelper mAppWindowAnimationHelper;
|
||||
protected final TaskViewSimulator mTaskViewSimulator;
|
||||
private AnimatorPlaybackController mWindowTransitionController;
|
||||
|
||||
protected final TransformParams mTransformParams = new TransformParams();
|
||||
|
||||
// Shift in the range of [0, 1].
|
||||
|
@ -113,27 +122,25 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
|||
protected T mActivity;
|
||||
protected Q mRecentsView;
|
||||
protected DeviceProfile mDp;
|
||||
private final int mPageSpacing;
|
||||
|
||||
protected Runnable mGestureEndCallback;
|
||||
|
||||
protected MultiStateCallback mStateCallback;
|
||||
|
||||
protected boolean mCanceled;
|
||||
protected int mFinishingRecentsAnimationForNewTaskId = -1;
|
||||
|
||||
private RecentsOrientedState mOrientedState;
|
||||
private boolean mRecentsViewScrollLinked = false;
|
||||
|
||||
protected BaseSwipeUpHandler(Context context, RecentsAnimationDeviceState deviceState,
|
||||
GestureState gestureState, InputConsumerController inputConsumer) {
|
||||
GestureState gestureState, InputConsumerController inputConsumer,
|
||||
WindowSizeStrategy windowSizeStrategy) {
|
||||
mContext = context;
|
||||
mDeviceState = deviceState;
|
||||
mGestureState = gestureState;
|
||||
mActivityInterface = gestureState.getActivityInterface();
|
||||
mActivityInitListener = mActivityInterface.createActivityInitListener(this::onActivityInit);
|
||||
mInputConsumer = inputConsumer;
|
||||
mAppWindowAnimationHelper = new AppWindowAnimationHelper(context);
|
||||
mPageSpacing = context.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing);
|
||||
mTaskViewSimulator = new TaskViewSimulator(context, windowSizeStrategy);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -193,13 +200,13 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
|||
updateFinalShift();
|
||||
}
|
||||
});
|
||||
mRecentsView.setAppWindowAnimationHelper(mAppWindowAnimationHelper);
|
||||
runOnRecentsAnimationStart(() ->
|
||||
mRecentsView.setRecentsAnimationTargets(mRecentsAnimationController,
|
||||
mRecentsAnimationTargets));
|
||||
mRecentsViewScrollLinked = true;
|
||||
}
|
||||
|
||||
protected void startNewTask(int successStateFlag, Consumer<Boolean> resultCallback) {
|
||||
protected void startNewTask(Consumer<Boolean> resultCallback) {
|
||||
// Launch the task user scrolled to (mRecentsView.getNextPage()).
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
// We finish recents animation inside launchTask() when live tile is enabled.
|
||||
|
@ -210,24 +217,41 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
|||
if (!mCanceled) {
|
||||
TaskView nextTask = mRecentsView.getTaskView(taskId);
|
||||
if (nextTask != null) {
|
||||
mGestureState.updateLastStartedTaskId(taskId);
|
||||
nextTask.launchTask(false /* animate */, true /* freezeTaskList */,
|
||||
success -> {
|
||||
resultCallback.accept(success);
|
||||
if (!success) {
|
||||
if (success) {
|
||||
if (mRecentsView.indexOfChild(nextTask)
|
||||
== getLastAppearedTaskIndex()) {
|
||||
onRestartLastAppearedTask();
|
||||
}
|
||||
} else {
|
||||
mActivityInterface.onLaunchTaskFailed();
|
||||
nextTask.notifyTaskLaunchFailed(TAG);
|
||||
} else {
|
||||
mActivityInterface.onLaunchTaskSuccess();
|
||||
mRecentsAnimationController.finish(true /* toRecents */, null);
|
||||
}
|
||||
}, MAIN_EXECUTOR.getHandler());
|
||||
}
|
||||
mStateCallback.setStateOnUiThread(successStateFlag);
|
||||
}
|
||||
mCanceled = false;
|
||||
}
|
||||
ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when we successfully startNewTask() on the task that was previously running. Normally
|
||||
* we call resumeLastTask() when returning to the previously running task, but this handles a
|
||||
* specific edge case: if we switch from A to B, and back to A before B appears, we need to
|
||||
* start A again to ensure it stays on top.
|
||||
*/
|
||||
@CallSuper
|
||||
protected void onRestartLastAppearedTask() {
|
||||
// Finish the controller here, since we won't get onTaskAppeared() for a task that already
|
||||
// appeared.
|
||||
mRecentsAnimationController.finish(false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the given {@param action} if the recents animation has already started, or queues it to
|
||||
* be run when it is next started.
|
||||
|
@ -241,42 +265,36 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
|||
}
|
||||
|
||||
/**
|
||||
* TODO can we remove this now that we don't finish the controller until onTaskAppeared()?
|
||||
* @return whether the recents animation has started and there are valid app targets.
|
||||
*/
|
||||
protected boolean hasTargets() {
|
||||
return mRecentsAnimationTargets != null && mRecentsAnimationTargets.hasTargets();
|
||||
}
|
||||
|
||||
protected void updateSource(Rect stackBounds, RemoteAnimationTargetCompat runningTarget) {
|
||||
mAppWindowAnimationHelper.updateSource(stackBounds, runningTarget);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentsAnimationStart(RecentsAnimationController recentsAnimationController,
|
||||
RecentsAnimationTargets targets) {
|
||||
mRecentsAnimationController = recentsAnimationController;
|
||||
mRecentsAnimationTargets = targets;
|
||||
DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(mContext).getDeviceProfile(mContext);
|
||||
final Rect overviewStackBounds;
|
||||
RemoteAnimationTargetCompat runningTaskTarget = targets.findTask(
|
||||
mGestureState.getRunningTaskId());
|
||||
|
||||
if (targets.minimizedHomeBounds != null && runningTaskTarget != null) {
|
||||
overviewStackBounds = mActivityInterface
|
||||
Rect overviewStackBounds = mActivityInterface
|
||||
.getOverviewWindowBounds(targets.minimizedHomeBounds, runningTaskTarget);
|
||||
dp = dp.getMultiWindowProfile(mContext, overviewStackBounds);
|
||||
} else {
|
||||
// If we are not in multi-window mode, home insets should be same as system insets.
|
||||
dp = dp.copy(mContext);
|
||||
overviewStackBounds = getStackBounds(dp);
|
||||
}
|
||||
dp.updateInsets(targets.homeContentInsets);
|
||||
dp.updateIsSeascape(mContext);
|
||||
if (runningTaskTarget != null) {
|
||||
updateSource(overviewStackBounds, runningTaskTarget);
|
||||
mTaskViewSimulator.setPreview(runningTaskTarget);
|
||||
}
|
||||
|
||||
mAppWindowAnimationHelper.prepareAnimation(dp);
|
||||
initTransitionEndpoints(dp);
|
||||
|
||||
// Notify when the animation starts
|
||||
|
@ -306,51 +324,73 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
|||
}
|
||||
}
|
||||
|
||||
private Rect getStackBounds(DeviceProfile dp) {
|
||||
if (mActivity != null) {
|
||||
int loc[] = new int[2];
|
||||
View rootView = mActivity.getRootView();
|
||||
rootView.getLocationOnScreen(loc);
|
||||
return new Rect(loc[0], loc[1], loc[0] + rootView.getWidth(),
|
||||
loc[1] + rootView.getHeight());
|
||||
} else {
|
||||
return new Rect(0, 0, dp.widthPx, dp.heightPx);
|
||||
@Override
|
||||
public void onTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {
|
||||
if (mRecentsAnimationController != null) {
|
||||
if (handleTaskAppeared(appearedTaskTarget)) {
|
||||
mRecentsAnimationController.finish(false /* toRecents */,
|
||||
null /* onFinishComplete */);
|
||||
mActivityInterface.onLaunchTaskSuccess();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @return Whether this was the task we were waiting to appear, and thus handled it. */
|
||||
protected abstract boolean handleTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget);
|
||||
|
||||
/**
|
||||
* @return The index of the TaskView in RecentsView whose taskId matches the task that will
|
||||
* resume if we finish the controller.
|
||||
*/
|
||||
protected int getLastAppearedTaskIndex() {
|
||||
return mGestureState.getLastAppearedTaskId() != -1
|
||||
? mRecentsView.getTaskIndexForId(mGestureState.getLastAppearedTaskId())
|
||||
: mRecentsView.getRunningTaskIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether we are continuing a gesture that already landed on a new task,
|
||||
* but before that task appeared.
|
||||
*/
|
||||
protected boolean hasStartedNewTask() {
|
||||
return mGestureState.getLastStartedTaskId() != -1;
|
||||
}
|
||||
|
||||
protected void initTransitionEndpoints(DeviceProfile dp) {
|
||||
mDp = dp;
|
||||
|
||||
mTransitionDragLength = mActivityInterface.getSwipeUpDestinationAndLength(
|
||||
dp, mContext, TEMP_RECT);
|
||||
mTaskViewSimulator.setDp(dp);
|
||||
mTaskViewSimulator.setLayoutRotation(
|
||||
mDeviceState.getCurrentActiveRotation(),
|
||||
mDeviceState.getDisplayRotation());
|
||||
|
||||
if (!dp.isMultiWindowMode) {
|
||||
// When updating the target rect, also update the home bounds since the location on
|
||||
// screen of the launcher window may be stale (position is not updated until first
|
||||
// traversal after the window is resized). We only do this for non-multiwindow because
|
||||
// we otherwise use the minimized home bounds provided by the system.
|
||||
mAppWindowAnimationHelper.updateHomeBounds(getStackBounds(dp));
|
||||
}
|
||||
int displayRotation = 0;
|
||||
if (mOrientedState != null && mOrientedState.isMultipleOrientationSupportedByDevice()) {
|
||||
// TODO(b/150300347): The first recents animation after launcher is started with the
|
||||
// foreground app not in landscape will look funky until that bug is fixed
|
||||
displayRotation = mOrientedState.getDisplayRotation();
|
||||
|
||||
RectF tempRectF = new RectF(TEMP_RECT);
|
||||
mOrientedState.mapRectFromRotation(displayRotation,
|
||||
tempRectF, dp.widthPx, dp.heightPx);
|
||||
tempRectF.roundOut(TEMP_RECT);
|
||||
}
|
||||
mAppWindowAnimationHelper.updateTargetRect(TEMP_RECT);
|
||||
if (mDeviceState.isFullyGesturalNavMode()) {
|
||||
// We can drag all the way to the top of the screen.
|
||||
mDragLengthFactor = (float) dp.heightPx / mTransitionDragLength;
|
||||
Pair<Float, Float> dragFactorStartAndMaxProgress =
|
||||
mActivityInterface.getSwipeUpPullbackStartAndMaxProgress();
|
||||
mDragLengthFactorStartPullback = dragFactorStartAndMaxProgress.first;
|
||||
mDragLengthFactorMaxPullback = dragFactorStartAndMaxProgress.second;
|
||||
|
||||
float startScale = mTaskViewSimulator.getFullScreenScale();
|
||||
// Start pulling back when RecentsView scale is 0.75f, and let it go down to 0.5f.
|
||||
mDragLengthFactorStartPullback = (0.75f - startScale) / (1 - startScale);
|
||||
mDragLengthFactorMaxPullback = (0.5f - startScale) / (1 - startScale);
|
||||
} else {
|
||||
mDragLengthFactor = 1;
|
||||
mDragLengthFactorStartPullback = mDragLengthFactorMaxPullback = 1;
|
||||
}
|
||||
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
anim.setDuration(mTransitionDragLength * 2);
|
||||
anim.setInterpolator(t -> t * mDragLengthFactor);
|
||||
anim.play(ObjectAnimator.ofFloat(mTaskViewSimulator.recentsViewScale,
|
||||
AnimatedFloat.VALUE,
|
||||
mTaskViewSimulator.getFullScreenScale(), 1));
|
||||
anim.play(ObjectAnimator.ofFloat(mTaskViewSimulator.fullScreenProgress,
|
||||
AnimatedFloat.VALUE,
|
||||
BACKGROUND_APP.getOverviewFullscreenProgress(),
|
||||
OVERVIEW.getOverviewFullscreenProgress()));
|
||||
mWindowTransitionController =
|
||||
AnimatorPlaybackController.wrap(anim, mTransitionDragLength * 2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -361,9 +401,6 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
|||
protected boolean onActivityInit(Boolean alreadyOnHome) {
|
||||
T createdActivity = mActivityInterface.getCreatedActivity();
|
||||
if (createdActivity != null) {
|
||||
mOrientedState = ((RecentsView) createdActivity.getOverviewPanel())
|
||||
.getPagedViewOrientedState();
|
||||
mAppWindowAnimationHelper = new AppWindowAnimationHelper(mOrientedState, mContext);
|
||||
initTransitionEndpoints(InvariantDeviceProfile.INSTANCE.get(mContext)
|
||||
.getDeviceProfile(mContext));
|
||||
}
|
||||
|
@ -412,35 +449,23 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
|||
}
|
||||
|
||||
/**
|
||||
* Applies the transform on the recents animation without any additional null checks
|
||||
* Applies the transform on the recents animation
|
||||
*/
|
||||
protected void applyTransformUnchecked() {
|
||||
float shift = mCurrentShift.value;
|
||||
float offset = mRecentsView == null ? 0 : mRecentsView.getScrollOffsetScaled();
|
||||
float taskSize = getOrientationHandler()
|
||||
.getPrimarySize(mAppWindowAnimationHelper.getTargetRect());
|
||||
float offsetScale = getTaskCurveScaleForOffset(offset, taskSize);
|
||||
mTransformParams
|
||||
.setProgress(shift)
|
||||
.setOffset(offset)
|
||||
.setOffsetScale(offsetScale)
|
||||
.setTargetSet(mRecentsAnimationTargets)
|
||||
.setLauncherOnTop(true);
|
||||
mAppWindowAnimationHelper.applyTransform(mTransformParams);
|
||||
}
|
||||
protected void applyWindowTransform() {
|
||||
if (mWindowTransitionController != null) {
|
||||
float progress = mCurrentShift.value / mDragLengthFactor;
|
||||
mWindowTransitionController.setPlayFraction(progress);
|
||||
mTransformParams.setTargetSet(mRecentsAnimationTargets);
|
||||
|
||||
private float getTaskCurveScaleForOffset(float offset, float taskSize) {
|
||||
int dpPixel = getOrientationHandler().getShortEdgeLength(mDp);
|
||||
float distanceToReachEdge = dpPixel / 2 + taskSize / 2 + mPageSpacing;
|
||||
float interpolation = Math.min(1, offset / distanceToReachEdge);
|
||||
return TaskView.getCurveScaleForInterpolation(interpolation);
|
||||
if (mRecentsViewScrollLinked) {
|
||||
mTaskViewSimulator.setScroll(mRecentsView.getScrollOffset());
|
||||
}
|
||||
mTaskViewSimulator.apply(mTransformParams);
|
||||
}
|
||||
}
|
||||
|
||||
protected PagedOrientationHandler getOrientationHandler() {
|
||||
if (mOrientedState == null) {
|
||||
return PagedOrientationHandler.PORTRAIT;
|
||||
}
|
||||
return mOrientedState.getOrientationHandler();
|
||||
return mTaskViewSimulator.getOrientationState().getOrientationHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -451,104 +476,40 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
|||
protected RectFSpringAnim createWindowAnimationToHome(float startProgress,
|
||||
HomeAnimationFactory homeAnimationFactory) {
|
||||
final RectF targetRect = homeAnimationFactory.getWindowTargetRect();
|
||||
final View floatingView = homeAnimationFactory.getFloatingView();
|
||||
final boolean isFloatingIconView = floatingView instanceof FloatingIconView;
|
||||
final RectF startRect = new RectF(
|
||||
mAppWindowAnimationHelper.applyTransform(
|
||||
mTransformParams.setProgress(startProgress)
|
||||
.setTargetSet(mRecentsAnimationTargets)
|
||||
.setLauncherOnTop(false)));
|
||||
if (isFloatingIconView) {
|
||||
mOrientedState.mapInverseRectFromNormalOrientation(
|
||||
startRect, mDp.widthPx, mDp.heightPx);
|
||||
}
|
||||
final FloatingIconView fiv = homeAnimationFactory.mIconView;
|
||||
final boolean isFloatingIconView = fiv != null;
|
||||
|
||||
mWindowTransitionController.setPlayFraction(startProgress / mDragLengthFactor);
|
||||
mTaskViewSimulator.apply(mTransformParams
|
||||
.setProgress(startProgress)
|
||||
.setTargetSet(mRecentsAnimationTargets));
|
||||
RectF cropRectF = new RectF(mTaskViewSimulator.getCurrentCropRect());
|
||||
|
||||
// Matrix to map a rect in Launcher space to window space
|
||||
Matrix homeToWindowPositionMap = new Matrix();
|
||||
mTaskViewSimulator.applyWindowToHomeRotation(homeToWindowPositionMap);
|
||||
|
||||
final RectF startRect = new RectF(cropRectF);
|
||||
mTaskViewSimulator.getCurrentMatrix().mapRect(startRect);
|
||||
// Move the startRect to Launcher space as floatingIconView runs in Launcher
|
||||
Matrix windowToHomePositionMap = new Matrix();
|
||||
homeToWindowPositionMap.invert(windowToHomePositionMap);
|
||||
windowToHomePositionMap.mapRect(startRect);
|
||||
|
||||
RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mContext);
|
||||
if (isFloatingIconView) {
|
||||
FloatingIconView fiv = (FloatingIconView) floatingView;
|
||||
anim.addAnimatorListener(fiv);
|
||||
fiv.setOnTargetChangeListener(anim::onTargetPositionChanged);
|
||||
fiv.setFastFinishRunnable(anim::end);
|
||||
}
|
||||
|
||||
AnimatorPlaybackController homeAnim = homeAnimationFactory.createActivityAnimationToHome();
|
||||
|
||||
// End on a "round-enough" radius so that the shape reveal doesn't have to do too much
|
||||
// rounding at the end of the animation.
|
||||
float startRadius = mAppWindowAnimationHelper.getCurrentCornerRadius();
|
||||
float endRadius = startRect.width() / 6f;
|
||||
|
||||
float startTransformProgress = mTransformParams.getProgress();
|
||||
float endTransformProgress = 1;
|
||||
|
||||
// We want the window alpha to be 0 once this threshold is met, so that the
|
||||
// FolderIconView can be seen morphing into the icon shape.
|
||||
final float windowAlphaThreshold = isFloatingIconView ? 1f - SHAPE_PROGRESS_DURATION : 1f;
|
||||
final RectF rotatedRect = new RectF();
|
||||
anim.addOnUpdateListener(new RectFSpringAnim.OnUpdateListener() {
|
||||
|
||||
@Override
|
||||
public void onUpdate(RectF currentRect, float progress) {
|
||||
homeAnim.setPlayFraction(progress);
|
||||
|
||||
rotatedRect.set(currentRect);
|
||||
if (isFloatingIconView) {
|
||||
mOrientedState.mapRectFromNormalOrientation(
|
||||
rotatedRect, mDp.widthPx, mDp.heightPx);
|
||||
mTransformParams.setCornerRadius(endRadius * progress + startRadius
|
||||
* (1f - progress));
|
||||
}
|
||||
mTransformParams.setProgress(
|
||||
Utilities.mapRange(progress, startTransformProgress, endTransformProgress))
|
||||
.setCurrentRect(rotatedRect)
|
||||
.setTargetAlpha(getWindowAlpha(progress));
|
||||
mAppWindowAnimationHelper.applyTransform(mTransformParams);
|
||||
|
||||
if (isFloatingIconView) {
|
||||
((FloatingIconView) floatingView).update(currentRect, 1f, progress,
|
||||
windowAlphaThreshold, mAppWindowAnimationHelper.getCurrentCornerRadius(),
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
if (isFloatingIconView) {
|
||||
((FloatingIconView) floatingView).fastFinish();
|
||||
}
|
||||
}
|
||||
});
|
||||
anim.addAnimatorListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
homeAnim.dispatchOnStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
homeAnim.getAnimationPlayer().end();
|
||||
}
|
||||
});
|
||||
SpringAnimationRunner runner = new SpringAnimationRunner(
|
||||
homeAnimationFactory, cropRectF, homeToWindowPositionMap);
|
||||
anim.addOnUpdateListener(runner);
|
||||
anim.addAnimatorListener(runner);
|
||||
return anim;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param progress The progress of the animation to the home screen.
|
||||
* @return The current alpha to set on the animating app window.
|
||||
*/
|
||||
protected float getWindowAlpha(float progress) {
|
||||
// Alpha interpolates between [1, 0] between progress values [start, end]
|
||||
final float start = 0f;
|
||||
final float end = 0.85f;
|
||||
|
||||
if (progress <= start) {
|
||||
return 1f;
|
||||
}
|
||||
if (progress >= end) {
|
||||
return 0f;
|
||||
}
|
||||
return Utilities.mapToRange(progress, start, end, 1, 0, ACCEL_1_5);
|
||||
}
|
||||
|
||||
public interface Factory {
|
||||
|
||||
BaseSwipeUpHandler newHandler(GestureState gestureState, long touchTimeMs,
|
||||
|
@ -588,4 +549,135 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param progress The progress of the animation to the home screen.
|
||||
* @return The current alpha to set on the animating app window.
|
||||
*/
|
||||
protected float getWindowAlpha(float progress) {
|
||||
// Alpha interpolates between [1, 0] between progress values [start, end]
|
||||
final float start = 0f;
|
||||
final float end = 0.85f;
|
||||
|
||||
if (progress <= start) {
|
||||
return 1f;
|
||||
}
|
||||
if (progress >= end) {
|
||||
return 0f;
|
||||
}
|
||||
return Utilities.mapToRange(progress, start, end, 1, 0, ACCEL_1_5);
|
||||
}
|
||||
|
||||
protected abstract class HomeAnimationFactory {
|
||||
|
||||
private FloatingIconView mIconView;
|
||||
|
||||
public HomeAnimationFactory(@Nullable FloatingIconView iconView) {
|
||||
mIconView = iconView;
|
||||
}
|
||||
|
||||
public @NonNull RectF getWindowTargetRect() {
|
||||
PagedOrientationHandler orientationHandler = getOrientationHandler();
|
||||
DeviceProfile dp = mDp;
|
||||
final int halfIconSize = dp.iconSizePx / 2;
|
||||
float primaryDimension = orientationHandler
|
||||
.getPrimaryValue(dp.availableWidthPx, dp.availableHeightPx);
|
||||
float secondaryDimension = orientationHandler
|
||||
.getSecondaryValue(dp.availableWidthPx, dp.availableHeightPx);
|
||||
final float targetX = primaryDimension / 2f;
|
||||
final float targetY = secondaryDimension - dp.hotseatBarSizePx;
|
||||
// Fallback to animate to center of screen.
|
||||
return new RectF(targetX - halfIconSize, targetY - halfIconSize,
|
||||
targetX + halfIconSize, targetY + halfIconSize);
|
||||
}
|
||||
|
||||
public abstract @NonNull AnimatorPlaybackController createActivityAnimationToHome();
|
||||
|
||||
public void playAtomicAnimation(float velocity) {
|
||||
// No-op
|
||||
}
|
||||
}
|
||||
|
||||
private class SpringAnimationRunner extends AnimationSuccessListener
|
||||
implements RectFSpringAnim.OnUpdateListener, BuilderProxy {
|
||||
|
||||
final Rect mCropRect = new Rect();
|
||||
final Matrix mMatrix = new Matrix();
|
||||
|
||||
final RectF mWindowCurrentRect = new RectF();
|
||||
final Matrix mHomeToWindowPositionMap;
|
||||
|
||||
final FloatingIconView mFIV;
|
||||
final AnimatorPlaybackController mHomeAnim;
|
||||
final RectF mCropRectF;
|
||||
|
||||
final float mStartRadius;
|
||||
final float mEndRadius;
|
||||
final float mWindowAlphaThreshold;
|
||||
|
||||
SpringAnimationRunner(HomeAnimationFactory factory, RectF cropRectF,
|
||||
Matrix homeToWindowPositionMap) {
|
||||
mHomeAnim = factory.createActivityAnimationToHome();
|
||||
mCropRectF = cropRectF;
|
||||
mHomeToWindowPositionMap = homeToWindowPositionMap;
|
||||
|
||||
cropRectF.roundOut(mCropRect);
|
||||
mFIV = factory.mIconView;
|
||||
|
||||
// End on a "round-enough" radius so that the shape reveal doesn't have to do too much
|
||||
// rounding at the end of the animation.
|
||||
mStartRadius = mTaskViewSimulator.getCurrentCornerRadius();
|
||||
mEndRadius = cropRectF.width() / 2f;
|
||||
|
||||
// We want the window alpha to be 0 once this threshold is met, so that the
|
||||
// FolderIconView can be seen morphing into the icon shape.
|
||||
mWindowAlphaThreshold = mFIV != null ? 1f - SHAPE_PROGRESS_DURATION : 1f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(RectF currentRect, float progress) {
|
||||
mHomeAnim.setPlayFraction(progress);
|
||||
mHomeToWindowPositionMap.mapRect(mWindowCurrentRect, currentRect);
|
||||
|
||||
mMatrix.setRectToRect(mCropRectF, mWindowCurrentRect, ScaleToFit.FILL);
|
||||
float cornerRadius = Utilities.mapRange(progress, mStartRadius, mEndRadius);
|
||||
mTransformParams
|
||||
.setTargetAlpha(getWindowAlpha(progress))
|
||||
.setCornerRadius(cornerRadius);
|
||||
|
||||
mTransformParams.applySurfaceParams(mTransformParams.createSurfaceParams(this));
|
||||
if (mFIV != null) {
|
||||
mFIV.update(currentRect, 1f, progress,
|
||||
mWindowAlphaThreshold, mMatrix.mapRadius(cornerRadius), false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBuildParams(Builder builder, RemoteAnimationTargetCompat app, int targetMode,
|
||||
TransformParams params) {
|
||||
if (app.mode == targetMode
|
||||
&& app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
|
||||
builder.withMatrix(mMatrix)
|
||||
.withWindowCrop(mCropRect)
|
||||
.withCornerRadius(params.getCornerRadius());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
if (mFIV != null) {
|
||||
mFIV.fastFinish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mHomeAnim.dispatchOnStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
mHomeAnim.getAnimationPlayer().end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,25 +15,23 @@
|
|||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
|
||||
import static com.android.quickstep.fallback.FallbackRecentsView.ZOOM_PROGRESS;
|
||||
import static com.android.quickstep.fallback.RecentsState.BACKGROUND_APP;
|
||||
import static com.android.quickstep.fallback.RecentsState.DEFAULT;
|
||||
import static com.android.quickstep.util.WindowSizeStrategy.FALLBACK_RECENTS_SIZE_STRATEGY;
|
||||
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
|
||||
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.quickstep.fallback.FallbackRecentsView;
|
||||
import com.android.quickstep.util.ActivityInitListener;
|
||||
|
@ -89,54 +87,17 @@ public final class FallbackActivityInterface implements
|
|||
// set to zero prior to this class becoming active.
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public HomeAnimationFactory prepareHomeUI() {
|
||||
public AnimationFactory prepareRecentsUI(
|
||||
boolean activityVisible, Consumer<AnimatorPlaybackController> callback) {
|
||||
RecentsActivity activity = getCreatedActivity();
|
||||
RecentsView recentsView = activity.getOverviewPanel();
|
||||
|
||||
return new HomeAnimationFactory() {
|
||||
@NonNull
|
||||
@Override
|
||||
public RectF getWindowTargetRect() {
|
||||
float centerX = recentsView.getPivotX();
|
||||
float centerY = recentsView.getPivotY();
|
||||
return new RectF(centerX, centerY, centerX, centerY);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public AnimatorPlaybackController createActivityAnimationToHome() {
|
||||
Animator anim = ObjectAnimator.ofFloat(recentsView, CONTENT_ALPHA, 0);
|
||||
anim.addListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
recentsView.startHome();
|
||||
}
|
||||
});
|
||||
AnimatorSet animatorSet = new AnimatorSet();
|
||||
animatorSet.play(anim);
|
||||
long accuracy = 2 * Math.max(recentsView.getWidth(), recentsView.getHeight());
|
||||
return AnimatorPlaybackController.wrap(animatorSet, accuracy);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnimationFactory prepareRecentsUI(boolean activityVisible,
|
||||
boolean animateActivity, Consumer<AnimatorPlaybackController> callback) {
|
||||
RecentsActivity activity = getCreatedActivity();
|
||||
if (activityVisible) {
|
||||
if (activity == null) {
|
||||
return (transitionLength) -> { };
|
||||
}
|
||||
|
||||
activity.getStateManager().goToState(BACKGROUND_APP);
|
||||
FallbackRecentsView rv = activity.getOverviewPanel();
|
||||
rv.setContentAlpha(0);
|
||||
rv.getClearAllButton().setVisibilityAlpha(0);
|
||||
rv.setDisallowScrollToClearAll(true);
|
||||
|
||||
boolean fromState = !animateActivity;
|
||||
rv.setInOverviewState(fromState);
|
||||
|
||||
return new AnimationFactory() {
|
||||
|
||||
|
@ -154,27 +115,19 @@ public final class FallbackActivityInterface implements
|
|||
|
||||
@Override
|
||||
public void createActivityInterface(long transitionLength) {
|
||||
AnimatorSet animatorSet = new AnimatorSet();
|
||||
PendingAnimation pa = new PendingAnimation(transitionLength * 2);
|
||||
|
||||
if (isAnimatingToRecents) {
|
||||
ObjectAnimator anim = ObjectAnimator.ofFloat(rv, CONTENT_ALPHA, 0, 1);
|
||||
anim.setDuration(transitionLength).setInterpolator(LINEAR);
|
||||
animatorSet.play(anim);
|
||||
pa.addFloat(rv, CONTENT_ALPHA, 0, 1, LINEAR);
|
||||
}
|
||||
|
||||
ObjectAnimator anim = ObjectAnimator.ofFloat(rv, ZOOM_PROGRESS, 1, 0);
|
||||
anim.setDuration(transitionLength).setInterpolator(LINEAR);
|
||||
animatorSet.play(anim);
|
||||
|
||||
AnimatorPlaybackController controller =
|
||||
AnimatorPlaybackController.wrap(animatorSet, transitionLength);
|
||||
pa.addFloat(rv, SCALE_PROPERTY, rv.getMaxScaleForFullScreen(), 1, LINEAR);
|
||||
pa.addFloat(rv, FULLSCREEN_PROGRESS, 1, 0, LINEAR);
|
||||
AnimatorPlaybackController controller = pa.createPlaybackController();
|
||||
|
||||
// Since we are changing the start position of the UI, reapply the state, at the end
|
||||
controller.setEndAction(() -> {
|
||||
boolean endState = true;
|
||||
rv.setInOverviewState(controller.getInterpolatedProgress() > 0.5 ?
|
||||
endState : fromState);
|
||||
});
|
||||
|
||||
controller.setEndAction(() -> activity.getStateManager().goToState(
|
||||
controller.getInterpolatedProgress() > 0.5 ? DEFAULT : BACKGROUND_APP));
|
||||
callback.accept(controller);
|
||||
}
|
||||
};
|
||||
|
@ -190,7 +143,7 @@ public final class FallbackActivityInterface implements
|
|||
@Nullable
|
||||
@Override
|
||||
public RecentsActivity getCreatedActivity() {
|
||||
return BaseRecentsActivity.ACTIVITY_TRACKER.getCreatedActivity();
|
||||
return RecentsActivity.ACTIVITY_TRACKER.getCreatedActivity();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
|
|
@ -24,6 +24,7 @@ import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS;
|
|||
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
|
||||
import static com.android.quickstep.RecentsActivity.EXTRA_TASK_ID;
|
||||
import static com.android.quickstep.RecentsActivity.EXTRA_THUMBNAIL;
|
||||
import static com.android.quickstep.util.WindowSizeStrategy.FALLBACK_RECENTS_SIZE_STRATEGY;
|
||||
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
|
||||
|
||||
import android.animation.Animator;
|
||||
|
@ -32,25 +33,24 @@ import android.app.ActivityOptions;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Bundle;
|
||||
import android.util.ArrayMap;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.launcher3.util.ObjectWrapper;
|
||||
import com.android.quickstep.BaseActivityInterface.HomeAnimationFactory;
|
||||
import com.android.quickstep.BaseActivityInterface.AnimationFactory;
|
||||
import com.android.quickstep.GestureState.GestureEndTarget;
|
||||
import com.android.quickstep.fallback.FallbackRecentsView;
|
||||
import com.android.quickstep.util.RectFSpringAnim;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.ActivityOptionsCompat;
|
||||
import com.android.systemui.shared.system.InputConsumerController;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
|
||||
/**
|
||||
* Handles the navigation gestures when a 3rd party launcher is the default home activity.
|
||||
|
@ -105,10 +105,16 @@ public class FallbackSwipeHandler extends BaseSwipeUpHandler<RecentsActivity, Fa
|
|||
private final PointF mEndVelocityPxPerMs = new PointF(0, 0.5f);
|
||||
private RunningWindowAnim mFinishAnimation;
|
||||
|
||||
// Used to control Recents components throughout the swipe gesture.
|
||||
private AnimatorPlaybackController mLauncherTransitionController;
|
||||
private boolean mHasLauncherTransitionControllerStarted;
|
||||
|
||||
private AnimationFactory mAnimationFactory = (t) -> { };
|
||||
|
||||
public FallbackSwipeHandler(Context context, RecentsAnimationDeviceState deviceState,
|
||||
GestureState gestureState, InputConsumerController inputConsumer,
|
||||
boolean isLikelyToStartNewTask, boolean continuingLastGesture) {
|
||||
super(context, deviceState, gestureState, inputConsumer);
|
||||
super(context, deviceState, gestureState, inputConsumer, FALLBACK_RECENTS_SIZE_STRATEGY);
|
||||
|
||||
mInQuickSwitchMode = isLikelyToStartNewTask || continuingLastGesture;
|
||||
mContinuingLastGesture = continuingLastGesture;
|
||||
|
@ -118,9 +124,9 @@ public class FallbackSwipeHandler extends BaseSwipeUpHandler<RecentsActivity, Fa
|
|||
// Keep the home launcher invisible until we decide to land there.
|
||||
mLauncherAlpha.value = mRunningOverHome ? 1 : 0;
|
||||
if (mSwipeUpOverHome) {
|
||||
mAppWindowAnimationHelper.setBaseAlphaCallback((t, a) -> 1 - mLauncherAlpha.value);
|
||||
mTransformParams.setBaseAlphaCallback((t, a) -> 1 - mLauncherAlpha.value);
|
||||
} else {
|
||||
mAppWindowAnimationHelper.setBaseAlphaCallback((t, a) -> mLauncherAlpha.value);
|
||||
mTransformParams.setBaseAlphaCallback((t, a) -> mLauncherAlpha.value);
|
||||
}
|
||||
|
||||
// Going home has an extra long progress to ensure that it animates into the screen
|
||||
|
@ -156,7 +162,7 @@ public class FallbackSwipeHandler extends BaseSwipeUpHandler<RecentsActivity, Fa
|
|||
|
||||
private void onLauncherAlphaChanged() {
|
||||
if (mRecentsAnimationTargets != null && mGestureState.getEndTarget() == null) {
|
||||
applyTransformUnchecked();
|
||||
applyWindowTransform();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,10 +173,6 @@ public class FallbackSwipeHandler extends BaseSwipeUpHandler<RecentsActivity, Fa
|
|||
mRecentsView = mActivity.getOverviewPanel();
|
||||
mRecentsView.setOnPageTransitionEndCallback(null);
|
||||
linkRecentsViewScroll();
|
||||
mRecentsView.setDisallowScrollToClearAll(true);
|
||||
mRecentsView.getClearAllButton().setVisibilityAlpha(0);
|
||||
mRecentsView.setZoomProgress(1);
|
||||
|
||||
if (!mContinuingLastGesture) {
|
||||
if (mRunningOverHome) {
|
||||
mRecentsView.onGestureAnimationStart(mGestureState.getRunningTask());
|
||||
|
@ -180,9 +182,48 @@ public class FallbackSwipeHandler extends BaseSwipeUpHandler<RecentsActivity, Fa
|
|||
}
|
||||
mStateCallback.setStateOnUiThread(STATE_RECENTS_PRESENT);
|
||||
mDeviceState.enableMultipleRegions(false);
|
||||
|
||||
mAnimationFactory = mActivityInterface.prepareRecentsUI(alreadyOnHome,
|
||||
this::onAnimatorPlaybackControllerCreated);
|
||||
mAnimationFactory.createActivityInterface(mTransitionDragLength);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initTransitionEndpoints(DeviceProfile dp) {
|
||||
super.initTransitionEndpoints(dp);
|
||||
if (canCreateNewOrUpdateExistingLauncherTransitionController()) {
|
||||
mAnimationFactory.createActivityInterface(mTransitionDragLength);
|
||||
}
|
||||
}
|
||||
|
||||
private void onAnimatorPlaybackControllerCreated(AnimatorPlaybackController anim) {
|
||||
mLauncherTransitionController = anim;
|
||||
mLauncherTransitionController.dispatchSetInterpolator(t -> t * mDragLengthFactor);
|
||||
mLauncherTransitionController.dispatchOnStart();
|
||||
updateLauncherTransitionProgress();
|
||||
}
|
||||
|
||||
private void updateLauncherTransitionProgress() {
|
||||
if (mLauncherTransitionController == null
|
||||
|| !canCreateNewOrUpdateExistingLauncherTransitionController()) {
|
||||
return;
|
||||
}
|
||||
// Normalize the progress to 0 to 1, as the animation controller will clamp it to that
|
||||
// anyway. The controller mimics the drag length factor by applying it to its interpolators.
|
||||
float progress = mCurrentShift.value / mDragLengthFactor;
|
||||
mLauncherTransitionController.setPlayFraction(progress);
|
||||
}
|
||||
|
||||
/**
|
||||
* We don't want to change mLauncherTransitionController if mGestureState.getEndTarget() == HOME
|
||||
* (it has its own animation) or if we're already animating the current controller.
|
||||
* @return Whether we can create the launcher controller or update its progress.
|
||||
*/
|
||||
private boolean canCreateNewOrUpdateExistingLauncherTransitionController() {
|
||||
return mGestureState.getEndTarget() != HOME && !mHasLauncherTransitionControllerStarted;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean moveWindowWithRecentsScroll() {
|
||||
return mInQuickSwitchMode;
|
||||
|
@ -261,9 +302,8 @@ public class FallbackSwipeHandler extends BaseSwipeUpHandler<RecentsActivity, Fa
|
|||
updateOverviewThresholdPassed(mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW);
|
||||
}
|
||||
|
||||
if (mRecentsAnimationTargets != null) {
|
||||
applyTransformUnchecked();
|
||||
}
|
||||
applyWindowTransform();
|
||||
updateLauncherTransitionProgress();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -320,15 +360,6 @@ public class FallbackSwipeHandler extends BaseSwipeUpHandler<RecentsActivity, Fa
|
|||
}
|
||||
|
||||
if (mRecentsView != null) {
|
||||
if (mFinishingRecentsAnimationForNewTaskId != -1) {
|
||||
TaskView newRunningTaskView = mRecentsView.getTaskView(
|
||||
mFinishingRecentsAnimationForNewTaskId);
|
||||
int newRunningTaskId = newRunningTaskView != null
|
||||
? newRunningTaskView.getTask().key.id
|
||||
: -1;
|
||||
mRecentsView.setCurrentTask(newRunningTaskId);
|
||||
mGestureState.setFinishingRecentsAnimationTaskId(newRunningTaskId);
|
||||
}
|
||||
mRecentsView.setOnScrollChangeListener(null);
|
||||
}
|
||||
} else {
|
||||
|
@ -401,7 +432,7 @@ public class FallbackSwipeHandler extends BaseSwipeUpHandler<RecentsActivity, Fa
|
|||
break;
|
||||
}
|
||||
case NEW_TASK: {
|
||||
startNewTask(STATE_HANDLER_INVALIDATED, b -> {});
|
||||
startNewTask(success -> { });
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -416,7 +447,7 @@ public class FallbackSwipeHandler extends BaseSwipeUpHandler<RecentsActivity, Fa
|
|||
if (mRecentsView == null || !hasTargets()) {
|
||||
mGestureState.setEndTarget(LAST_TASK);
|
||||
} else {
|
||||
final int runningTaskIndex = mRecentsView.getRunningTaskIndex();
|
||||
final int runningTaskIndex = getLastAppearedTaskIndex();
|
||||
final int taskToLaunch = mRecentsView.getNextPage();
|
||||
mGestureState.setEndTarget(
|
||||
(runningTaskIndex >= 0 && taskToLaunch != runningTaskIndex)
|
||||
|
@ -477,11 +508,7 @@ public class FallbackSwipeHandler extends BaseSwipeUpHandler<RecentsActivity, Fa
|
|||
RecentsAnimationTargets targets) {
|
||||
super.onRecentsAnimationStart(controller, targets);
|
||||
mRecentsAnimationController.enableInputConsumer();
|
||||
|
||||
if (mRunningOverHome) {
|
||||
mAppWindowAnimationHelper.prepareAnimation(mDp);
|
||||
}
|
||||
applyTransformUnchecked();
|
||||
applyWindowTransform();
|
||||
|
||||
mStateCallback.setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
|
||||
}
|
||||
|
@ -494,23 +521,17 @@ public class FallbackSwipeHandler extends BaseSwipeUpHandler<RecentsActivity, Fa
|
|||
super.onRecentsAnimationCanceled(thumbnailData);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean handleTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an animation that transforms the current app window into the home app.
|
||||
* @param startProgress The progress of {@link #mCurrentShift} to start the window from.
|
||||
*/
|
||||
private RectFSpringAnim createWindowAnimationToHome(float startProgress, long duration) {
|
||||
HomeAnimationFactory factory = new HomeAnimationFactory() {
|
||||
@Override
|
||||
public RectF getWindowTargetRect() {
|
||||
PagedOrientationHandler orientationHandler = mRecentsView != null
|
||||
? mRecentsView.getPagedOrientationHandler()
|
||||
: (mDp.isLandscape
|
||||
? PagedOrientationHandler.LANDSCAPE
|
||||
: PagedOrientationHandler.PORTRAIT);
|
||||
return HomeAnimationFactory
|
||||
.getDefaultWindowTargetRect(orientationHandler, mDp);
|
||||
}
|
||||
|
||||
HomeAnimationFactory factory = new HomeAnimationFactory(null) {
|
||||
@Override
|
||||
public AnimatorPlaybackController createActivityAnimationToHome() {
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
|
|
|
@ -16,32 +16,26 @@
|
|||
package com.android.quickstep;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_RECENTS_FADE_ANIM;
|
||||
import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_RECENTS_TRANSLATE_X_ANIM;
|
||||
import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_SHELF_ANIM;
|
||||
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.anim.Interpolators.ACCEL_2;
|
||||
import static com.android.launcher3.anim.Interpolators.INSTANT;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_RECENTS_FADE_ANIM;
|
||||
import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_RECENTS_TRANSLATE_X_ANIM;
|
||||
import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_SHELF_ANIM;
|
||||
import static com.android.quickstep.LauncherSwipeHandler.RECENTS_ATTACH_DURATION;
|
||||
import static com.android.quickstep.util.WindowSizeStrategy.LAUNCHER_ACTIVITY_SIZE_STRATEGY;
|
||||
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
|
||||
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Pair;
|
||||
import android.util.Log;
|
||||
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;
|
||||
|
||||
|
@ -52,20 +46,19 @@ import com.android.launcher3.LauncherInitListener;
|
|||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.allapps.DiscoveryBounce;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.appprediction.PredictionUiStateManager;
|
||||
import com.android.launcher3.statehandlers.DepthController;
|
||||
import com.android.launcher3.statehandlers.DepthController.ClampedDepthProperty;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.views.FloatingIconView;
|
||||
import com.android.quickstep.SysUINavigationMode.Mode;
|
||||
import com.android.quickstep.util.ActivityInitListener;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
import com.android.quickstep.util.ShelfPeekAnim;
|
||||
import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
|
||||
import com.android.quickstep.util.StaggeredWorkspaceAnim;
|
||||
import com.android.quickstep.views.LauncherRecentsView;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.plugins.shared.LauncherOverlayManager;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
|
@ -78,9 +71,6 @@ import java.util.function.Predicate;
|
|||
*/
|
||||
public final class LauncherActivityInterface implements BaseActivityInterface<Launcher> {
|
||||
|
||||
private Pair<Float, Float> mSwipeUpPullbackStartAndMaxProgress =
|
||||
BaseActivityInterface.super.getSwipeUpPullbackStartAndMaxProgress();
|
||||
|
||||
@Override
|
||||
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
|
||||
LAUNCHER_ACTIVITY_SIZE_STRATEGY.calculateTaskSize(context, dp, outRect);
|
||||
|
@ -93,11 +83,6 @@ public final class LauncherActivityInterface implements BaseActivityInterface<La
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<Float, Float> getSwipeUpPullbackStartAndMaxProgress() {
|
||||
return mSwipeUpPullbackStartAndMaxProgress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionCancelled(boolean activityVisible) {
|
||||
Launcher launcher = getCreatedActivity();
|
||||
|
@ -148,66 +133,9 @@ public final class LauncherActivityInterface implements BaseActivityInterface<La
|
|||
launcher.onAssistantVisibilityChanged(visibility);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public HomeAnimationFactory prepareHomeUI() {
|
||||
Launcher launcher = getCreatedActivity();
|
||||
final DeviceProfile dp = launcher.getDeviceProfile();
|
||||
final RecentsView recentsView = launcher.getOverviewPanel();
|
||||
final TaskView runningTaskView = recentsView.getRunningTaskView();
|
||||
final View workspaceView;
|
||||
if (runningTaskView != null && runningTaskView.getTask().key.getComponent() != null) {
|
||||
workspaceView = launcher.getWorkspace().getFirstMatchForAppClose(
|
||||
runningTaskView.getTask().key.getComponent().getPackageName(),
|
||||
UserHandle.of(runningTaskView.getTask().key.userId));
|
||||
} else {
|
||||
workspaceView = null;
|
||||
}
|
||||
final RectF iconLocation = new RectF();
|
||||
boolean canUseWorkspaceView = workspaceView != null && workspaceView.isAttachedToWindow();
|
||||
FloatingIconView floatingIconView = canUseWorkspaceView
|
||||
? FloatingIconView.getFloatingIconView(launcher, workspaceView,
|
||||
true /* hideOriginal */, iconLocation, false /* isOpening */)
|
||||
: null;
|
||||
setLauncherHideBackArrow(true);
|
||||
return new HomeAnimationFactory() {
|
||||
@Nullable
|
||||
@Override
|
||||
public View getFloatingView() {
|
||||
return floatingIconView;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RectF getWindowTargetRect() {
|
||||
if (canUseWorkspaceView) {
|
||||
return iconLocation;
|
||||
} else {
|
||||
return HomeAnimationFactory
|
||||
.getDefaultWindowTargetRect(recentsView.getPagedOrientationHandler(), dp);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public AnimatorPlaybackController createActivityAnimationToHome() {
|
||||
// Return an empty APC here since we have an non-user controlled animation to home.
|
||||
long accuracy = 2 * Math.max(dp.widthPx, dp.heightPx);
|
||||
return launcher.getStateManager().createAnimationToNewWorkspace(NORMAL, accuracy,
|
||||
0 /* animComponents */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playAtomicAnimation(float velocity) {
|
||||
new StaggeredWorkspaceAnim(launcher, velocity, true /* animateOverviewScrim */)
|
||||
.start();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnimationFactory prepareRecentsUI(boolean activityVisible,
|
||||
boolean animateActivity, Consumer<AnimatorPlaybackController> callback) {
|
||||
public AnimationFactory prepareRecentsUI(
|
||||
boolean activityVisible, Consumer<AnimatorPlaybackController> callback) {
|
||||
BaseQuickstepLauncher launcher = getCreatedActivity();
|
||||
final LauncherState startState = launcher.getStateManager().getState();
|
||||
|
||||
|
@ -217,8 +145,7 @@ public final class LauncherActivityInterface implements BaseActivityInterface<La
|
|||
}
|
||||
launcher.getStateManager().setRestState(resetState);
|
||||
|
||||
final LauncherState fromState = animateActivity ? BACKGROUND_APP : OVERVIEW;
|
||||
launcher.getStateManager().goToState(fromState, false);
|
||||
launcher.getStateManager().goToState(BACKGROUND_APP, false);
|
||||
// Since all apps is not visible, we can safely reset the scroll position.
|
||||
// This ensures then the next swipe up to all-apps starts from scroll 0.
|
||||
launcher.getAppsView().reset(false /* animate */);
|
||||
|
@ -229,7 +156,7 @@ public final class LauncherActivityInterface implements BaseActivityInterface<La
|
|||
|
||||
@Override
|
||||
public void createActivityInterface(long transitionLength) {
|
||||
createActivityInterfaceInternal(launcher, fromState, transitionLength, callback);
|
||||
callback.accept(createBackgroundToOverviewAnim(launcher, transitionLength));
|
||||
// Creating the activity controller animation sometimes reapplies the launcher state
|
||||
// (because we set the animation as the current state animation), so we reapply the
|
||||
// attached state here as well to ensure recents is shown/hidden appropriately.
|
||||
|
@ -283,74 +210,45 @@ public final class LauncherActivityInterface implements BaseActivityInterface<La
|
|||
};
|
||||
}
|
||||
|
||||
private void createActivityInterfaceInternal(Launcher activity, LauncherState fromState,
|
||||
long transitionLength, Consumer<AnimatorPlaybackController> callback) {
|
||||
LauncherState endState = OVERVIEW;
|
||||
if (fromState == endState) {
|
||||
return;
|
||||
}
|
||||
private AnimatorPlaybackController createBackgroundToOverviewAnim(
|
||||
Launcher activity, long transitionLength) {
|
||||
|
||||
PendingAnimation pa = new PendingAnimation(transitionLength * 2);
|
||||
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
if (!activity.getDeviceProfile().isVerticalBarLayout()
|
||||
&& SysUINavigationMode.getMode(activity) != Mode.NO_BUTTON) {
|
||||
// Don't animate the shelf when the mode is NO_BUTTON, because we update it atomically.
|
||||
anim.play(activity.getStateManager().createStateElementAnimation(
|
||||
pa.add(activity.getStateManager().createStateElementAnimation(
|
||||
INDEX_SHELF_ANIM,
|
||||
fromState.getVerticalProgress(activity),
|
||||
endState.getVerticalProgress(activity)));
|
||||
BACKGROUND_APP.getVerticalProgress(activity),
|
||||
OVERVIEW.getVerticalProgress(activity)));
|
||||
}
|
||||
|
||||
// Animate the blur and wallpaper zoom
|
||||
DepthController depthController = getDepthController();
|
||||
float fromDepthRatio = fromState.getDepth(activity);
|
||||
float toDepthRatio = endState.getDepth(activity);
|
||||
Animator depthAnimator = ObjectAnimator.ofFloat(depthController,
|
||||
new ClampedDepthProperty(fromDepthRatio, toDepthRatio),
|
||||
fromDepthRatio, toDepthRatio);
|
||||
anim.play(depthAnimator);
|
||||
float fromDepthRatio = BACKGROUND_APP.getDepth(activity);
|
||||
float toDepthRatio = OVERVIEW.getDepth(activity);
|
||||
pa.addFloat(getDepthController(), new ClampedDepthProperty(fromDepthRatio, toDepthRatio),
|
||||
fromDepthRatio, toDepthRatio, LINEAR);
|
||||
|
||||
playScaleDownAnim(anim, activity, fromState, endState);
|
||||
|
||||
anim.setDuration(transitionLength * 2);
|
||||
anim.setInterpolator(LINEAR);
|
||||
AnimatorPlaybackController controller =
|
||||
AnimatorPlaybackController.wrap(anim, transitionLength * 2);
|
||||
// Scale down recents from being full screen to being in overview.
|
||||
RecentsView recentsView = activity.getOverviewPanel();
|
||||
pa.addFloat(recentsView, SCALE_PROPERTY,
|
||||
BACKGROUND_APP.getOverviewScaleAndOffset(activity)[0],
|
||||
OVERVIEW.getOverviewScaleAndOffset(activity)[0],
|
||||
LINEAR);
|
||||
pa.addFloat(recentsView, FULLSCREEN_PROGRESS,
|
||||
BACKGROUND_APP.getOverviewFullscreenProgress(),
|
||||
OVERVIEW.getOverviewFullscreenProgress(),
|
||||
LINEAR);
|
||||
|
||||
AnimatorPlaybackController controller = pa.createPlaybackController();
|
||||
activity.getStateManager().setCurrentUserControlledAnimation(controller);
|
||||
|
||||
// Since we are changing the start position of the UI, reapply the state, at the end
|
||||
controller.setEndAction(() -> {
|
||||
activity.getStateManager().goToState(
|
||||
controller.getInterpolatedProgress() > 0.5 ? endState : fromState, false);
|
||||
});
|
||||
callback.accept(controller);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale down recents from the center task being full screen to being in overview.
|
||||
*/
|
||||
private void playScaleDownAnim(AnimatorSet anim, Launcher launcher, LauncherState fromState,
|
||||
LauncherState endState) {
|
||||
RecentsView recentsView = launcher.getOverviewPanel();
|
||||
if (recentsView.getCurrentPageTaskView() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
float fromFullscreenProgress = fromState.getOverviewFullscreenProgress();
|
||||
float endFullscreenProgress = endState.getOverviewFullscreenProgress();
|
||||
|
||||
float fromScale = fromState.getOverviewScaleAndOffset(launcher)[0];
|
||||
float endScale = endState.getOverviewScaleAndOffset(launcher)[0];
|
||||
|
||||
Animator scale = ObjectAnimator.ofFloat(recentsView, SCALE_PROPERTY, fromScale, endScale);
|
||||
Animator applyFullscreenProgress = ObjectAnimator.ofFloat(recentsView,
|
||||
RecentsView.FULLSCREEN_PROGRESS, fromFullscreenProgress, endFullscreenProgress);
|
||||
anim.playTogether(scale, applyFullscreenProgress);
|
||||
|
||||
// Start pulling back when RecentsView scale is 0.75f, and let it go down to 0.5f.
|
||||
float pullbackStartProgress = (0.75f - fromScale) / (endScale - fromScale);
|
||||
float pullbackMaxProgress = (0.5f - fromScale) / (endScale - fromScale);
|
||||
mSwipeUpPullbackStartAndMaxProgress = new Pair<>(
|
||||
pullbackStartProgress, pullbackMaxProgress);
|
||||
controller.setEndAction(() -> activity.getStateManager().goToState(
|
||||
controller.getInterpolatedProgress() > 0.5 ? OVERVIEW : BACKGROUND_APP, false));
|
||||
return controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -383,6 +281,9 @@ public final class LauncherActivityInterface implements BaseActivityInterface<La
|
|||
|
||||
@Override
|
||||
public boolean switchToRecentsIfVisible(Runnable onCompleteCallback) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.OVERIEW_NOT_ALLAPPS, "switchToRecentsIfVisible");
|
||||
}
|
||||
Launcher launcher = getVisibleLauncher();
|
||||
if (launcher == null) {
|
||||
return false;
|
||||
|
|
|
@ -17,8 +17,7 @@ package com.android.quickstep;
|
|||
|
||||
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
|
||||
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
|
||||
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
|
||||
|
@ -32,7 +31,6 @@ import static com.android.quickstep.GestureState.GestureEndTarget.NEW_TASK;
|
|||
import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS;
|
||||
import static com.android.quickstep.GestureState.STATE_END_TARGET_ANIMATION_FINISHED;
|
||||
import static com.android.quickstep.GestureState.STATE_RECENTS_SCROLLING_FINISHED;
|
||||
import static com.android.quickstep.GestureState.STATE_TASK_APPEARED_DURING_SWITCH;
|
||||
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
|
||||
import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.HIDE;
|
||||
|
@ -42,17 +40,16 @@ import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHO
|
|||
|
||||
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.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Build;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.view.View;
|
||||
import android.view.View.OnApplyWindowInsetsListener;
|
||||
import android.view.ViewTreeObserver.OnDrawListener;
|
||||
|
@ -65,6 +62,7 @@ import androidx.annotation.UiThread;
|
|||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
|
@ -75,16 +73,16 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
|
|||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.launcher3.views.FloatingIconView;
|
||||
import com.android.quickstep.BaseActivityInterface.AnimationFactory;
|
||||
import com.android.quickstep.BaseActivityInterface.HomeAnimationFactory;
|
||||
import com.android.quickstep.GestureState.GestureEndTarget;
|
||||
import com.android.quickstep.inputconsumers.OverviewInputConsumer;
|
||||
import com.android.quickstep.util.ActiveGestureLog;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper.TargetAlphaProvider;
|
||||
import com.android.quickstep.util.RectFSpringAnim;
|
||||
import com.android.quickstep.util.ShelfPeekAnim;
|
||||
import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
|
||||
import com.android.quickstep.util.TaskViewSimulator;
|
||||
import com.android.quickstep.util.StaggeredWorkspaceAnim;
|
||||
import com.android.quickstep.util.TransformParams.TargetAlphaProvider;
|
||||
import com.android.quickstep.views.LiveTileOverlay;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
|
@ -97,8 +95,8 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
|||
* Handles the navigation gestures when Launcher is the default home activity.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
||||
extends BaseSwipeUpHandler<T, RecentsView> implements OnApplyWindowInsetsListener {
|
||||
public class LauncherSwipeHandler extends BaseSwipeUpHandler<Launcher, RecentsView>
|
||||
implements OnApplyWindowInsetsListener {
|
||||
private static final String TAG = LauncherSwipeHandler.class.getSimpleName();
|
||||
|
||||
private static final String[] STATE_NAMES = DEBUG_STATES ? new String[16] : null;
|
||||
|
@ -152,7 +150,6 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
|||
STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_LAUNCHER_STARTED;
|
||||
|
||||
public static final long MAX_SWIPE_DURATION = 350;
|
||||
public static final long MIN_SWIPE_DURATION = 80;
|
||||
public static final long MIN_OVERSHOOT_DURATION = 120;
|
||||
|
||||
public static final float MIN_PROGRESS_FOR_OVERVIEW = 0.7f;
|
||||
|
@ -181,9 +178,6 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
|||
private AnimatorPlaybackController mLauncherTransitionController;
|
||||
private boolean mHasLauncherTransitionControllerStarted;
|
||||
|
||||
private final TaskViewSimulator mTaskViewSimulator;
|
||||
private AnimatorPlaybackController mWindowTransitionController;
|
||||
|
||||
private AnimationFactory mAnimationFactory = (t) -> { };
|
||||
|
||||
private boolean mWasLauncherAlreadyVisible;
|
||||
|
@ -204,11 +198,10 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
|||
TaskAnimationManager taskAnimationManager, GestureState gestureState,
|
||||
long touchTimeMs, boolean continuingLastGesture,
|
||||
InputConsumerController inputConsumer) {
|
||||
super(context, deviceState, gestureState, inputConsumer);
|
||||
super(context, deviceState, gestureState, inputConsumer, LAUNCHER_ACTIVITY_SIZE_STRATEGY);
|
||||
mTaskAnimationManager = taskAnimationManager;
|
||||
mTouchTimeMs = touchTimeMs;
|
||||
mContinuingLastGesture = continuingLastGesture;
|
||||
mTaskViewSimulator = new TaskViewSimulator(context, LAUNCHER_ACTIVITY_SIZE_STRATEGY);
|
||||
|
||||
initAfterSubclassConstructor();
|
||||
initStateCallbacks();
|
||||
|
@ -264,8 +257,6 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
|||
| STATE_RECENTS_SCROLLING_FINISHED,
|
||||
this::onSettledOnEndTarget);
|
||||
|
||||
mGestureState.runOnceAtState(STATE_TASK_APPEARED_DURING_SWITCH, this::onTaskAppeared);
|
||||
|
||||
mStateCallback.runOnceAtState(STATE_HANDLER_INVALIDATED, this::invalidateHandler);
|
||||
mStateCallback.runOnceAtState(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
|
||||
this::invalidateHandlerWithLauncher);
|
||||
|
@ -282,7 +273,7 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
|||
@Override
|
||||
protected boolean onActivityInit(Boolean alreadyOnHome) {
|
||||
super.onActivityInit(alreadyOnHome);
|
||||
final T activity = mActivityInterface.getCreatedActivity();
|
||||
final Launcher activity = mActivityInterface.getCreatedActivity();
|
||||
if (mActivity == activity) {
|
||||
return true;
|
||||
}
|
||||
|
@ -304,7 +295,6 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
|||
|
||||
mRecentsView = activity.getOverviewPanel();
|
||||
mRecentsView.setOnPageTransitionEndCallback(null);
|
||||
linkRecentsViewScroll();
|
||||
addLiveTileOverlay();
|
||||
|
||||
mStateCallback.setState(STATE_LAUNCHER_PRESENT);
|
||||
|
@ -321,6 +311,8 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
|||
// so we need to kick off switching to the overview predictions as soon as possible
|
||||
mActivityInterface.updateOverviewPredictionState();
|
||||
}
|
||||
linkRecentsViewScroll();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -330,7 +322,7 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
|||
}
|
||||
|
||||
private void onLauncherStart() {
|
||||
final T activity = mActivityInterface.getCreatedActivity();
|
||||
final Launcher activity = mActivityInterface.getCreatedActivity();
|
||||
if (mActivity != activity) {
|
||||
return;
|
||||
}
|
||||
|
@ -343,8 +335,7 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
|||
if (mGestureState.getEndTarget() != HOME) {
|
||||
Runnable initAnimFactory = () -> {
|
||||
mAnimationFactory = mActivityInterface.prepareRecentsUI(
|
||||
mWasLauncherAlreadyVisible, true,
|
||||
this::onAnimatorPlaybackControllerCreated);
|
||||
mWasLauncherAlreadyVisible, this::onAnimatorPlaybackControllerCreated);
|
||||
maybeUpdateRecentsAttachedState(false /* animate */);
|
||||
};
|
||||
if (mWasLauncherAlreadyVisible) {
|
||||
|
@ -521,34 +512,6 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
|||
mAnimationFactory.createActivityInterface(mTransitionDragLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateSource(Rect stackBounds, RemoteAnimationTargetCompat runningTarget) {
|
||||
super.updateSource(stackBounds, runningTarget);
|
||||
mTaskViewSimulator.setPreview(runningTarget, mRecentsAnimationTargets);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initTransitionEndpoints(DeviceProfile dp) {
|
||||
super.initTransitionEndpoints(dp);
|
||||
mTaskViewSimulator.setDp(dp);
|
||||
mTaskViewSimulator.setLayoutRotation(
|
||||
mDeviceState.getCurrentActiveRotation(),
|
||||
mDeviceState.getDisplayRotation());
|
||||
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
anim.setDuration(mTransitionDragLength * 2);
|
||||
anim.setInterpolator(t -> t * mDragLengthFactor);
|
||||
anim.play(ObjectAnimator.ofFloat(mTaskViewSimulator.recentsViewScale,
|
||||
AnimatedFloat.VALUE,
|
||||
mTaskViewSimulator.getFullScreenScale(), 1));
|
||||
anim.play(ObjectAnimator.ofFloat(mTaskViewSimulator.fullScreenProgress,
|
||||
AnimatedFloat.VALUE,
|
||||
BACKGROUND_APP.getOverviewFullscreenProgress(),
|
||||
OVERVIEW.getOverviewFullscreenProgress()));
|
||||
mWindowTransitionController =
|
||||
AnimatorPlaybackController.wrap(anim, mTransitionDragLength * 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* We don't want to change mLauncherTransitionController if mGestureState.getEndTarget() == HOME
|
||||
* (it has its own animation) or if we're already animating the current controller.
|
||||
|
@ -579,18 +542,11 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
|||
|
||||
@Override
|
||||
public void updateFinalShift() {
|
||||
if (mRecentsAnimationTargets != null) {
|
||||
// Base class expects applyTransformUnchecked to be called here.
|
||||
// TODO: Remove this dependency for swipe-up animation.
|
||||
// applyTransformUnchecked();
|
||||
updateSysUiFlags(mCurrentShift.value);
|
||||
}
|
||||
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
if (mRecentsAnimationTargets != null) {
|
||||
LiveTileOverlay.INSTANCE.update(
|
||||
mAppWindowAnimationHelper.getCurrentRectWithInsets(),
|
||||
mAppWindowAnimationHelper.getCurrentCornerRadius());
|
||||
mTaskViewSimulator.getCurrentCropRect(),
|
||||
mTaskViewSimulator.getCurrentCornerRadius());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -602,16 +558,8 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
|||
}
|
||||
}
|
||||
|
||||
if (mWindowTransitionController != null) {
|
||||
float progress = mCurrentShift.value / mDragLengthFactor;
|
||||
mWindowTransitionController.setPlayFraction(progress);
|
||||
mTransformParams
|
||||
.setTargetSet(mRecentsAnimationTargets)
|
||||
.setLauncherOnTop(true);
|
||||
|
||||
mTaskViewSimulator.setScroll(mRecentsView == null ? 0 : mRecentsView.getScrollOffset());
|
||||
mTaskViewSimulator.apply(mTransformParams);
|
||||
}
|
||||
updateSysUiFlags(mCurrentShift.value);
|
||||
applyWindowTransform();
|
||||
updateLauncherTransitionProgress();
|
||||
}
|
||||
|
||||
|
@ -685,7 +633,7 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
|||
*/
|
||||
@UiThread
|
||||
private void notifyGestureStartedAsync() {
|
||||
final T curActivity = mActivity;
|
||||
final Launcher curActivity = mActivity;
|
||||
if (curActivity != null) {
|
||||
// Once the gesture starts, we can no longer transition home through the button, so
|
||||
// reset the force override of the activity visibility
|
||||
|
@ -771,20 +719,17 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
|||
}
|
||||
}
|
||||
|
||||
private void onTaskAppeared() {
|
||||
RemoteAnimationTargetCompat app = mGestureState.getAnimationTarget();
|
||||
if (mRecentsAnimationController != null && app != null) {
|
||||
|
||||
// TODO(b/152480470): Update Task target animation after onTaskAppeared holistically.
|
||||
/* android.util.Log.d("LauncherSwipeHandler", "onTaskAppeared");
|
||||
|
||||
final boolean result = mRecentsAnimationController.removeTaskTarget(app);
|
||||
mGestureState.setAnimationTarget(null);
|
||||
android.util.Log.d("LauncherSwipeHandler", "removeTask, result=" + result); */
|
||||
|
||||
mRecentsAnimationController.finish(false /* toRecents */,
|
||||
null /* onFinishComplete */);
|
||||
@Override
|
||||
protected boolean handleTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {
|
||||
if (mStateCallback.hasStates(STATE_HANDLER_INVALIDATED)) {
|
||||
return false;
|
||||
}
|
||||
if (mStateCallback.hasStates(STATE_START_NEW_TASK)
|
||||
&& appearedTaskTarget.taskId == mGestureState.getLastStartedTaskId()) {
|
||||
reset();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private GestureEndTarget calculateEndTarget(PointF velocity, float endVelocity, boolean isFling,
|
||||
|
@ -971,24 +916,61 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
|||
Interpolator interpolator, GestureEndTarget target, PointF velocityPxPerMs) {
|
||||
// Set the state, but don't notify until the animation completes
|
||||
mGestureState.setEndTarget(target, false /* isAtomic */);
|
||||
|
||||
maybeUpdateRecentsAttachedState();
|
||||
|
||||
if (mGestureState.getEndTarget() == HOME) {
|
||||
HomeAnimationFactory homeAnimFactory;
|
||||
if (mActivity != null) {
|
||||
homeAnimFactory = mActivityInterface.prepareHomeUI();
|
||||
} else {
|
||||
homeAnimFactory = new HomeAnimationFactory() {
|
||||
@NonNull
|
||||
final TaskView runningTaskView = mRecentsView.getRunningTaskView();
|
||||
final View workspaceView;
|
||||
if (runningTaskView != null
|
||||
&& runningTaskView.getTask().key.getComponent() != null) {
|
||||
workspaceView = mActivity.getWorkspace().getFirstMatchForAppClose(
|
||||
runningTaskView.getTask().key.getComponent().getPackageName(),
|
||||
UserHandle.of(runningTaskView.getTask().key.userId));
|
||||
} else {
|
||||
workspaceView = null;
|
||||
}
|
||||
final RectF iconLocation = new RectF();
|
||||
boolean canUseWorkspaceView =
|
||||
workspaceView != null && workspaceView.isAttachedToWindow();
|
||||
FloatingIconView floatingIconView = canUseWorkspaceView
|
||||
? FloatingIconView.getFloatingIconView(mActivity, workspaceView,
|
||||
true /* hideOriginal */, iconLocation, false /* isOpening */)
|
||||
: null;
|
||||
|
||||
mActivity.getRootView().setForceHideBackArrow(true);
|
||||
|
||||
homeAnimFactory = new HomeAnimationFactory(floatingIconView) {
|
||||
|
||||
@Override
|
||||
public RectF getWindowTargetRect() {
|
||||
RectF fallbackTarget = new RectF(mAppWindowAnimationHelper.getTargetRect());
|
||||
Utilities.scaleRectFAboutCenter(fallbackTarget, 0.25f);
|
||||
return fallbackTarget;
|
||||
if (canUseWorkspaceView) {
|
||||
return iconLocation;
|
||||
} else {
|
||||
return super.getWindowTargetRect();
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public AnimatorPlaybackController createActivityAnimationToHome() {
|
||||
// Return an empty APC here since we have an non-user controlled animation
|
||||
// to home.
|
||||
long accuracy = 2 * Math.max(mDp.widthPx, mDp.heightPx);
|
||||
return mActivity.getStateManager().createAnimationToNewWorkspace(
|
||||
NORMAL, accuracy, 0 /* animComponents */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playAtomicAnimation(float velocity) {
|
||||
new StaggeredWorkspaceAnim(mActivity, velocity,
|
||||
true /* animateOverviewScrim */).start();
|
||||
}
|
||||
};
|
||||
|
||||
} else {
|
||||
homeAnimFactory = new HomeAnimationFactory(null) {
|
||||
@Override
|
||||
public AnimatorPlaybackController createActivityAnimationToHome() {
|
||||
return AnimatorPlaybackController.wrap(new AnimatorSet(), duration);
|
||||
|
@ -1031,12 +1013,24 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
|||
// skip doing any future work here for the current gesture.
|
||||
return;
|
||||
}
|
||||
if (target == NEW_TASK && mRecentsView != null
|
||||
&& mRecentsView.getNextPage() == mRecentsView.getRunningTaskIndex()) {
|
||||
// We are about to launch the current running task, so use LAST_TASK state
|
||||
// instead of NEW_TASK. This could happen, for example, if our scroll is
|
||||
// aborted after we determined the target to be NEW_TASK.
|
||||
mGestureState.setEndTarget(LAST_TASK);
|
||||
if (mRecentsView != null) {
|
||||
int taskToLaunch = mRecentsView.getNextPage();
|
||||
int runningTask = getLastAppearedTaskIndex();
|
||||
boolean hasStartedNewTask = hasStartedNewTask();
|
||||
if (target == NEW_TASK && taskToLaunch == runningTask
|
||||
&& !hasStartedNewTask) {
|
||||
// We are about to launch the current running task, so use LAST_TASK
|
||||
// state instead of NEW_TASK. This could happen, for example, if our
|
||||
// scroll is aborted after we determined the target to be NEW_TASK.
|
||||
mGestureState.setEndTarget(LAST_TASK);
|
||||
} else if (target == LAST_TASK && hasStartedNewTask) {
|
||||
// We are about to re-launch the previously running task, but we can't
|
||||
// just finish the controller like we normally would because that would
|
||||
// instead resume the last task that appeared, and not ensure that this
|
||||
// task is restored to the top. To address this, re-launch the task as
|
||||
// if it were a new task.
|
||||
mGestureState.setEndTarget(NEW_TASK);
|
||||
}
|
||||
}
|
||||
mGestureState.setState(STATE_END_TARGET_ANIMATION_FINISHED);
|
||||
}
|
||||
|
@ -1160,8 +1154,9 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
|||
|
||||
@UiThread
|
||||
private void startNewTaskInternal() {
|
||||
startNewTask(STATE_HANDLER_INVALIDATED, success -> {
|
||||
startNewTask(success -> {
|
||||
if (!success) {
|
||||
reset();
|
||||
// We couldn't launch the task, so take user to overview so they can
|
||||
// decide what to do instead of staying in this broken state.
|
||||
endLauncherTransitionController();
|
||||
|
@ -1171,6 +1166,12 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestartLastAppearedTask() {
|
||||
super.onRestartLastAppearedTask();
|
||||
reset();
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
mStateCallback.setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
}
|
||||
|
@ -1186,19 +1187,6 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
|||
.getAnimationPlayer().isStarted()) {
|
||||
mLauncherTransitionController.getAnimationPlayer().cancel();
|
||||
}
|
||||
|
||||
if (mFinishingRecentsAnimationForNewTaskId != -1) {
|
||||
// If we are canceling mid-starting a new task, switch to the screenshot since the
|
||||
// recents animation has finished
|
||||
switchToScreenshot();
|
||||
TaskView newRunningTaskView = mRecentsView.getTaskView(
|
||||
mFinishingRecentsAnimationForNewTaskId);
|
||||
int newRunningTaskId = newRunningTaskView != null
|
||||
? newRunningTaskView.getTask().key.id
|
||||
: -1;
|
||||
mRecentsView.setCurrentTask(newRunningTaskId);
|
||||
mGestureState.setFinishingRecentsAnimationTaskId(newRunningTaskId);
|
||||
}
|
||||
}
|
||||
|
||||
private void invalidateHandler() {
|
||||
|
@ -1337,8 +1325,7 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
|||
}
|
||||
|
||||
private void setTargetAlphaProvider(TargetAlphaProvider provider) {
|
||||
mAppWindowAnimationHelper.setTaskAlphaCallback(provider);
|
||||
mTaskViewSimulator.setTaskAlphaCallback(provider);
|
||||
mTransformParams.setTaskAlphaCallback(provider);
|
||||
updateFinalShift();
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
|
||||
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
|
||||
|
||||
import static com.android.launcher3.QuickstepAppTransitionManagerImpl.RECENTS_LAUNCH_DURATION;
|
||||
import static com.android.launcher3.QuickstepAppTransitionManagerImpl.STATUS_BAR_TRANSITION_DURATION;
|
||||
import static com.android.launcher3.QuickstepAppTransitionManagerImpl.STATUS_BAR_TRANSITION_PRE_DELAY;
|
||||
|
@ -29,21 +32,32 @@ import android.animation.AnimatorSet;
|
|||
import android.app.ActivityOptions;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.LauncherAnimationRunner;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
||||
import com.android.launcher3.statemanager.StateManager;
|
||||
import com.android.launcher3.statemanager.StateManager.StateHandler;
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
import com.android.launcher3.util.ActivityTracker;
|
||||
import com.android.launcher3.util.ObjectWrapper;
|
||||
import com.android.launcher3.util.SystemUiController;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
import com.android.quickstep.fallback.FallbackRecentsStateController;
|
||||
import com.android.quickstep.fallback.FallbackRecentsView;
|
||||
import com.android.quickstep.fallback.RecentsRootView;
|
||||
import com.android.quickstep.fallback.RecentsState;
|
||||
import com.android.quickstep.views.OverviewActionsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.ActivityOptionsCompat;
|
||||
|
@ -51,26 +65,40 @@ import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
|
|||
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* A recents activity that shows the recently launched tasks as swipable task cards.
|
||||
* See {@link com.android.quickstep.views.RecentsView}.
|
||||
*/
|
||||
public final class RecentsActivity extends BaseRecentsActivity {
|
||||
public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
||||
|
||||
public static final String EXTRA_THUMBNAIL = "thumbnailData";
|
||||
public static final String EXTRA_TASK_ID = "taskID";
|
||||
public static final ActivityTracker<RecentsActivity> ACTIVITY_TRACKER =
|
||||
new ActivityTracker<>();
|
||||
|
||||
private Handler mUiHandler = new Handler(Looper.getMainLooper());
|
||||
private RecentsRootView mRecentsRootView;
|
||||
private FallbackRecentsView mFallbackRecentsView;
|
||||
private OverviewActionsView mActionsView;
|
||||
|
||||
@Override
|
||||
private Configuration mOldConfig;
|
||||
|
||||
private StateManager<RecentsState> mStateManager;
|
||||
|
||||
/**
|
||||
* Init drag layer and overview panel views.
|
||||
*/
|
||||
protected void initViews() {
|
||||
setContentView(R.layout.fallback_recents_activity);
|
||||
mRecentsRootView = findViewById(R.id.drag_layer);
|
||||
mFallbackRecentsView = findViewById(R.id.overview_panel);
|
||||
mActionsView = findViewById(R.id.overview_actions_view);
|
||||
|
||||
mRecentsRootView.recreateControllers();
|
||||
mFallbackRecentsView.init(findViewById(R.id.overview_actions_view));
|
||||
mFallbackRecentsView.init(mActionsView);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -103,25 +131,38 @@ public final class RecentsActivity extends BaseRecentsActivity {
|
|||
intent.removeExtra(EXTRA_TASK_ID);
|
||||
intent.removeExtra(EXTRA_THUMBNAIL);
|
||||
super.onNewIntent(intent);
|
||||
ACTIVITY_TRACKER.handleNewIntent(this, intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
/**
|
||||
* Logic for when device configuration changes (rotation, screen size change, multi-window,
|
||||
* etc.)
|
||||
*/
|
||||
protected void onHandleConfigChanged() {
|
||||
super.onHandleConfigChanged();
|
||||
mUserEventDispatcher = null;
|
||||
initDeviceProfile();
|
||||
|
||||
AbstractFloatingView.closeOpenViews(this, true,
|
||||
AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
|
||||
dispatchDeviceProfileChanged();
|
||||
|
||||
reapplyUi();
|
||||
mRecentsRootView.recreateControllers();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reapplyUi() {
|
||||
mRecentsRootView.dispatchInsets();
|
||||
}
|
||||
|
||||
@Override
|
||||
/**
|
||||
* Generate the device profile to use in this activity.
|
||||
* @return device profile
|
||||
*/
|
||||
protected DeviceProfile createDeviceProfile() {
|
||||
DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(this).getDeviceProfile(this);
|
||||
DeviceProfile dp1 = InvariantDeviceProfile.INSTANCE.get(this).getDeviceProfile(this);
|
||||
|
||||
// In case we are reusing IDP, create a copy so that we don't conflict with Launcher
|
||||
// activity.
|
||||
return (mRecentsRootView != null) && isInMultiWindowMode()
|
||||
? dp.getMultiWindowProfile(this, getMultiWindowDisplaySize())
|
||||
: super.createDeviceProfile();
|
||||
: dp1.copy(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -139,6 +180,10 @@ public final class RecentsActivity extends BaseRecentsActivity {
|
|||
return (T) mFallbackRecentsView;
|
||||
}
|
||||
|
||||
public OverviewActionsView getActionsView() {
|
||||
return mActionsView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void returnToHomescreen() {
|
||||
super.returnToHomescreen();
|
||||
|
@ -160,12 +205,7 @@ public final class RecentsActivity extends BaseRecentsActivity {
|
|||
RemoteAnimationTargetCompat[] wallpaperTargets, AnimationResult result) {
|
||||
AnimatorSet anim = composeRecentsLaunchAnimator(taskView, appTargets,
|
||||
wallpaperTargets);
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mFallbackRecentsView.resetViewUI();
|
||||
}
|
||||
});
|
||||
anim.addListener(resetStateListener());
|
||||
result.setAnimation(anim, RecentsActivity.this);
|
||||
}
|
||||
};
|
||||
|
@ -193,12 +233,7 @@ public final class RecentsActivity extends BaseRecentsActivity {
|
|||
.createAdjacentPageAnimForTaskLaunch(taskView);
|
||||
adjacentAnimation.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR);
|
||||
adjacentAnimation.setDuration(RECENTS_LAUNCH_DURATION);
|
||||
adjacentAnimation.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mFallbackRecentsView.resetTaskVisuals();
|
||||
}
|
||||
});
|
||||
adjacentAnimation.addListener(resetStateListener());
|
||||
target.play(adjacentAnimation);
|
||||
}
|
||||
return target;
|
||||
|
@ -210,13 +245,14 @@ public final class RecentsActivity extends BaseRecentsActivity {
|
|||
// onActivityStart callback.
|
||||
mFallbackRecentsView.setContentAlpha(1);
|
||||
super.onStart();
|
||||
mFallbackRecentsView.resetTaskVisuals();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mFallbackRecentsView.reset();
|
||||
|
||||
// Workaround for b/78520668, explicitly trim memory once UI is hidden
|
||||
onTrimMemory(TRIM_MEMORY_UI_HIDDEN);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -228,4 +264,98 @@ public final class RecentsActivity extends BaseRecentsActivity {
|
|||
public void onTaskLaunched() {
|
||||
mFallbackRecentsView.resetTaskVisuals();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mStateManager = new StateManager<>(this, RecentsState.DEFAULT);
|
||||
|
||||
mOldConfig = new Configuration(getResources().getConfiguration());
|
||||
initDeviceProfile();
|
||||
initViews();
|
||||
|
||||
getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW,
|
||||
Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText));
|
||||
ACTIVITY_TRACKER.handleCreate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
int diff = newConfig.diff(mOldConfig);
|
||||
if ((diff & (CONFIG_ORIENTATION | CONFIG_SCREEN_SIZE)) != 0) {
|
||||
onHandleConfigChanged();
|
||||
}
|
||||
mOldConfig.setTo(newConfig);
|
||||
super.onConfigurationChanged(newConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize/update the device profile.
|
||||
*/
|
||||
private void initDeviceProfile() {
|
||||
mDeviceProfile = createDeviceProfile();
|
||||
onDeviceProfileInitiated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnterAnimationComplete() {
|
||||
super.onEnterAnimationComplete();
|
||||
// After the transition to home, enable the high-res thumbnail loader if it wasn't enabled
|
||||
// as a part of quickstep, so that high-res thumbnails can load the next time we enter
|
||||
// overview
|
||||
RecentsModel.INSTANCE.get(this).getThumbnailCache()
|
||||
.getHighResLoadingState().setVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrimMemory(int level) {
|
||||
super.onTrimMemory(level);
|
||||
RecentsModel.INSTANCE.get(this).onTrimMemory(level);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
ACTIVITY_TRACKER.onActivityDestroyed(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
// TODO: Launch the task we came from
|
||||
startHome();
|
||||
}
|
||||
|
||||
public void startHome() {
|
||||
startActivity(new Intent(Intent.ACTION_MAIN)
|
||||
.addCategory(Intent.CATEGORY_HOME)
|
||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StateHandler<RecentsState>[] createStateHandlers() {
|
||||
return new StateHandler[] { new FallbackRecentsStateController(this) };
|
||||
}
|
||||
|
||||
@Override
|
||||
public StateManager<RecentsState> getStateManager() {
|
||||
return mStateManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
|
||||
super.dump(prefix, fd, writer, args);
|
||||
writer.println(prefix + "Misc:");
|
||||
dumpMisc(prefix + "\t", writer);
|
||||
}
|
||||
|
||||
private AnimatorListenerAdapter resetStateListener() {
|
||||
return new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mFallbackRecentsView.resetTaskVisuals();
|
||||
mStateManager.reapplyState();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import android.content.Context;
|
|||
import android.graphics.Insets;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Rect;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.launcher3.BaseActivity;
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
|
@ -109,16 +110,26 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
|
|||
public void initOverlay(Task task, ThumbnailData thumbnail, Matrix matrix) {
|
||||
ImageActionsApi imageApi = new ImageActionsApi(
|
||||
mApplicationContext, mThumbnailView::getThumbnail);
|
||||
final boolean isAllowedByPolicy = thumbnail.isRealSnapshot;
|
||||
|
||||
getActionsView().setCallbacks(new OverlayUICallbacks() {
|
||||
@Override
|
||||
public void onShare() {
|
||||
imageApi.startShareActivity();
|
||||
if (isAllowedByPolicy) {
|
||||
imageApi.startShareActivity();
|
||||
} else {
|
||||
showBlockedByPolicyMessage();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScreenshot() {
|
||||
imageApi.saveScreenshot(mThumbnailView.getThumbnail(),
|
||||
getTaskSnapshotBounds(), getTaskSnapshotInsets(), task.key.id);
|
||||
if (isAllowedByPolicy) {
|
||||
imageApi.saveScreenshot(mThumbnailView.getThumbnail(),
|
||||
getTaskSnapshotBounds(), getTaskSnapshotInsets(), task.key.id);
|
||||
} else {
|
||||
showBlockedByPolicyMessage();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -152,6 +163,13 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
|
|||
// TODO: return the real insets
|
||||
return Insets.of(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
private void showBlockedByPolicyMessage() {
|
||||
Toast.makeText(
|
||||
mThumbnailView.getContext(),
|
||||
R.string.blocked_by_policy,
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -38,6 +38,7 @@ import com.android.launcher3.model.data.ItemInfo;
|
|||
import com.android.launcher3.statehandlers.DepthController;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper;
|
||||
import com.android.quickstep.util.MultiValueUpdateListener;
|
||||
import com.android.quickstep.util.TransformParams;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
|
@ -132,11 +133,10 @@ public final class TaskViewUtils {
|
|||
final RemoteAnimationTargets targets =
|
||||
new RemoteAnimationTargets(appTargets, wallpaperTargets, MODE_OPENING);
|
||||
targets.addDependentTransactionApplier(applier);
|
||||
AppWindowAnimationHelper.TransformParams params =
|
||||
new AppWindowAnimationHelper.TransformParams()
|
||||
TransformParams params =
|
||||
new TransformParams()
|
||||
.setSyncTransactionApplier(applier)
|
||||
.setTargetSet(targets)
|
||||
.setLauncherOnTop(true);
|
||||
.setTargetSet(targets);
|
||||
|
||||
AnimatorSet animatorSet = new AnimatorSet();
|
||||
final RecentsView recentsView = v.getRecentsView();
|
||||
|
@ -150,7 +150,7 @@ public final class TaskViewUtils {
|
|||
final RectF mThumbnailRect;
|
||||
|
||||
{
|
||||
inOutHelper.setTaskAlphaCallback((t, alpha) -> mTaskAlpha.value);
|
||||
params.setTaskAlphaCallback((t, alpha) -> mTaskAlpha.value);
|
||||
inOutHelper.prepareAnimation(
|
||||
BaseActivity.fromContext(v.getContext()).getDeviceProfile());
|
||||
inOutHelper.fromTaskThumbnailView(v.getThumbnail(), (RecentsView) v.getParent(),
|
||||
|
@ -175,7 +175,7 @@ public final class TaskViewUtils {
|
|||
v.getRecentsView().getClipAnimationHelper();
|
||||
if (liveTileAnimationHelper != null) {
|
||||
// Append the surface transform params for the live tile app.
|
||||
AppWindowAnimationHelper.TransformParams liveTileParams =
|
||||
TransformParams liveTileParams =
|
||||
v.getRecentsView().getLiveTileParams(true /* mightNeedToRefill */);
|
||||
if (liveTileParams != null) {
|
||||
SurfaceParams[] liveTileSurfaceParams =
|
||||
|
@ -186,7 +186,7 @@ public final class TaskViewUtils {
|
|||
}
|
||||
}
|
||||
// Apply surface transform using the surface params list.
|
||||
AppWindowAnimationHelper.applySurfaceParams(params.getSyncTransactionApplier(),
|
||||
params.applySurfaceParams(
|
||||
surfaceParamsList.toArray(new SurfaceParams[surfaceParamsList.size()]));
|
||||
// Get the task bounds for the app that's being opened after surface transform
|
||||
// update.
|
||||
|
|
|
@ -30,8 +30,6 @@ import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYS
|
|||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.RemoteAction;
|
||||
import android.app.Service;
|
||||
|
@ -40,6 +38,7 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Build;
|
||||
|
@ -71,6 +70,7 @@ import com.android.launcher3.tracing.nano.TouchInteractionServiceProto;
|
|||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
|
||||
import com.android.launcher3.util.OnboardingPrefs;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.launcher3.util.WindowBounds;
|
||||
import com.android.quickstep.inputconsumers.AccessibilityInputConsumer;
|
||||
import com.android.quickstep.inputconsumers.AssistantInputConsumer;
|
||||
import com.android.quickstep.inputconsumers.DeviceLockedInputConsumer;
|
||||
|
@ -83,6 +83,7 @@ import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer;
|
|||
import com.android.quickstep.util.ActiveGestureLog;
|
||||
import com.android.quickstep.util.AssistantUtilities;
|
||||
import com.android.quickstep.util.ProtoTracer;
|
||||
import com.android.quickstep.util.SplitScreenBounds;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.systemui.plugins.OverscrollPlugin;
|
||||
import com.android.systemui.plugins.PluginListener;
|
||||
|
@ -120,7 +121,7 @@ class ArgList extends LinkedList<String> {
|
|||
/**
|
||||
* Service connected by system-UI for handling touch interaction.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.Q)
|
||||
@TargetApi(Build.VERSION_CODES.R)
|
||||
public class TouchInteractionService extends Service implements PluginListener<OverscrollPlugin>,
|
||||
ProtoTraceable<LauncherTraceProto> {
|
||||
|
||||
|
@ -231,6 +232,11 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
|||
MAIN_EXECUTOR.execute(() -> mDeviceState.setDeferredGestureRegion(region));
|
||||
}
|
||||
|
||||
public void onSplitScreenSecondaryBoundsChanged(Rect bounds, Rect insets) {
|
||||
WindowBounds wb = new WindowBounds(bounds, insets);
|
||||
MAIN_EXECUTOR.execute(() -> SplitScreenBounds.INSTANCE.setSecondaryWindowBounds(wb));
|
||||
}
|
||||
|
||||
/** Deprecated methods **/
|
||||
public void onQuickStep(MotionEvent motionEvent) { }
|
||||
|
||||
|
@ -518,8 +524,13 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
|||
private GestureState createGestureState() {
|
||||
GestureState gestureState = new GestureState(mOverviewComponentObserver,
|
||||
ActiveGestureLog.INSTANCE.generateAndSetLogId());
|
||||
gestureState.updateRunningTask(TraceHelper.whitelistIpcs("getRunningTask.0",
|
||||
() -> mAM.getRunningTask(false /* filterOnlyVisibleRecents */)));
|
||||
if (mTaskAnimationManager.isRecentsAnimationRunning()) {
|
||||
gestureState.updateRunningTask(mGestureState.getRunningTask());
|
||||
gestureState.updateLastStartedTaskId(mGestureState.getLastStartedTaskId());
|
||||
} else {
|
||||
gestureState.updateRunningTask(TraceHelper.whitelistIpcs("getRunningTask.0",
|
||||
() -> mAM.getRunningTask(false /* filterOnlyVisibleRecents */)));
|
||||
}
|
||||
return gestureState;
|
||||
}
|
||||
|
||||
|
@ -599,15 +610,24 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
|||
}
|
||||
|
||||
private void handleOrientationSetup(InputConsumer baseInputConsumer) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "handleOrientationSetup.1");
|
||||
}
|
||||
if (!isFixedRotationTransformEnabled(this)) {
|
||||
return;
|
||||
}
|
||||
mDeviceState.enableMultipleRegions(baseInputConsumer instanceof OtherActivityInputConsumer);
|
||||
BaseDraggingActivity activity =
|
||||
mOverviewComponentObserver.getActivityInterface().getCreatedActivity();
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "handleOrientationSetup.2");
|
||||
}
|
||||
if (activity == null || !(activity.getOverviewPanel() instanceof RecentsView)) {
|
||||
return;
|
||||
}
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "handleOrientationSetup.3");
|
||||
}
|
||||
((RecentsView) activity.getOverviewPanel())
|
||||
.setLayoutRotation(mDeviceState.getCurrentActiveRotation(),
|
||||
mDeviceState.getDisplayRotation());
|
||||
|
@ -637,14 +657,7 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
|||
runningComponent != null && runningComponent.equals(homeComponent);
|
||||
}
|
||||
|
||||
if (previousGestureState.getFinishingRecentsAnimationTaskId() > 0) {
|
||||
// If the finish animation was interrupted, then continue using the other activity input
|
||||
// consumer but with the next task as the running task
|
||||
RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
|
||||
info.id = previousGestureState.getFinishingRecentsAnimationTaskId();
|
||||
gestureState.updateRunningTask(info);
|
||||
return createOtherActivityInputConsumer(previousGestureState, gestureState, event);
|
||||
} else if (gestureState.getRunningTask() == null) {
|
||||
if (gestureState.getRunningTask() == null) {
|
||||
return mResetGestureInputConsumer;
|
||||
} else if (previousGestureState.isRunningAnimationToLauncher()
|
||||
|| gestureState.getActivityInterface().isResumed()
|
||||
|
@ -658,25 +671,22 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
|||
} else if (mDeviceState.isGestureBlockedActivity(gestureState.getRunningTask())) {
|
||||
return mResetGestureInputConsumer;
|
||||
} else {
|
||||
return createOtherActivityInputConsumer(previousGestureState, gestureState, event);
|
||||
return createOtherActivityInputConsumer(gestureState, event);
|
||||
}
|
||||
}
|
||||
|
||||
private InputConsumer createOtherActivityInputConsumer(GestureState previousGestureState,
|
||||
GestureState gestureState, MotionEvent event) {
|
||||
private InputConsumer createOtherActivityInputConsumer(GestureState gestureState,
|
||||
MotionEvent event) {
|
||||
|
||||
final boolean shouldDefer;
|
||||
final BaseSwipeUpHandler.Factory factory;
|
||||
|
||||
if (!mOverviewComponentObserver.isHomeAndOverviewSame()) {
|
||||
shouldDefer = previousGestureState.getFinishingRecentsAnimationTaskId() < 0;
|
||||
factory = mFallbackSwipeHandlerFactory;
|
||||
} else {
|
||||
shouldDefer = gestureState.getActivityInterface().deferStartingActivity(mDeviceState,
|
||||
event);
|
||||
factory = mLauncherSwipeHandlerFactory;
|
||||
}
|
||||
|
||||
final boolean shouldDefer = !mOverviewComponentObserver.isHomeAndOverviewSame()
|
||||
|| gestureState.getActivityInterface().deferStartingActivity(mDeviceState, event);
|
||||
final boolean disableHorizontalSwipe = mDeviceState.isInExclusionRegion(event);
|
||||
return new OtherActivityInputConsumer(this, mDeviceState, mTaskAnimationManager,
|
||||
gestureState, shouldDefer, this::onConsumerInactive,
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.quickstep.fallback;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_SCALE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
|
||||
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
|
||||
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
|
||||
import static com.android.quickstep.views.RecentsView.TASK_MODALNESS;
|
||||
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.anim.PropertySetter;
|
||||
import com.android.launcher3.statemanager.StateManager.StateHandler;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.util.MultiValueAlpha;
|
||||
import com.android.quickstep.RecentsActivity;
|
||||
import com.android.quickstep.views.ClearAllButton;
|
||||
|
||||
/**
|
||||
* State controller for fallback recents activity
|
||||
*/
|
||||
public class FallbackRecentsStateController implements StateHandler<RecentsState> {
|
||||
|
||||
private final StateAnimationConfig mNoConfig = new StateAnimationConfig();
|
||||
private final RecentsActivity mActivity;
|
||||
private final FallbackRecentsView mRecentsView;
|
||||
|
||||
public FallbackRecentsStateController(RecentsActivity activity) {
|
||||
mActivity = activity;
|
||||
mRecentsView = activity.getOverviewPanel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setState(RecentsState state) {
|
||||
mRecentsView.updateEmptyMessage();
|
||||
mRecentsView.resetTaskVisuals();
|
||||
setProperties(state, mNoConfig, PropertySetter.NO_ANIM_PROPERTY_SETTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStateWithAnimation(RecentsState toState, StateAnimationConfig config,
|
||||
PendingAnimation setter) {
|
||||
if (!config.hasAnimationFlag(PLAY_ATOMIC_OVERVIEW_PEEK | PLAY_ATOMIC_OVERVIEW_SCALE)) {
|
||||
// The entire recents animation is played atomically.
|
||||
return;
|
||||
}
|
||||
if (config.hasAnimationFlag(SKIP_OVERVIEW)) {
|
||||
return;
|
||||
}
|
||||
// While animating into recents, update the visible task data as needed
|
||||
setter.addOnFrameCallback(mRecentsView::loadVisibleTaskData);
|
||||
mRecentsView.updateEmptyMessage();
|
||||
|
||||
setProperties(toState, config, setter);
|
||||
}
|
||||
|
||||
private void setProperties(RecentsState state, StateAnimationConfig config,
|
||||
PropertySetter setter) {
|
||||
float buttonAlpha = state.hasButtons() ? 1 : 0;
|
||||
setter.setFloat(mRecentsView.getClearAllButton(), ClearAllButton.VISIBILITY_ALPHA,
|
||||
buttonAlpha, LINEAR);
|
||||
setter.setFloat(mActivity.getActionsView().getVisibilityAlpha(),
|
||||
MultiValueAlpha.VALUE, buttonAlpha, LINEAR);
|
||||
|
||||
float[] scaleAndOffset = state.getOverviewScaleAndOffset(mActivity);
|
||||
setter.setFloat(mRecentsView, SCALE_PROPERTY, scaleAndOffset[0],
|
||||
config.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR));
|
||||
setter.setFloat(mRecentsView, ADJACENT_PAGE_OFFSET, scaleAndOffset[1],
|
||||
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_X, LINEAR));
|
||||
|
||||
setter.setFloat(mRecentsView, TASK_MODALNESS, state.getOverviewModalness(),
|
||||
config.getInterpolator(ANIM_OVERVIEW_MODAL, LINEAR));
|
||||
setter.setFloat(mRecentsView, FULLSCREEN_PROGRESS, state.isFullScreen() ? 1 : 0, LINEAR);
|
||||
}
|
||||
}
|
|
@ -15,17 +15,17 @@
|
|||
*/
|
||||
package com.android.quickstep.fallback;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
import static com.android.quickstep.fallback.RecentsState.DEFAULT;
|
||||
import static com.android.quickstep.fallback.RecentsState.MODAL_TASK;
|
||||
import static com.android.quickstep.util.WindowSizeStrategy.FALLBACK_RECENTS_SIZE_STRATEGY;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.FloatProperty;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.statemanager.StateManager.StateListener;
|
||||
import com.android.quickstep.RecentsActivity;
|
||||
import com.android.quickstep.views.OverviewActionsView;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
@ -34,26 +34,9 @@ import com.android.systemui.shared.recents.model.Task.TaskKey;
|
|||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class FallbackRecentsView extends RecentsView<RecentsActivity> {
|
||||
|
||||
public static final FloatProperty<FallbackRecentsView> ZOOM_PROGRESS =
|
||||
new FloatProperty<FallbackRecentsView> ("zoomInProgress") {
|
||||
|
||||
@Override
|
||||
public void setValue(FallbackRecentsView view, float value) {
|
||||
view.setZoomProgress(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float get(FallbackRecentsView view) {
|
||||
return view.mZoomInProgress;
|
||||
}
|
||||
};
|
||||
|
||||
private float mZoomInProgress = 0;
|
||||
private boolean mInOverviewState = true;
|
||||
|
||||
private float mZoomScale = 1f;
|
||||
@TargetApi(Build.VERSION_CODES.R)
|
||||
public class FallbackRecentsView extends RecentsView<RecentsActivity>
|
||||
implements StateListener<RecentsState> {
|
||||
|
||||
private RunningTaskInfo mRunningTaskInfo;
|
||||
|
||||
|
@ -63,6 +46,7 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> {
|
|||
|
||||
public FallbackRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr, FALLBACK_RECENTS_SIZE_STRATEGY);
|
||||
mActivity.getStateManager().addStateListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -77,71 +61,12 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> {
|
|||
mActivity.startHome();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewAdded(View child) {
|
||||
super.onViewAdded(child);
|
||||
updateEmptyMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewRemoved(View child) {
|
||||
super.onViewRemoved(child);
|
||||
updateEmptyMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
maybeDrawEmptyMessage(canvas);
|
||||
super.draw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
resetViewUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldUseMultiWindowTaskSizeStrategy() {
|
||||
// Just use the activity task size for multi-window as well.
|
||||
return false;
|
||||
}
|
||||
|
||||
public void resetViewUI() {
|
||||
setZoomProgress(0);
|
||||
resetTaskVisuals();
|
||||
}
|
||||
|
||||
public void setInOverviewState(boolean inOverviewState) {
|
||||
if (mInOverviewState != inOverviewState) {
|
||||
mInOverviewState = inOverviewState;
|
||||
if (mInOverviewState) {
|
||||
resetTaskVisuals();
|
||||
} else {
|
||||
setZoomProgress(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetTaskVisuals() {
|
||||
super.resetTaskVisuals();
|
||||
setFullscreenProgress(mFullscreenProgress);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
mZoomScale = getMaxScaleForFullScreen();
|
||||
setZoomProgress(mZoomInProgress);
|
||||
}
|
||||
|
||||
public void setZoomProgress(float progress) {
|
||||
mZoomInProgress = progress;
|
||||
SCALE_PROPERTY.set(this, Utilities.mapRange(mZoomInProgress, 1, mZoomScale));
|
||||
FULLSCREEN_PROGRESS.set(this, mZoomInProgress);
|
||||
}
|
||||
|
||||
public void onGestureAnimationStart(RunningTaskInfo runningTaskInfo) {
|
||||
mRunningTaskInfo = runningTaskInfo;
|
||||
onGestureAnimationStart(runningTaskInfo == null ? -1 : runningTaskInfo.taskId);
|
||||
|
@ -178,4 +103,37 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> {
|
|||
}
|
||||
super.applyLoadPlan(tasks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModalStateEnabled(boolean isModalState) {
|
||||
super.setModalStateEnabled(isModalState);
|
||||
if (isModalState) {
|
||||
mActivity.getStateManager().goToState(RecentsState.MODAL_TASK);
|
||||
} else {
|
||||
if (mActivity.isInState(RecentsState.MODAL_TASK)) {
|
||||
mActivity.getStateManager().goToState(DEFAULT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateTransitionStart(RecentsState toState) {
|
||||
setOverviewStateEnabled(true);
|
||||
setFreezeViewVisibility(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateTransitionComplete(RecentsState finalState) {
|
||||
setOverlayEnabled(finalState == DEFAULT || finalState == MODAL_TASK);
|
||||
setFreezeViewVisibility(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOverviewStateEnabled(boolean enabled) {
|
||||
super.setOverviewStateEnabled(enabled);
|
||||
if (enabled) {
|
||||
RecentsState state = mActivity.getStateManager().getState();
|
||||
setDisallowScrollToClearAll(!state.hasButtons());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.quickstep.fallback;
|
||||
|
||||
import static com.android.launcher3.uioverrides.states.BackgroundAppState.getOverviewScaleAndOffsetForBackgroundState;
|
||||
import static com.android.launcher3.uioverrides.states.OverviewModalTaskState.getOverviewScaleAndOffsetForModalState;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.launcher3.statemanager.BaseState;
|
||||
import com.android.quickstep.RecentsActivity;
|
||||
|
||||
/**
|
||||
* State definition for Fallback recents
|
||||
*/
|
||||
public class RecentsState implements BaseState<RecentsState> {
|
||||
|
||||
private static final int FLAG_MODAL = BaseState.getFlag(0);
|
||||
private static final int FLAG_HAS_BUTTONS = BaseState.getFlag(1);
|
||||
private static final int FLAG_FULL_SCREEN = BaseState.getFlag(2);
|
||||
|
||||
public static final RecentsState DEFAULT = new RecentsState(0, FLAG_HAS_BUTTONS);
|
||||
public static final RecentsState MODAL_TASK = new ModalState(1,
|
||||
FLAG_DISABLE_RESTORE | FLAG_HAS_BUTTONS | FLAG_MODAL);
|
||||
public static final RecentsState BACKGROUND_APP = new BackgroundAppState(2,
|
||||
FLAG_DISABLE_RESTORE | FLAG_NON_INTERACTIVE | FLAG_FULL_SCREEN);
|
||||
|
||||
public final int ordinal;
|
||||
private final int mFlags;
|
||||
|
||||
private static final float NO_OFFSET = 0;
|
||||
private static final float NO_SCALE = 1;
|
||||
|
||||
public RecentsState(int id, int flags) {
|
||||
this.ordinal = id;
|
||||
this.mFlags = flags;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Ordinal-" + ordinal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean hasFlag(int mask) {
|
||||
return (mFlags & mask) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTransitionDuration(Context context) {
|
||||
return 250;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecentsState getHistoryForState(RecentsState previousState) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* For this state, how modal should over view been shown. 0 modalness means all tasks drawn,
|
||||
* 1 modalness means the current task is show on its own.
|
||||
*/
|
||||
public float getOverviewModalness() {
|
||||
return hasFlag(FLAG_MODAL) ? 1 : 0;
|
||||
}
|
||||
|
||||
public boolean isFullScreen() {
|
||||
return hasFlag(FLAG_FULL_SCREEN);
|
||||
}
|
||||
|
||||
public boolean hasButtons() {
|
||||
return hasFlag(FLAG_HAS_BUTTONS);
|
||||
}
|
||||
|
||||
public float[] getOverviewScaleAndOffset(RecentsActivity activity) {
|
||||
return new float[] { NO_SCALE, NO_OFFSET };
|
||||
}
|
||||
|
||||
|
||||
private static class ModalState extends RecentsState {
|
||||
|
||||
public ModalState(int id, int flags) {
|
||||
super(id, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] getOverviewScaleAndOffset(RecentsActivity activity) {
|
||||
return getOverviewScaleAndOffsetForModalState(activity);
|
||||
}
|
||||
}
|
||||
|
||||
private static class BackgroundAppState extends RecentsState {
|
||||
public BackgroundAppState(int id, int flags) {
|
||||
super(id, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] getOverviewScaleAndOffset(RecentsActivity activity) {
|
||||
return getOverviewScaleAndOffsetForBackgroundState(activity);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,8 +21,8 @@ import static android.view.MotionEvent.ACTION_UP;
|
|||
|
||||
import static com.android.launcher3.Utilities.squaredHypot;
|
||||
import static com.android.launcher3.Utilities.squaredTouchSlop;
|
||||
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
|
||||
import static com.android.quickstep.LauncherSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
|
||||
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
|
||||
import static com.android.quickstep.util.ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID;
|
||||
|
||||
import android.content.ComponentName;
|
||||
|
@ -44,12 +44,13 @@ import com.android.quickstep.GestureState;
|
|||
import com.android.quickstep.InputConsumer;
|
||||
import com.android.quickstep.LockScreenRecentsActivity;
|
||||
import com.android.quickstep.MultiStateCallback;
|
||||
import com.android.quickstep.RecentsAnimationCallbacks;
|
||||
import com.android.quickstep.RecentsAnimationController;
|
||||
import com.android.quickstep.RecentsAnimationDeviceState;
|
||||
import com.android.quickstep.RecentsAnimationCallbacks;
|
||||
import com.android.quickstep.RecentsAnimationTargets;
|
||||
import com.android.quickstep.TaskAnimationManager;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper;
|
||||
import com.android.quickstep.util.TransformParams;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.InputMonitorCompat;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
|
@ -84,7 +85,7 @@ public class DeviceLockedInputConsumer implements InputConsumer,
|
|||
|
||||
private final PointF mTouchDown = new PointF();
|
||||
private final AppWindowAnimationHelper mAppWindowAnimationHelper;
|
||||
private final AppWindowAnimationHelper.TransformParams mTransformParams;
|
||||
private final TransformParams mTransformParams;
|
||||
private final Point mDisplaySize;
|
||||
private final MultiStateCallback mStateCallback;
|
||||
|
||||
|
@ -105,7 +106,7 @@ public class DeviceLockedInputConsumer implements InputConsumer,
|
|||
mGestureState = gestureState;
|
||||
mTouchSlopSquared = squaredTouchSlop(context);
|
||||
mAppWindowAnimationHelper = new AppWindowAnimationHelper(context);
|
||||
mTransformParams = new AppWindowAnimationHelper.TransformParams();
|
||||
mTransformParams = new TransformParams();
|
||||
mInputMonitorCompat = inputMonitorCompat;
|
||||
|
||||
// Do not use DeviceProfile as the user data might be locked
|
||||
|
@ -230,8 +231,7 @@ public class DeviceLockedInputConsumer implements InputConsumer,
|
|||
|
||||
Utilities.scaleRectAboutCenter(displaySize, SCALE_DOWN);
|
||||
displaySize.offsetTo(displaySize.left, 0);
|
||||
mTransformParams.setTargetSet(mRecentsAnimationTargets)
|
||||
.setLauncherOnTop(true);
|
||||
mTransformParams.setTargetSet(mRecentsAnimationTargets);
|
||||
mAppWindowAnimationHelper.updateTargetRect(displaySize);
|
||||
mAppWindowAnimationHelper.applyTransform(mTransformParams);
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ package com.android.quickstep.inputconsumers;
|
|||
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
|
||||
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
|
@ -95,6 +96,9 @@ public class OverviewInputConsumer<T extends BaseDraggingActivity>
|
|||
ev.setEdgeFlags(flags | Utilities.EDGE_NAV_BAR);
|
||||
}
|
||||
ev.offsetLocation(-mLocationOnScreen[0], -mLocationOnScreen[1]);
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "OverviewInputConsumer");
|
||||
}
|
||||
boolean handled = mEventReceiver.test(ev);
|
||||
ev.offsetLocation(mLocationOnScreen[0], mLocationOnScreen[1]);
|
||||
ev.setEdgeFlags(flags);
|
||||
|
|
|
@ -15,11 +15,10 @@
|
|||
*/
|
||||
package com.android.quickstep.util;
|
||||
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
|
||||
import static com.android.launcher3.Utilities.boundToRange;
|
||||
import static com.android.launcher3.Utilities.mapRange;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.getWindowCornerRadius;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.supportsRoundedCornersOnWindows;
|
||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
|
||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
|
@ -36,9 +35,7 @@ import com.android.launcher3.BaseDraggingActivity;
|
|||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
import com.android.quickstep.RemoteAnimationTargets;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskThumbnailView;
|
||||
|
@ -46,14 +43,14 @@ import com.android.systemui.shared.recents.utilities.RectFEvaluator;
|
|||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
|
||||
import com.android.systemui.shared.system.TransactionCompat;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams.Builder;
|
||||
import com.android.systemui.shared.system.WindowManagerWrapper;
|
||||
|
||||
/**
|
||||
* Utility class to handle window clip animation
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.P)
|
||||
public class AppWindowAnimationHelper {
|
||||
public class AppWindowAnimationHelper implements TransformParams.BuilderProxy {
|
||||
|
||||
// The bounds of the source app in device coordinates
|
||||
private final RectF mSourceStackBounds = new RectF();
|
||||
|
@ -94,9 +91,6 @@ public class AppWindowAnimationHelper {
|
|||
// Corner radius currently applied to transformed window.
|
||||
private float mCurrentCornerRadius;
|
||||
|
||||
private TargetAlphaProvider mTaskAlphaCallback = (t, a) -> a;
|
||||
private TargetAlphaProvider mBaseAlphaCallback = (t, a) -> 1;
|
||||
|
||||
public AppWindowAnimationHelper(RecentsOrientedState orientedState, Context context) {
|
||||
Resources res = context.getResources();
|
||||
mOrientedState = orientedState;
|
||||
|
@ -167,7 +161,7 @@ public class AppWindowAnimationHelper {
|
|||
if (surfaceParams == null) {
|
||||
return null;
|
||||
}
|
||||
applySurfaceParams(params.mSyncTransactionApplier, surfaceParams);
|
||||
params.applySurfaceParams(surfaceParams);
|
||||
return mCurrentRect;
|
||||
}
|
||||
|
||||
|
@ -176,97 +170,60 @@ public class AppWindowAnimationHelper {
|
|||
* the SurfaceParams to apply via {@link SyncRtSurfaceTransactionApplierCompat#applyParams}.
|
||||
*/
|
||||
public SurfaceParams[] computeSurfaceParams(TransformParams params) {
|
||||
if (params.mTargetSet == null) {
|
||||
if (params.getTargetSet() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
float progress = Utilities.boundToRange(params.mProgress, 0, 1);
|
||||
updateCurrentRect(params);
|
||||
return params.createSurfaceParams(this);
|
||||
}
|
||||
|
||||
SurfaceParams[] surfaceParams = new SurfaceParams[params.mTargetSet.unfilteredApps.length];
|
||||
for (int i = 0; i < params.mTargetSet.unfilteredApps.length; i++) {
|
||||
RemoteAnimationTargetCompat app = params.mTargetSet.unfilteredApps[i];
|
||||
SurfaceParams.Builder builder = new SurfaceParams.Builder(app.leash);
|
||||
@Override
|
||||
public void onBuildParams(Builder builder, RemoteAnimationTargetCompat app,
|
||||
int targetMode, TransformParams params) {
|
||||
Rect crop = mTmpRect;
|
||||
crop.set(app.screenSpaceBounds);
|
||||
crop.offsetTo(0, 0);
|
||||
float cornerRadius = 0f;
|
||||
float scale = Math.max(mCurrentRect.width(), mTargetRect.width()) / crop.width();
|
||||
if (app.mode == targetMode
|
||||
&& app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
|
||||
mTmpMatrix.setRectToRect(mSourceRect, mCurrentRect, ScaleToFit.FILL);
|
||||
if (app.localBounds != null) {
|
||||
mTmpMatrix.setTranslate(0, 0);
|
||||
if (app.activityType == ACTIVITY_TYPE_HOME && app.mode == MODE_CLOSING) {
|
||||
mTmpMatrix.setTranslate(app.localBounds.left, app.localBounds.top);
|
||||
}
|
||||
mTmpMatrix.postTranslate(app.localBounds.left, app.localBounds.top);
|
||||
} else {
|
||||
mTmpMatrix.setTranslate(app.position.x, app.position.y);
|
||||
mTmpMatrix.postTranslate(app.position.x, app.position.y);
|
||||
}
|
||||
mCurrentClipRectF.roundOut(crop);
|
||||
if (mSupportsRoundedCornersOnWindows) {
|
||||
if (params.getCornerRadius() > -1) {
|
||||
cornerRadius = params.getCornerRadius();
|
||||
scale = mCurrentRect.width() / crop.width();
|
||||
} else {
|
||||
float windowCornerRadius = mUseRoundedCornersOnWindows
|
||||
? mWindowCornerRadius : 0;
|
||||
cornerRadius = mapRange(boundToRange(params.getProgress(), 0, 1),
|
||||
windowCornerRadius, mTaskCornerRadius);
|
||||
}
|
||||
mCurrentCornerRadius = cornerRadius;
|
||||
}
|
||||
|
||||
Rect crop = mTmpRect;
|
||||
crop.set(app.screenSpaceBounds);
|
||||
crop.offsetTo(0, 0);
|
||||
float alpha;
|
||||
float cornerRadius = 0f;
|
||||
float scale = Math.max(mCurrentRect.width(), mTargetRect.width()) / crop.width();
|
||||
if (app.mode == params.mTargetSet.targetMode) {
|
||||
alpha = mTaskAlphaCallback.getAlpha(app, params.mTargetAlpha);
|
||||
if (app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
|
||||
mTmpMatrix.setRectToRect(mSourceRect, mCurrentRect, ScaleToFit.FILL);
|
||||
if (app.localBounds != null) {
|
||||
mTmpMatrix.postTranslate(app.localBounds.left, app.localBounds.top);
|
||||
} else {
|
||||
mTmpMatrix.postTranslate(app.position.x, app.position.y);
|
||||
}
|
||||
mCurrentClipRectF.roundOut(crop);
|
||||
if (mSupportsRoundedCornersOnWindows) {
|
||||
if (params.mCornerRadius > -1) {
|
||||
cornerRadius = params.mCornerRadius;
|
||||
scale = mCurrentRect.width() / crop.width();
|
||||
} else {
|
||||
float windowCornerRadius = mUseRoundedCornersOnWindows
|
||||
? mWindowCornerRadius : 0;
|
||||
cornerRadius = Utilities.mapRange(progress, windowCornerRadius,
|
||||
mTaskCornerRadius);
|
||||
}
|
||||
mCurrentCornerRadius = cornerRadius;
|
||||
}
|
||||
// Fade out Assistant overlay.
|
||||
if (app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_ASSISTANT
|
||||
&& app.isNotInRecents) {
|
||||
alpha = 1 - Interpolators.DEACCEL_2_5.getInterpolation(progress);
|
||||
}
|
||||
} else if (params.mTargetSet.hasRecents) {
|
||||
// If home has a different target then recents, reverse anim the
|
||||
// home target.
|
||||
alpha = 1 - (progress * params.mTargetAlpha);
|
||||
}
|
||||
} else {
|
||||
alpha = mBaseAlphaCallback.getAlpha(app, progress);
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get() && params.mLauncherOnTop) {
|
||||
crop = null;
|
||||
}
|
||||
}
|
||||
builder.withAlpha(alpha)
|
||||
.withMatrix(mTmpMatrix)
|
||||
builder.withMatrix(mTmpMatrix)
|
||||
.withWindowCrop(crop)
|
||||
// Since radius is in Surface space, but we draw the rounded corners in screen
|
||||
// space, we have to undo the scale
|
||||
.withCornerRadius(cornerRadius / scale);
|
||||
surfaceParams[i] = builder.build();
|
||||
|
||||
}
|
||||
return surfaceParams;
|
||||
}
|
||||
|
||||
public RectF updateCurrentRect(TransformParams params) {
|
||||
if (params.mCurrentRect != null) {
|
||||
mCurrentRect.set(params.mCurrentRect);
|
||||
if (params.getCurrentRect() != null) {
|
||||
mCurrentRect.set(params.getCurrentRect());
|
||||
} else {
|
||||
mTmpRectF.set(mTargetRect);
|
||||
Utilities.scaleRectFAboutCenter(mTmpRectF, params.mOffsetScale);
|
||||
mCurrentRect.set(mRectFEvaluator.evaluate(params.mProgress, mSourceRect, mTmpRectF));
|
||||
if (mOrientedState == null
|
||||
|| !mOrientedState.isMultipleOrientationSupportedByDevice()) {
|
||||
mCurrentRect.offset(params.mOffset, 0);
|
||||
} else {
|
||||
int displayRotation = mOrientedState.getDisplayRotation();
|
||||
int launcherRotation = mOrientedState.getLauncherRotation();
|
||||
mOrientedState.getOrientationHandler().offsetTaskRect(mCurrentRect,
|
||||
params.mOffset, displayRotation, launcherRotation);
|
||||
}
|
||||
mCurrentRect.set(mRectFEvaluator.evaluate(
|
||||
params.getProgress(), mSourceRect, mTmpRectF));
|
||||
}
|
||||
|
||||
updateClipRect(params);
|
||||
|
@ -275,7 +232,7 @@ public class AppWindowAnimationHelper {
|
|||
|
||||
private void updateClipRect(TransformParams params) {
|
||||
// Don't clip past progress > 1.
|
||||
float progress = Math.min(1, params.mProgress);
|
||||
float progress = Math.min(1, params.getProgress());
|
||||
mCurrentClipRectF.left = mSourceWindowClipInsets.left * progress;
|
||||
mCurrentClipRectF.top = mSourceWindowClipInsets.top * progress;
|
||||
mCurrentClipRectF.right =
|
||||
|
@ -289,28 +246,6 @@ public class AppWindowAnimationHelper {
|
|||
return mCurrentRectWithInsets;
|
||||
}
|
||||
|
||||
public static void applySurfaceParams(@Nullable SyncRtSurfaceTransactionApplierCompat
|
||||
syncTransactionApplier, SurfaceParams[] params) {
|
||||
if (syncTransactionApplier != null) {
|
||||
syncTransactionApplier.scheduleApply(params);
|
||||
} else {
|
||||
TransactionCompat t = new TransactionCompat();
|
||||
for (SurfaceParams param : params) {
|
||||
SyncRtSurfaceTransactionApplierCompat.applyParams(t, param);
|
||||
}
|
||||
t.setEarlyWakeup();
|
||||
t.apply();
|
||||
}
|
||||
}
|
||||
|
||||
public void setTaskAlphaCallback(TargetAlphaProvider callback) {
|
||||
mTaskAlphaCallback = callback;
|
||||
}
|
||||
|
||||
public void setBaseAlphaCallback(TargetAlphaProvider callback) {
|
||||
mBaseAlphaCallback = callback;
|
||||
}
|
||||
|
||||
public void fromTaskThumbnailView(TaskThumbnailView ttv, RecentsView rv,
|
||||
@Nullable RemoteAnimationTargetCompat target) {
|
||||
BaseDraggingActivity activity = BaseDraggingActivity.fromContext(ttv.getContext());
|
||||
|
@ -386,157 +321,4 @@ public class AppWindowAnimationHelper {
|
|||
return mCurrentCornerRadius;
|
||||
}
|
||||
|
||||
public interface TargetAlphaProvider {
|
||||
float getAlpha(RemoteAnimationTargetCompat target, float expectedAlpha);
|
||||
}
|
||||
|
||||
public static class TransformParams {
|
||||
private float mProgress;
|
||||
private float mOffset;
|
||||
private float mOffsetScale;
|
||||
private @Nullable RectF mCurrentRect;
|
||||
private float mTargetAlpha;
|
||||
private float mCornerRadius;
|
||||
private boolean mLauncherOnTop;
|
||||
private RemoteAnimationTargets mTargetSet;
|
||||
private SyncRtSurfaceTransactionApplierCompat mSyncTransactionApplier;
|
||||
|
||||
public TransformParams() {
|
||||
mProgress = 0;
|
||||
mOffset = 0;
|
||||
mOffsetScale = 1;
|
||||
mCurrentRect = null;
|
||||
mTargetAlpha = 1;
|
||||
mCornerRadius = -1;
|
||||
mLauncherOnTop = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the progress of the transformation, where 0 is the source and 1 is the target. We
|
||||
* automatically adjust properties such as currentRect and cornerRadius based on this
|
||||
* progress, unless they are manually overridden by setting them on this TransformParams.
|
||||
*/
|
||||
public TransformParams setProgress(float progress) {
|
||||
mProgress = progress;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the corner radius of the transformed window, in pixels. If unspecified (-1), we
|
||||
* simply interpolate between the window's corner radius to the task view's corner radius,
|
||||
* based on {@link #mProgress}.
|
||||
*/
|
||||
public TransformParams setCornerRadius(float cornerRadius) {
|
||||
mCornerRadius = cornerRadius;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current rect to show the transformed window, in device coordinates. This gives
|
||||
* the caller manual control of where to show the window. If unspecified (null), we
|
||||
* interpolate between {@link AppWindowAnimationHelper#mSourceRect} and
|
||||
* {@link AppWindowAnimationHelper#mTargetRect}, based on {@link #mProgress}.
|
||||
*/
|
||||
public TransformParams setCurrentRect(RectF currentRect) {
|
||||
mCurrentRect = currentRect;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the alpha of the transformed window. Default is 1.
|
||||
*/
|
||||
public TransformParams setTargetAlpha(float targetAlpha) {
|
||||
mTargetAlpha = targetAlpha;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If {@link #mCurrentRect} is null (i.e. {@link #setCurrentRect(RectF)} hasn't overridden
|
||||
* the default), then offset the current rect by this amount after computing the rect based
|
||||
* on {@link #mProgress}.
|
||||
*/
|
||||
public TransformParams setOffset(float offset) {
|
||||
mOffset = offset;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If {@link #mCurrentRect} is null (i.e. {@link #setCurrentRect(RectF)} hasn't overridden
|
||||
* the default), then scale the current rect by this amount after computing the rect based
|
||||
* on {@link #mProgress}.
|
||||
*/
|
||||
public TransformParams setOffsetScale(float offsetScale) {
|
||||
mOffsetScale = offsetScale;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If true, sets the crop = null and layer = Integer.MAX_VALUE for targets that don't match
|
||||
* {@link #mTargetSet}.targetMode. (Currently only does this when live tiles are enabled.)
|
||||
*/
|
||||
public TransformParams setLauncherOnTop(boolean launcherOnTop) {
|
||||
mLauncherOnTop = launcherOnTop;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the set of RemoteAnimationTargetCompats that are included in the transformation
|
||||
* that these TransformParams help compute. These TransformParams generally only apply to
|
||||
* the targetSet.apps which match the targetSet.targetMode (e.g. the MODE_CLOSING app when
|
||||
* swiping to home).
|
||||
*/
|
||||
public TransformParams setTargetSet(RemoteAnimationTargets targetSet) {
|
||||
mTargetSet = targetSet;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the SyncRtSurfaceTransactionApplierCompat that will apply the SurfaceParams that
|
||||
* are computed based on these TransformParams.
|
||||
*/
|
||||
public TransformParams setSyncTransactionApplier(
|
||||
SyncRtSurfaceTransactionApplierCompat applier) {
|
||||
mSyncTransactionApplier = applier;
|
||||
return this;
|
||||
}
|
||||
|
||||
// Pubic getters so outside packages can read the values.
|
||||
|
||||
public float getProgress() {
|
||||
return mProgress;
|
||||
}
|
||||
|
||||
public float getOffset() {
|
||||
return mOffset;
|
||||
}
|
||||
|
||||
public float getOffsetScale() {
|
||||
return mOffsetScale;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public RectF getCurrentRect() {
|
||||
return mCurrentRect;
|
||||
}
|
||||
|
||||
public float getTargetAlpha() {
|
||||
return mTargetAlpha;
|
||||
}
|
||||
|
||||
public float getCornerRadius() {
|
||||
return mCornerRadius;
|
||||
}
|
||||
|
||||
public boolean isLauncherOnTop() {
|
||||
return mLauncherOnTop;
|
||||
}
|
||||
|
||||
public RemoteAnimationTargets getTargetSet() {
|
||||
return mTargetSet;
|
||||
}
|
||||
|
||||
public SyncRtSurfaceTransactionApplierCompat getSyncTransactionApplier() {
|
||||
return mSyncTransactionApplier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,10 +15,10 @@
|
|||
*/
|
||||
package com.android.quickstep.util;
|
||||
|
||||
import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_SHELF_ANIM;
|
||||
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
|
||||
import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_SHELF_ANIM;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
|
|
|
@ -19,8 +19,6 @@ import static android.view.Surface.ROTATION_0;
|
|||
|
||||
import static com.android.launcher3.states.RotationHelper.deltaRotation;
|
||||
import static com.android.launcher3.touch.PagedOrientationHandler.MATRIX_POST_TRANSLATE;
|
||||
import static com.android.quickstep.util.AppWindowAnimationHelper.applySurfaceParams;
|
||||
import static com.android.quickstep.util.RecentsOrientedState.isFixedRotationTransformEnabled;
|
||||
import static com.android.quickstep.util.RecentsOrientedState.postDisplayRotation;
|
||||
import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_FULLSCREEN;
|
||||
|
||||
|
@ -33,24 +31,20 @@ import android.graphics.RectF;
|
|||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.quickstep.AnimatedFloat;
|
||||
import com.android.quickstep.RecentsAnimationTargets;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper.TargetAlphaProvider;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper.TransformParams;
|
||||
import com.android.quickstep.views.RecentsView.ScrollState;
|
||||
import com.android.quickstep.views.TaskThumbnailView.PreviewPositionHelper;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.quickstep.views.TaskView.FullscreenDrawParams;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams.Builder;
|
||||
|
||||
/**
|
||||
* A utility class which emulates the layout behavior of TaskView and RecentsView
|
||||
*/
|
||||
public class TaskViewSimulator {
|
||||
public class TaskViewSimulator implements TransformParams.BuilderProxy {
|
||||
|
||||
private final Rect mTmpCropRect = new Rect();
|
||||
private final RectF mTempRectF = new RectF();
|
||||
|
@ -66,14 +60,11 @@ public class TaskViewSimulator {
|
|||
|
||||
private final Matrix mMatrix = new Matrix();
|
||||
private RemoteAnimationTargetCompat mRunningTarget;
|
||||
private RecentsAnimationTargets mAllTargets;
|
||||
|
||||
private TargetAlphaProvider mTaskAlphaCallback = (t, a) -> a;
|
||||
|
||||
// Thumbnail view properties
|
||||
private final Rect mThumbnailPosition = new Rect();
|
||||
private final ThumbnailData mThumbnailData = new ThumbnailData();
|
||||
private final PreviewPositionHelper mPositionHelper;
|
||||
private final PreviewPositionHelper mPositionHelper = new PreviewPositionHelper();
|
||||
private final Matrix mInversePositionMatrix = new Matrix();
|
||||
|
||||
// TaskView properties
|
||||
|
@ -93,12 +84,8 @@ public class TaskViewSimulator {
|
|||
public TaskViewSimulator(Context context, WindowSizeStrategy sizeStrategy) {
|
||||
mContext = context;
|
||||
mSizeStrategy = sizeStrategy;
|
||||
mPositionHelper = new PreviewPositionHelper(context);
|
||||
|
||||
mOrientationState = new RecentsOrientedState(context, sizeStrategy, i -> { });
|
||||
// We do not need to attach listeners as the simulator is created just for the gesture
|
||||
// duration, and any settings are unlikely to change during this
|
||||
mOrientationState.initWithoutListeners();
|
||||
|
||||
mCurrentFullscreenParams = new FullscreenDrawParams(context);
|
||||
mPageSpacing = context.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing);
|
||||
|
@ -117,15 +104,7 @@ public class TaskViewSimulator {
|
|||
* @see com.android.quickstep.views.RecentsView#setLayoutRotation(int, int)
|
||||
*/
|
||||
public void setLayoutRotation(int touchRotation, int displayRotation) {
|
||||
int launcherRotation;
|
||||
if (!mOrientationState.isMultipleOrientationSupportedByDevice()
|
||||
|| mOrientationState.isHomeRotationAllowed()) {
|
||||
launcherRotation = displayRotation;
|
||||
} else {
|
||||
launcherRotation = ROTATION_0;
|
||||
}
|
||||
|
||||
mOrientationState.update(touchRotation, displayRotation, launcherRotation);
|
||||
mOrientationState.update(touchRotation, displayRotation);
|
||||
mLayoutValid = false;
|
||||
}
|
||||
|
||||
|
@ -143,10 +122,8 @@ public class TaskViewSimulator {
|
|||
/**
|
||||
* Sets the targets which the simulator will control
|
||||
*/
|
||||
public void setPreview(
|
||||
RemoteAnimationTargetCompat runningTarget, RecentsAnimationTargets allTargets) {
|
||||
public void setPreview(RemoteAnimationTargetCompat runningTarget) {
|
||||
mRunningTarget = runningTarget;
|
||||
mAllTargets = allTargets;
|
||||
|
||||
mThumbnailData.insets.set(mRunningTarget.contentInsets);
|
||||
// TODO: What is this?
|
||||
|
@ -169,10 +146,40 @@ public class TaskViewSimulator {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets an alternate function which can be used to control the alpha
|
||||
* Returns the current clipped/visible window bounds in the window coordinate space
|
||||
*/
|
||||
public void setTaskAlphaCallback(TargetAlphaProvider callback) {
|
||||
mTaskAlphaCallback = callback;
|
||||
public RectF getCurrentCropRect() {
|
||||
// Crop rect is the inverse of thumbnail matrix
|
||||
RectF insets = mCurrentFullscreenParams.mCurrentDrawnInsets;
|
||||
mTempRectF.set(-insets.left, -insets.top,
|
||||
mTaskRect.width() + insets.right, mTaskRect.height() + insets.bottom);
|
||||
mInversePositionMatrix.mapRect(mTempRectF);
|
||||
return mTempRectF;
|
||||
}
|
||||
|
||||
public RecentsOrientedState getOrientationState() {
|
||||
return mOrientationState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current transform applied to the window
|
||||
*/
|
||||
public Matrix getCurrentMatrix() {
|
||||
return mMatrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the rotation on the matrix to so that it maps from launcher coordinate space to
|
||||
* window coordinate space.
|
||||
*/
|
||||
public void applyWindowToHomeRotation(Matrix matrix) {
|
||||
mMatrix.postTranslate(mDp.windowX, mDp.windowY);
|
||||
postDisplayRotation(deltaRotation(
|
||||
mOrientationState.getLauncherRotation(), mOrientationState.getDisplayRotation()),
|
||||
mDp.widthPx, mDp.heightPx, matrix);
|
||||
if (mRunningTarget != null) {
|
||||
matrix.postTranslate(-mRunningTarget.position.x, -mRunningTarget.position.y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -186,12 +193,12 @@ public class TaskViewSimulator {
|
|||
mLayoutValid = true;
|
||||
|
||||
getFullScreenScale();
|
||||
mThumbnailData.rotation = isFixedRotationTransformEnabled(mContext)
|
||||
? mOrientationState.getDisplayRotation() : mPositionHelper.getCurrentRotation();
|
||||
|
||||
mPositionHelper.updateThumbnailMatrix(mThumbnailPosition, mThumbnailData,
|
||||
mTaskRect.width(), mTaskRect.height(), mDp);
|
||||
mThumbnailData.rotation = mOrientationState.getDisplayRotation();
|
||||
|
||||
mPositionHelper.updateThumbnailMatrix(
|
||||
mThumbnailPosition, mThumbnailData,
|
||||
mTaskRect.width(), mTaskRect.height(),
|
||||
mDp, mOrientationState.getLauncherRotation());
|
||||
mPositionHelper.getMatrix().invert(mInversePositionMatrix);
|
||||
|
||||
PagedOrientationHandler poh = mOrientationState.getOrientationHandler();
|
||||
|
@ -201,7 +208,6 @@ public class TaskViewSimulator {
|
|||
mScrollValid = false;
|
||||
}
|
||||
|
||||
|
||||
if (!mScrollValid) {
|
||||
mScrollValid = true;
|
||||
int start = mOrientationState.getOrientationHandler()
|
||||
|
@ -233,11 +239,7 @@ public class TaskViewSimulator {
|
|||
|
||||
// Apply recensView matrix
|
||||
mMatrix.postScale(recentsViewScale.value, recentsViewScale.value, mPivot.x, mPivot.y);
|
||||
postDisplayRotation(deltaRotation(
|
||||
mOrientationState.getLauncherRotation(), mOrientationState.getDisplayRotation()),
|
||||
mDp.widthPx, mDp.heightPx, mMatrix);
|
||||
mMatrix.postTranslate(mDp.windowX - mRunningTarget.position.x,
|
||||
mDp.windowY - mRunningTarget.position.y);
|
||||
applyWindowToHomeRotation(mMatrix);
|
||||
|
||||
// Crop rect is the inverse of thumbnail matrix
|
||||
mTempRectF.set(-insets.left, -insets.top,
|
||||
|
@ -245,35 +247,18 @@ public class TaskViewSimulator {
|
|||
mInversePositionMatrix.mapRect(mTempRectF);
|
||||
mTempRectF.roundOut(mTmpCropRect);
|
||||
|
||||
SurfaceParams[] surfaceParams = new SurfaceParams[mAllTargets.unfilteredApps.length];
|
||||
for (int i = 0; i < mAllTargets.unfilteredApps.length; i++) {
|
||||
RemoteAnimationTargetCompat app = mAllTargets.unfilteredApps[i];
|
||||
SurfaceParams.Builder builder = new SurfaceParams.Builder(app.leash);
|
||||
params.applySurfaceParams(params.createSurfaceParams(this));
|
||||
}
|
||||
|
||||
if (app.mode == mAllTargets.targetMode) {
|
||||
float alpha = mTaskAlphaCallback.getAlpha(app, params.getTargetAlpha());
|
||||
if (app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
|
||||
// Fade out Assistant overlay.
|
||||
if (app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_ASSISTANT
|
||||
&& app.isNotInRecents) {
|
||||
alpha = Interpolators.ACCEL_2.getInterpolation(fullScreenProgress.value);
|
||||
}
|
||||
|
||||
builder.withAlpha(alpha)
|
||||
.withMatrix(mMatrix)
|
||||
.withWindowCrop(mTmpCropRect)
|
||||
.withCornerRadius(getCurrentCornerRadius());
|
||||
} else if (params.getTargetSet().hasRecents) {
|
||||
// If home has a different target then recents, reverse anim the home target.
|
||||
builder.withAlpha(fullScreenProgress.value * params.getTargetAlpha());
|
||||
}
|
||||
} else {
|
||||
builder.withAlpha(1);
|
||||
}
|
||||
surfaceParams[i] = builder.build();
|
||||
@Override
|
||||
public void onBuildParams(Builder builder, RemoteAnimationTargetCompat app,
|
||||
int targetMode, TransformParams params) {
|
||||
if (app.mode == targetMode
|
||||
&& app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
|
||||
builder.withMatrix(mMatrix)
|
||||
.withWindowCrop(mTmpCropRect)
|
||||
.withCornerRadius(getCurrentCornerRadius());
|
||||
}
|
||||
|
||||
applySurfaceParams(params.getSyncTransactionApplier(), surfaceParams);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.quickstep.util;
|
||||
|
||||
import android.graphics.RectF;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.quickstep.RemoteAnimationTargets;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
|
||||
import com.android.systemui.shared.system.TransactionCompat;
|
||||
|
||||
public class TransformParams {
|
||||
|
||||
private float mProgress;
|
||||
private @Nullable RectF mCurrentRect;
|
||||
private float mTargetAlpha;
|
||||
private float mCornerRadius;
|
||||
private RemoteAnimationTargets mTargetSet;
|
||||
private SyncRtSurfaceTransactionApplierCompat mSyncTransactionApplier;
|
||||
|
||||
private TargetAlphaProvider mTaskAlphaCallback = (t, a) -> a;
|
||||
private TargetAlphaProvider mBaseAlphaCallback = (t, a) -> 1;
|
||||
|
||||
public TransformParams() {
|
||||
mProgress = 0;
|
||||
mCurrentRect = null;
|
||||
mTargetAlpha = 1;
|
||||
mCornerRadius = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the progress of the transformation, where 0 is the source and 1 is the target. We
|
||||
* automatically adjust properties such as currentRect and cornerRadius based on this
|
||||
* progress, unless they are manually overridden by setting them on this TransformParams.
|
||||
*/
|
||||
public TransformParams setProgress(float progress) {
|
||||
mProgress = progress;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the corner radius of the transformed window, in pixels. If unspecified (-1), we
|
||||
* simply interpolate between the window's corner radius to the task view's corner radius,
|
||||
* based on {@link #mProgress}.
|
||||
*/
|
||||
public TransformParams setCornerRadius(float cornerRadius) {
|
||||
mCornerRadius = cornerRadius;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current rect to show the transformed window, in device coordinates. This gives
|
||||
* the caller manual control of where to show the window. If unspecified (null), we
|
||||
* interpolate between {@link AppWindowAnimationHelper#mSourceRect} and
|
||||
* {@link AppWindowAnimationHelper#mTargetRect}, based on {@link #mProgress}.
|
||||
*/
|
||||
public TransformParams setCurrentRect(RectF currentRect) {
|
||||
mCurrentRect = currentRect;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the alpha of the transformed window. Default is 1.
|
||||
*/
|
||||
public TransformParams setTargetAlpha(float targetAlpha) {
|
||||
mTargetAlpha = targetAlpha;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the set of RemoteAnimationTargetCompats that are included in the transformation
|
||||
* that these TransformParams help compute. These TransformParams generally only apply to
|
||||
* the targetSet.apps which match the targetSet.targetMode (e.g. the MODE_CLOSING app when
|
||||
* swiping to home).
|
||||
*/
|
||||
public TransformParams setTargetSet(RemoteAnimationTargets targetSet) {
|
||||
mTargetSet = targetSet;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the SyncRtSurfaceTransactionApplierCompat that will apply the SurfaceParams that
|
||||
* are computed based on these TransformParams.
|
||||
*/
|
||||
public TransformParams setSyncTransactionApplier(
|
||||
SyncRtSurfaceTransactionApplierCompat applier) {
|
||||
mSyncTransactionApplier = applier;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an alternate function which can be used to control the alpha of target app
|
||||
*/
|
||||
public TransformParams setTaskAlphaCallback(TargetAlphaProvider callback) {
|
||||
mTaskAlphaCallback = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an alternate function which can be used to control the alpha of non-target app
|
||||
*/
|
||||
public TransformParams setBaseAlphaCallback(TargetAlphaProvider callback) {
|
||||
mBaseAlphaCallback = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SurfaceParams[] createSurfaceParams(BuilderProxy proxy) {
|
||||
RemoteAnimationTargets targets = mTargetSet;
|
||||
SurfaceParams[] surfaceParams = new SurfaceParams[targets.unfilteredApps.length];
|
||||
for (int i = 0; i < targets.unfilteredApps.length; i++) {
|
||||
RemoteAnimationTargetCompat app = targets.unfilteredApps[i];
|
||||
SurfaceParams.Builder builder = new SurfaceParams.Builder(app.leash);
|
||||
|
||||
float progress = Utilities.boundToRange(getProgress(), 0, 1);
|
||||
float alpha;
|
||||
if (app.mode == targets.targetMode) {
|
||||
alpha = mTaskAlphaCallback.getAlpha(app, getTargetAlpha());
|
||||
if (app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
|
||||
// Fade out Assistant overlay.
|
||||
if (app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_ASSISTANT
|
||||
&& app.isNotInRecents) {
|
||||
alpha = 1 - Interpolators.DEACCEL_2_5.getInterpolation(progress);
|
||||
}
|
||||
} else if (targets.hasRecents) {
|
||||
// If home has a different target then recents, reverse anim the
|
||||
// home target.
|
||||
alpha = 1 - (progress * getTargetAlpha());
|
||||
}
|
||||
} else {
|
||||
alpha = mBaseAlphaCallback.getAlpha(app, progress);
|
||||
}
|
||||
proxy.onBuildParams(builder.withAlpha(alpha), app, targets.targetMode, this);
|
||||
surfaceParams[i] = builder.build();
|
||||
}
|
||||
return surfaceParams;
|
||||
}
|
||||
|
||||
// Pubic getters so outside packages can read the values.
|
||||
|
||||
public float getProgress() {
|
||||
return mProgress;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public RectF getCurrentRect() {
|
||||
return mCurrentRect;
|
||||
}
|
||||
|
||||
public float getTargetAlpha() {
|
||||
return mTargetAlpha;
|
||||
}
|
||||
|
||||
public float getCornerRadius() {
|
||||
return mCornerRadius;
|
||||
}
|
||||
|
||||
public RemoteAnimationTargets getTargetSet() {
|
||||
return mTargetSet;
|
||||
}
|
||||
|
||||
public SyncRtSurfaceTransactionApplierCompat getSyncTransactionApplier() {
|
||||
return mSyncTransactionApplier;
|
||||
}
|
||||
|
||||
public void applySurfaceParams(SurfaceParams[] params) {
|
||||
if (mSyncTransactionApplier != null) {
|
||||
mSyncTransactionApplier.scheduleApply(params);
|
||||
} else {
|
||||
TransactionCompat t = new TransactionCompat();
|
||||
for (SurfaceParams param : params) {
|
||||
SyncRtSurfaceTransactionApplierCompat.applyParams(t, param);
|
||||
}
|
||||
t.setEarlyWakeup();
|
||||
t.apply();
|
||||
}
|
||||
}
|
||||
|
||||
public interface TargetAlphaProvider {
|
||||
float getAlpha(RemoteAnimationTargetCompat target, float expectedAlpha);
|
||||
}
|
||||
|
||||
public interface BuilderProxy {
|
||||
|
||||
void onBuildParams(SurfaceParams.Builder builder,
|
||||
RemoteAnimationTargetCompat app, int targetMode, TransformParams params);
|
||||
}
|
||||
}
|
|
@ -64,7 +64,13 @@ public class ClearAllButton extends Button implements PageCallbacks {
|
|||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
mParent = (RecentsView) getParent();
|
||||
mIsRtl = !mParent.getPagedOrientationHandler().getRecentsRtlSetting(getResources());
|
||||
mIsRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRtlPropertiesChanged(int layoutDirection) {
|
||||
super.onRtlPropertiesChanged(layoutDirection);
|
||||
mIsRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -31,27 +31,24 @@ import android.animation.AnimatorSet;
|
|||
import android.animation.ObjectAnimator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.android.launcher3.BaseQuickstepLauncher;
|
||||
import com.android.launcher3.Hotseat;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager.StateListener;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.appprediction.PredictionUiStateManager;
|
||||
import com.android.launcher3.appprediction.PredictionUiStateManager.Client;
|
||||
import com.android.launcher3.statehandlers.DepthController;
|
||||
import com.android.launcher3.statemanager.StateManager.StateListener;
|
||||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.launcher3.views.ScrimView;
|
||||
import com.android.quickstep.SysUINavigationMode;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper.TransformParams;
|
||||
import com.android.quickstep.util.TransformParams;
|
||||
import com.android.systemui.plugins.PluginListener;
|
||||
import com.android.systemui.plugins.RecentsExtraCard;
|
||||
|
||||
|
@ -60,7 +57,7 @@ import com.android.systemui.plugins.RecentsExtraCard;
|
|||
*/
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class LauncherRecentsView extends RecentsView<BaseQuickstepLauncher>
|
||||
implements StateListener {
|
||||
implements StateListener<LauncherState> {
|
||||
|
||||
private final TransformParams mTransformParams = new TransformParams();
|
||||
|
||||
|
@ -124,24 +121,6 @@ public class LauncherRecentsView extends RecentsView<BaseQuickstepLauncher>
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
maybeDrawEmptyMessage(canvas);
|
||||
super.draw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewAdded(View child) {
|
||||
super.onViewAdded(child);
|
||||
updateEmptyMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTaskStackUpdated() {
|
||||
// Lazily update the empty message only when the task stack is reapplied
|
||||
updateEmptyMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Animates adjacent tasks and translate hotseat off screen as well.
|
||||
*/
|
||||
|
@ -213,14 +192,14 @@ public class LauncherRecentsView extends RecentsView<BaseQuickstepLauncher>
|
|||
|
||||
@Override
|
||||
public void redrawLiveTile(boolean mightNeedToRefill) {
|
||||
AppWindowAnimationHelper.TransformParams transformParams = getLiveTileParams(mightNeedToRefill);
|
||||
TransformParams transformParams = getLiveTileParams(mightNeedToRefill);
|
||||
if (transformParams != null) {
|
||||
mAppWindowAnimationHelper.applyTransform(transformParams);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppWindowAnimationHelper.TransformParams getLiveTileParams(
|
||||
public TransformParams getLiveTileParams(
|
||||
boolean mightNeedToRefill) {
|
||||
if (!mEnableDrawingLiveTile || mRecentsAnimationController == null
|
||||
|| mRecentsAnimationTargets == null || mAppWindowAnimationHelper == null) {
|
||||
|
@ -248,8 +227,7 @@ public class LauncherRecentsView extends RecentsView<BaseQuickstepLauncher>
|
|||
.setCurrentRect(mTempRectF)
|
||||
.setTargetAlpha(taskView.getAlpha())
|
||||
.setSyncTransactionApplier(mSyncTransactionApplier)
|
||||
.setTargetSet(mRecentsAnimationTargets)
|
||||
.setLauncherOnTop(true);
|
||||
.setTargetSet(mRecentsAnimationTargets);
|
||||
}
|
||||
return mTransformParams;
|
||||
}
|
||||
|
@ -373,4 +351,16 @@ public class LauncherRecentsView extends RecentsView<BaseQuickstepLauncher>
|
|||
protected DepthController getDepthController() {
|
||||
return mActivity.getDepthController();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModalStateEnabled(boolean isModalState) {
|
||||
super.setModalStateEnabled(isModalState);
|
||||
if (isModalState) {
|
||||
mActivity.getStateManager().goToState(LauncherState.OVERVIEW_MODAL_TASK);
|
||||
} else {
|
||||
if (mActivity.isInState(LauncherState.OVERVIEW_MODAL_TASK)) {
|
||||
mActivity.getStateManager().goToState(LauncherState.OVERVIEW);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import androidx.annotation.Nullable;
|
|||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.util.MultiValueAlpha;
|
||||
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
|
||||
import com.android.quickstep.SysUINavigationMode.Mode;
|
||||
import com.android.quickstep.TaskOverlayFactory.OverlayUICallbacks;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
|
@ -141,4 +142,19 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
|
|||
public AlphaProperty getVisibilityAlpha() {
|
||||
return mMultiValueAlpha.getProperty(INDEX_VISIBILITY_ALPHA);
|
||||
}
|
||||
|
||||
/** Updates vertical margins for different navigation mode. */
|
||||
public void updateVerticalMarginForNavModeChange(Mode mode) {
|
||||
int bottomMargin = 0;
|
||||
if (mode == Mode.THREE_BUTTONS) {
|
||||
bottomMargin = getResources()
|
||||
.getDimensionPixelSize(R.dimen.overview_actions_bottom_margin_three_button);
|
||||
} else {
|
||||
bottomMargin = getResources()
|
||||
.getDimensionPixelSize(R.dimen.overview_actions_bottom_margin_gesture);
|
||||
}
|
||||
LayoutParams params = (LayoutParams) getLayoutParams();
|
||||
params.setMargins(
|
||||
params.leftMargin, params.topMargin, params.rightMargin, bottomMargin);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
package com.android.quickstep.views;
|
||||
|
||||
import static android.view.Surface.ROTATION_0;
|
||||
|
||||
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
|
||||
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARAMS;
|
||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
|
@ -30,8 +32,8 @@ import static com.android.launcher3.anim.Interpolators.ACCEL_2;
|
|||
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.TASK_DISMISS_SWIPE_UP;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.TASK_LAUNCH_SWIPE_DOWN;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN;
|
||||
import static com.android.launcher3.statehandlers.DepthController.DEPTH;
|
||||
import static com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchController.SUCCESS_TRANSITION_PROGRESS;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
|
||||
|
@ -55,7 +57,6 @@ import android.app.ActivityManager;
|
|||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
|
@ -123,14 +124,16 @@ import com.android.quickstep.TaskThumbnailCache;
|
|||
import com.android.quickstep.TaskUtils;
|
||||
import com.android.quickstep.ViewUtils;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
import com.android.quickstep.util.RecentsOrientedState;
|
||||
import com.android.quickstep.util.SplitScreenBounds;
|
||||
import com.android.quickstep.util.TransformParams;
|
||||
import com.android.quickstep.util.WindowSizeStrategy;
|
||||
import com.android.systemui.plugins.ResourceProvider;
|
||||
import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.ConfigurationCompat;
|
||||
import com.android.systemui.shared.system.LauncherEventUtil;
|
||||
import com.android.systemui.shared.system.PackageManagerWrapper;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
|
||||
|
@ -145,7 +148,8 @@ import java.util.function.Consumer;
|
|||
@TargetApi(Build.VERSION_CODES.P)
|
||||
public abstract class RecentsView<T extends BaseActivity> extends PagedView implements Insettable,
|
||||
TaskThumbnailCache.HighResLoadingState.HighResLoadingStateChangedCallback,
|
||||
InvariantDeviceProfile.OnIDPChangeListener, TaskVisualsChangeListener {
|
||||
InvariantDeviceProfile.OnIDPChangeListener, TaskVisualsChangeListener,
|
||||
SplitScreenBounds.OnChangeListener {
|
||||
|
||||
private static final String TAG = RecentsView.class.getSimpleName();
|
||||
|
||||
|
@ -507,7 +511,8 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||
mIPinnedStackAnimationListener.setActivity(mActivity);
|
||||
SystemUiProxy.INSTANCE.get(getContext()).setPinnedStackAnimationListener(
|
||||
mIPinnedStackAnimationListener);
|
||||
mOrientationState.init();
|
||||
mOrientationState.initListeners();
|
||||
SplitScreenBounds.INSTANCE.addOnChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -521,8 +526,9 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||
RecentsModel.INSTANCE.get(getContext()).removeThumbnailChangeListener(this);
|
||||
mIdp.removeOnChangeListener(this);
|
||||
SystemUiProxy.INSTANCE.get(getContext()).setPinnedStackAnimationListener(null);
|
||||
SplitScreenBounds.INSTANCE.removeOnChangeListener(this);
|
||||
mIPinnedStackAnimationListener.setActivity(null);
|
||||
mOrientationState.destroy();
|
||||
mOrientationState.destroyListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -548,6 +554,13 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||
child.setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_LTR : View.LAYOUT_DIRECTION_RTL);
|
||||
updateTaskStartIndex(child);
|
||||
mActionsView.updateHiddenFlags(HIDDEN_NO_TASKS, false);
|
||||
updateEmptyMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
maybeDrawEmptyMessage(canvas);
|
||||
super.draw(canvas);
|
||||
}
|
||||
|
||||
private void updateTaskStartIndex(View affectingView) {
|
||||
|
@ -598,20 +611,20 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void onPageEndTransition() {
|
||||
super.onPageEndTransition();
|
||||
if (getNextPage() > 0) {
|
||||
setSwipeDownShouldLaunchApp(true);
|
||||
}
|
||||
protected void onPageBeginTransition() {
|
||||
super.onPageBeginTransition();
|
||||
LayoutUtils.setViewEnabled(mActionsView, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
int windowConfigurationRotation = ConfigurationCompat
|
||||
.getWindowConfigurationRotation(getResources().getConfiguration());
|
||||
setLayoutInternal(mOrientationState.getTouchRotation(),
|
||||
mOrientationState.getDisplayRotation(), windowConfigurationRotation);
|
||||
protected void onPageEndTransition() {
|
||||
super.onPageEndTransition();
|
||||
if (getScrollX() == getScrollForPage(getPageNearestToCenterOfScreen())) {
|
||||
LayoutUtils.setViewEnabled(mActionsView, true);
|
||||
}
|
||||
if (getNextPage() > 0) {
|
||||
setSwipeDownShouldLaunchApp(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -760,7 +773,10 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||
return taskViewCount;
|
||||
}
|
||||
|
||||
protected void onTaskStackUpdated() { }
|
||||
protected void onTaskStackUpdated() {
|
||||
// Lazily update the empty message only when the task stack is reapplied
|
||||
updateEmptyMessage();
|
||||
}
|
||||
|
||||
public void resetTaskVisuals() {
|
||||
for (int i = getTaskViewCount() - 1; i >= 0; i--) {
|
||||
|
@ -827,6 +843,11 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||
mSizeStrategy.calculateTaskSize(mActivity, mActivity.getDeviceProfile(), outRect);
|
||||
}
|
||||
|
||||
/** Gets the task size for modal state. */
|
||||
public void getModalTaskSize(Rect outRect) {
|
||||
mSizeStrategy.calculateModalTaskSize(mActivity, mActivity.getDeviceProfile(), outRect);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean computeScrollHelper() {
|
||||
boolean scrolling = super.computeScrollHelper();
|
||||
|
@ -958,6 +979,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||
setCurrentPage(0);
|
||||
mDwbToastShown = false;
|
||||
mActivity.getSystemUiController().updateUiState(UI_STATE_OVERVIEW, 0);
|
||||
LayoutUtils.setViewEnabled(mActionsView, true);
|
||||
}
|
||||
|
||||
public @Nullable TaskView getRunningTaskView() {
|
||||
|
@ -965,7 +987,15 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||
}
|
||||
|
||||
public int getRunningTaskIndex() {
|
||||
TaskView tv = getRunningTaskView();
|
||||
return getTaskIndexForId(mRunningTaskId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index of the task view whose id matches {@param taskId}.
|
||||
* @return -1 if there is no task view for the task id, else the index of the task view.
|
||||
*/
|
||||
public int getTaskIndexForId(int taskId) {
|
||||
TaskView tv = getTaskView(taskId);
|
||||
return tv == null ? -1 : indexOfChild(tv);
|
||||
}
|
||||
|
||||
|
@ -1294,7 +1324,8 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||
ComponentKey compKey = TaskUtils.getLaunchComponentKeyForTask(taskView.getTask().key);
|
||||
mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
|
||||
endState.logAction, Direction.UP, index, compKey);
|
||||
mActivity.getStatsLogManager().log(TASK_DISMISS_SWIPE_UP, taskView.buildProto());
|
||||
mActivity.getStatsLogManager().log(
|
||||
LAUNCHER_TASK_DISMISS_SWIPE_UP, taskView.buildProto());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1574,19 +1605,19 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||
}
|
||||
|
||||
public void setLayoutRotation(int touchRotation, int displayRotation) {
|
||||
int launcherRotation = mOrientationState.getLauncherRotation();
|
||||
setLayoutInternal(touchRotation, displayRotation, launcherRotation);
|
||||
}
|
||||
|
||||
private void setLayoutInternal(int touchRotation, int displayRotation, int launcherRotation) {
|
||||
if (mOrientationState.update(touchRotation, displayRotation, launcherRotation)) {
|
||||
if (mOrientationState.update(touchRotation, displayRotation)) {
|
||||
mOrientationHandler = mOrientationState.getOrientationHandler();
|
||||
mIsRtl = mOrientationHandler.getRecentsRtlSetting(getResources());
|
||||
setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
|
||||
setLayoutDirection(mIsRtl
|
||||
? View.LAYOUT_DIRECTION_RTL
|
||||
: View.LAYOUT_DIRECTION_LTR);
|
||||
mClearAllButton.setLayoutDirection(mIsRtl
|
||||
? View.LAYOUT_DIRECTION_LTR
|
||||
: View.LAYOUT_DIRECTION_RTL);
|
||||
mClearAllButton.setRotation(mOrientationHandler.getDegreesRotated());
|
||||
mActivity.getDragLayer().recreateControllers();
|
||||
mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION,
|
||||
touchRotation != 0 || launcherRotation != 0);
|
||||
touchRotation != 0 || mOrientationState.getLauncherRotation() != ROTATION_0);
|
||||
requestLayout();
|
||||
}
|
||||
}
|
||||
|
@ -1682,7 +1713,8 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||
}
|
||||
int count = getChildCount();
|
||||
|
||||
TaskView runningTask = mRunningTaskId == -1 ? null : getTaskView(mRunningTaskId);
|
||||
TaskView runningTask = mRunningTaskId == -1 || !mRunningTaskTileHidden
|
||||
? null : getTaskView(mRunningTaskId);
|
||||
int midPoint = runningTask == null ? -1 : indexOfChild(runningTask);
|
||||
int currentPage = getCurrentPage();
|
||||
|
||||
|
@ -1872,8 +1904,8 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||
mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
|
||||
endState.logAction, Direction.DOWN, indexOfChild(tv),
|
||||
TaskUtils.getLaunchComponentKeyForTask(task.key));
|
||||
mActivity.getStatsLogManager().log(TASK_LAUNCH_SWIPE_DOWN, tv.buildProto()
|
||||
);
|
||||
mActivity.getStatsLogManager().log(
|
||||
LAUNCHER_TASK_LAUNCH_SWIPE_DOWN, tv.buildProto());
|
||||
}
|
||||
} else {
|
||||
onTaskLaunched(false);
|
||||
|
@ -2059,14 +2091,6 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||
return getScrollForPage(getRunningTaskIndex()) - mOrientationHandler.getPrimaryScroll(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return How many pixels the running task is offset on the x-axis due to the current scrollX
|
||||
* and parent scale.
|
||||
*/
|
||||
public float getScrollOffsetScaled() {
|
||||
return getScrollOffset() * mOrientationHandler.getPrimaryScale(this);
|
||||
}
|
||||
|
||||
public Consumer<MotionEvent> getEventDispatcher(float navbarRotation) {
|
||||
float degreesRotated;
|
||||
if (navbarRotation == 0) {
|
||||
|
@ -2100,7 +2124,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||
return mAppWindowAnimationHelper;
|
||||
}
|
||||
|
||||
public AppWindowAnimationHelper.TransformParams getLiveTileParams(
|
||||
public TransformParams getLiveTileParams(
|
||||
boolean mightNeedToRefill) {
|
||||
return null;
|
||||
}
|
||||
|
@ -2145,18 +2169,6 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||
updatePageOffsets();
|
||||
if (getCurrentPageTaskView() != null) {
|
||||
getCurrentPageTaskView().setModalness(modalness);
|
||||
TaskView tv = getCurrentPageTaskView();
|
||||
|
||||
// Move the task view up as it scales...
|
||||
// ...the icon on taskview is hidden in modal state, so consider the top of the task
|
||||
mTempFloatPoint[0] = 0;
|
||||
mTempFloatPoint[1] = tv.getTop() + mTaskTopMargin;
|
||||
// ...find the top after the transformation
|
||||
getMatrix().mapPoints(mTempFloatPoint);
|
||||
|
||||
// ...make it match the top inset
|
||||
float calcOffset = (mInsets.top - mTempFloatPoint[1]) * mTaskModalness;
|
||||
tv.setTranslationY(calcOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2165,6 +2177,19 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSecondaryWindowBoundsChanged() {
|
||||
// Invalidate the task view size
|
||||
setInsets(mInsets);
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables modal state for RecentsView
|
||||
* @param isModalState
|
||||
*/
|
||||
public void setModalStateEnabled(boolean isModalState) { }
|
||||
|
||||
/**
|
||||
* Used to register callbacks for when our empty message state changes.
|
||||
*
|
||||
|
|
|
@ -90,7 +90,7 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc
|
|||
|
||||
// Contains the portion of the thumbnail that is clipped when fullscreen progress = 0.
|
||||
private final Rect mPreviewRect = new Rect();
|
||||
private final PreviewPositionHelper mPreviewPositionHelper;
|
||||
private final PreviewPositionHelper mPreviewPositionHelper = new PreviewPositionHelper();
|
||||
// Initialize with dummy value. It is overridden later by TaskView
|
||||
private TaskView.FullscreenDrawParams mFullscreenParams = TEMP_PARAMS;
|
||||
|
||||
|
@ -122,7 +122,6 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc
|
|||
mDimmingPaintAfterClearing.setColor(Color.BLACK);
|
||||
mActivity = BaseActivity.fromContext(context);
|
||||
mIsDarkTextTheme = Themes.getAttrBoolean(mActivity, R.attr.isWorkspaceDarkText);
|
||||
mPreviewPositionHelper = new PreviewPositionHelper(context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -349,8 +348,11 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc
|
|||
if (mBitmapShader != null && mThumbnailData != null) {
|
||||
mPreviewRect.set(0, 0, mThumbnailData.thumbnail.getWidth(),
|
||||
mThumbnailData.thumbnail.getHeight());
|
||||
int currentRotation = ConfigurationCompat.getWindowConfigurationRotation(
|
||||
mActivity.getResources().getConfiguration());
|
||||
mPreviewPositionHelper.updateThumbnailMatrix(mPreviewRect, mThumbnailData,
|
||||
getMeasuredWidth(), getMeasuredHeight(), mActivity.getDeviceProfile());
|
||||
getMeasuredWidth(), getMeasuredHeight(), mActivity.getDeviceProfile(),
|
||||
currentRotation);
|
||||
|
||||
mBitmapShader.setLocalMatrix(mPreviewPositionHelper.mMatrix);
|
||||
mPaint.setShader(mBitmapShader);
|
||||
|
@ -417,17 +419,6 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc
|
|||
private float mClipBottom = -1;
|
||||
private boolean mIsOrientationChanged;
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
public PreviewPositionHelper(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public int getCurrentRotation() {
|
||||
return ConfigurationCompat.getWindowConfigurationRotation(
|
||||
mContext.getResources().getConfiguration());
|
||||
}
|
||||
|
||||
public Matrix getMatrix() {
|
||||
return mMatrix;
|
||||
}
|
||||
|
@ -436,7 +427,7 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc
|
|||
* Updates the matrix based on the provided parameters
|
||||
*/
|
||||
public void updateThumbnailMatrix(Rect thumbnailPosition, ThumbnailData thumbnailData,
|
||||
int canvasWidth, int canvasHeight, DeviceProfile dp) {
|
||||
int canvasWidth, int canvasHeight, DeviceProfile dp, int currentRotation) {
|
||||
boolean isRotated = false;
|
||||
boolean isOrientationDifferent;
|
||||
mClipBottom = -1;
|
||||
|
@ -451,7 +442,6 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc
|
|||
|
||||
final float thumbnailScale;
|
||||
int thumbnailRotation = thumbnailData.rotation;
|
||||
int currentRotation = getCurrentRotation();
|
||||
int deltaRotate = getRotationDelta(currentRotation, thumbnailRotation);
|
||||
|
||||
Rect deviceInsets = dp.getInsets();
|
||||
|
|
|
@ -30,7 +30,7 @@ import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
|
|||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.TASK_LAUNCH_TAP;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
|
@ -212,7 +212,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
|||
mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
|
||||
Touch.TAP, Direction.NONE, getRecentsView().indexOfChild(this),
|
||||
TaskUtils.getLaunchComponentKeyForTask(getTask().key));
|
||||
mActivity.getStatsLogManager().log(TASK_LAUNCH_TAP, buildProto());
|
||||
mActivity.getStatsLogManager().log(LAUNCHER_TASK_LAUNCH_TAP, buildProto());
|
||||
});
|
||||
|
||||
mCurrentFullscreenParams = new FullscreenDrawParams(context);
|
||||
|
@ -449,13 +449,13 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
|||
|
||||
public void setOrientationState(RecentsOrientedState orientationState) {
|
||||
PagedOrientationHandler orientationHandler = orientationState.getOrientationHandler();
|
||||
boolean isRtl = orientationHandler.getRecentsRtlSetting(getResources());
|
||||
boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
|
||||
LayoutParams snapshotParams = (LayoutParams) mSnapshotView.getLayoutParams();
|
||||
int thumbnailPadding = (int) getResources().getDimension(R.dimen.task_thumbnail_top_margin);
|
||||
LayoutParams iconParams = (LayoutParams) mIconView.getLayoutParams();
|
||||
switch (orientationHandler.getRotation()) {
|
||||
case Surface.ROTATION_90:
|
||||
iconParams.gravity = (isRtl ? END : START) | CENTER_VERTICAL;
|
||||
iconParams.gravity = (isRtl ? START : END) | CENTER_VERTICAL;
|
||||
iconParams.rightMargin = -thumbnailPadding;
|
||||
iconParams.leftMargin = 0;
|
||||
iconParams.topMargin = snapshotParams.topMargin / 2;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<resources xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Splitscreen"</string>
|
||||
<string name="recent_task_option_pin" msgid="7929860679018978258">"Anpinnen"</string>
|
||||
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fixieren"</string>
|
||||
<string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform-Modus"</string>
|
||||
<string name="recents_empty_message" msgid="7040467240571714191">"Keine kürzlich verwendeten Elemente"</string>
|
||||
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Einstellungen zur App-Nutzung"</string>
|
||||
|
|
|
@ -17,14 +17,15 @@
|
|||
<resources>
|
||||
|
||||
<dimen name="task_thumbnail_top_margin">24dp</dimen>
|
||||
<dimen name="task_thumbnail_bottom_margin_with_actions">44dp</dimen>
|
||||
<dimen name="task_thumbnail_half_top_margin">12dp</dimen>
|
||||
<dimen name="task_thumbnail_icon_size">48dp</dimen>
|
||||
<!-- For screens without rounded corners -->
|
||||
<dimen name="task_corner_radius_small">2dp</dimen>
|
||||
|
||||
<!-- Overrideable in overlay that provides the Overview Actions. -->
|
||||
<dimen name="overview_actions_height">110dp</dimen>
|
||||
<dimen name="overview_actions_height">66dp</dimen>
|
||||
<dimen name="overview_actions_bottom_margin_gesture">16dp</dimen>
|
||||
<dimen name="overview_actions_bottom_margin_three_button">8dp</dimen>
|
||||
<dimen name="overview_actions_horizontal_margin">16dp</dimen>
|
||||
|
||||
<dimen name="recents_page_spacing">10dp</dimen>
|
||||
|
@ -61,7 +62,8 @@
|
|||
<dimen name="task_card_menu_shadow_height">3dp</dimen>
|
||||
<dimen name="task_card_menu_horizontal_padding">0dp</dimen>
|
||||
<dimen name="portrait_task_card_horz_space">136dp</dimen>
|
||||
<dimen name="portrait_task_card_horz_space_big_overview">24dp</dimen>
|
||||
<dimen name="portrait_task_card_horz_space_big_overview">96dp</dimen>
|
||||
<dimen name="portrait_modal_task_card_horz_space">60dp</dimen>
|
||||
<dimen name="landscape_task_card_horz_space">200dp</dimen>
|
||||
<dimen name="multi_window_task_card_horz_space">100dp</dimen>
|
||||
<!-- Copied from framework resource:
|
||||
|
|
|
@ -128,16 +128,18 @@
|
|||
<!-- Feedback shown during interactive parts of Home gesture tutorial when the gesture is horizontal instead of vertical. [CHAR LIMIT=100] -->
|
||||
<string name="home_gesture_feedback_wrong_swipe_direction" translatable="false">Make sure you swipe straight up</string>
|
||||
|
||||
<!-- Title shown on the confirmation screen after successful gesture. [CHAR LIMIT=30] -->
|
||||
<string name="gesture_tutorial_confirm_title" translatable="false">All set</string>
|
||||
<!-- Button text shown on a button on the confirm screen. [CHAR LIMIT=14] -->
|
||||
<string name="gesture_tutorial_action_button_label" translatable="false">Done</string>
|
||||
<!-- Button text shown on a text button on the confirm screen. [CHAR LIMIT=14] -->
|
||||
<string name="gesture_tutorial_action_text_button_label" translatable="false">Settings</string>
|
||||
<!-- Title shown on the confirmation screen after successful gesture. [CHAR LIMIT=30] -->
|
||||
<string name="gesture_tutorial_confirm_title" translatable="false">All set</string>
|
||||
<!-- Button text shown on a button on the confirm screen to leave the tutorial. [CHAR LIMIT=14] -->
|
||||
<string name="gesture_tutorial_action_button_label_done" translatable="false">Done</string>
|
||||
<!-- Button text shown on a button to go to Settings. [CHAR LIMIT=14] -->
|
||||
<string name="gesture_tutorial_action_button_label_settings" translatable="false">Settings</string>
|
||||
|
||||
<!-- ******* Overview ******* -->
|
||||
<!-- Label for a button that causes the current overview app to be shared. [CHAR_LIMIT=40] -->
|
||||
<string name="action_share">Share</string>
|
||||
<!-- Label for a button that causes a screen shot of the current app to be taken. [CHAR_LIMIT=40] -->
|
||||
<string name="action_screenshot">Screenshot</string>
|
||||
<!-- Message shown when an action is blocked by a policy enforced by the app or the organization managing the device. [CHAR_LIMIT=NONE] -->
|
||||
<string name="blocked_by_policy">This action isn\'t allowed by the app or your organization</string>
|
||||
</resources>
|
||||
|
|
|
@ -79,8 +79,8 @@
|
|||
|
||||
<style name="OverviewActionButton"
|
||||
parent="@android:style/Widget.DeviceDefault.Button.Borderless">
|
||||
<item name="android:textColor">?attr/workspaceTextColor</item>
|
||||
<item name="android:drawableTint">?attr/workspaceTextColor</item>
|
||||
<item name="android:textColor">@color/overview_button</item>
|
||||
<item name="android:drawableTint">@color/overview_button</item>
|
||||
<item name="android:tint">?attr/workspaceTextColor</item>
|
||||
<item name="android:drawablePadding">4dp</item>
|
||||
<item name="android:textAllCaps">false</item>
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static com.android.launcher3.util.LauncherUIHelper.doLayout;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.Config;
|
||||
|
||||
import com.android.quickstep.fallback.FallbackRecentsView;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.android.controller.ActivityController;
|
||||
import org.robolectric.annotation.LooperMode;
|
||||
import org.robolectric.annotation.LooperMode.Mode;
|
||||
import org.robolectric.shadows.ShadowLooper;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@LooperMode(Mode.PAUSED)
|
||||
public class RecentsActivityTest {
|
||||
|
||||
@Test
|
||||
public void testRecentsActivityCreates() {
|
||||
ActivityController<RecentsActivity> controller =
|
||||
Robolectric.buildActivity(RecentsActivity.class);
|
||||
|
||||
RecentsActivity launcher = controller.setup().get();
|
||||
doLayout(launcher);
|
||||
|
||||
// TODO: Ensure that LauncherAppState is not created
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRecets_showCurrentTask() {
|
||||
ActivityController<RecentsActivity> controller =
|
||||
Robolectric.buildActivity(RecentsActivity.class);
|
||||
|
||||
RecentsActivity activity = controller.setup().get();
|
||||
doLayout(activity);
|
||||
|
||||
FallbackRecentsView frv = activity.getOverviewPanel();
|
||||
frv.showCurrentTask(22);
|
||||
doLayout(activity);
|
||||
|
||||
ThumbnailData thumbnailData = new ThumbnailData();
|
||||
ReflectionHelpers.setField(thumbnailData, "thumbnail",
|
||||
Bitmap.createBitmap(300, 500, Config.ARGB_8888));
|
||||
frv.switchToScreenshot(thumbnailData, () -> { });
|
||||
ShadowLooper.idleMainLooper();
|
||||
}
|
||||
}
|
|
@ -30,7 +30,6 @@ import android.content.SharedPreferences;
|
|||
import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
|
||||
import com.android.launcher3.LauncherStateManager.StateHandler;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.model.WellbeingModel;
|
||||
import com.android.launcher3.popup.SystemShortcut;
|
||||
|
@ -38,6 +37,7 @@ import com.android.launcher3.proxy.ProxyActivityStarter;
|
|||
import com.android.launcher3.proxy.StartActivityParams;
|
||||
import com.android.launcher3.statehandlers.BackButtonAlphaHandler;
|
||||
import com.android.launcher3.statehandlers.DepthController;
|
||||
import com.android.launcher3.statemanager.StateManager.StateHandler;
|
||||
import com.android.launcher3.uioverrides.RecentsViewStateController;
|
||||
import com.android.launcher3.util.OnboardingPrefs;
|
||||
import com.android.launcher3.util.UiThreadHelper;
|
||||
|
@ -92,6 +92,9 @@ public abstract class BaseQuickstepLauncher extends Launcher
|
|||
@Override
|
||||
public void onNavigationModeChanged(Mode newMode) {
|
||||
getDragLayer().recreateControllers();
|
||||
if (mActionsView != null && isOverviewActionsEnabled()) {
|
||||
mActionsView.updateVerticalMarginForNavModeChange(newMode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -150,6 +153,7 @@ public abstract class BaseQuickstepLauncher extends Launcher
|
|||
|
||||
@Override
|
||||
protected void onDeferredResumed() {
|
||||
super.onDeferredResumed();
|
||||
if (mPendingActivityRequestCode != -1 && isInState(NORMAL)) {
|
||||
// Remove any active ProxyActivityStarter task and send RESULT_CANCELED to Launcher.
|
||||
onActivityResult(mPendingActivityRequestCode, RESULT_CANCELED, null);
|
||||
|
@ -167,13 +171,18 @@ public abstract class BaseQuickstepLauncher extends Launcher
|
|||
mActionsView = findViewById(R.id.overview_actions_view);
|
||||
((RecentsView) getOverviewPanel()).init(mActionsView);
|
||||
|
||||
if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(this)) {
|
||||
if (isOverviewActionsEnabled()) {
|
||||
// Overview is above all other launcher elements, including qsb, so move it to the top.
|
||||
getOverviewPanel().bringToFront();
|
||||
mActionsView.bringToFront();
|
||||
mActionsView.updateVerticalMarginForNavModeChange(SysUINavigationMode.getMode(this));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isOverviewActionsEnabled() {
|
||||
return FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(this);
|
||||
}
|
||||
|
||||
public <T extends OverviewActionsView> T getActionsView() {
|
||||
return (T) mActionsView;
|
||||
}
|
||||
|
@ -186,7 +195,7 @@ public abstract class BaseQuickstepLauncher extends Launcher
|
|||
}
|
||||
|
||||
@Override
|
||||
protected StateHandler[] createStateHandlers() {
|
||||
protected StateHandler<LauncherState>[] createStateHandlers() {
|
||||
return new StateHandler[] {
|
||||
getAllAppsController(),
|
||||
getWorkspace(),
|
||||
|
@ -200,9 +209,8 @@ public abstract class BaseQuickstepLauncher extends Launcher
|
|||
}
|
||||
|
||||
@Override
|
||||
protected OnboardingPrefs createOnboardingPrefs(SharedPreferences sharedPrefs,
|
||||
LauncherStateManager stateManager) {
|
||||
return new QuickstepOnboardingPrefs(this, sharedPrefs, stateManager);
|
||||
protected OnboardingPrefs createOnboardingPrefs(SharedPreferences sharedPrefs) {
|
||||
return new QuickstepOnboardingPrefs(this, sharedPrefs);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,14 +16,13 @@
|
|||
|
||||
package com.android.launcher3.statehandlers;
|
||||
|
||||
import static com.android.launcher3.LauncherState.FLAG_HIDE_BACK_BUTTON;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.quickstep.AnimatedFloat.VALUE;
|
||||
|
||||
import com.android.launcher3.BaseQuickstepLauncher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.statemanager.StateManager.StateHandler;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.util.UiThreadHelper;
|
||||
import com.android.quickstep.AnimatedFloat;
|
||||
|
@ -33,7 +32,7 @@ import com.android.quickstep.SystemUiProxy;
|
|||
/**
|
||||
* State handler for animating back button alpha
|
||||
*/
|
||||
public class BackButtonAlphaHandler implements LauncherStateManager.StateHandler {
|
||||
public class BackButtonAlphaHandler implements StateHandler<LauncherState> {
|
||||
|
||||
private final BaseQuickstepLauncher mLauncher;
|
||||
private final AnimatedFloat mBackAlpha = new AnimatedFloat(this::updateBackAlpha);
|
||||
|
|
|
@ -26,10 +26,10 @@ import android.view.ViewTreeObserver;
|
|||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.statemanager.StateManager.StateHandler;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
import com.android.systemui.shared.system.SurfaceControlCompat;
|
||||
|
@ -39,7 +39,7 @@ import com.android.systemui.shared.system.WallpaperManagerCompat;
|
|||
/**
|
||||
* Controls blur and wallpaper zoom, for the Launcher surface only.
|
||||
*/
|
||||
public class DepthController implements LauncherStateManager.StateHandler {
|
||||
public class DepthController implements StateHandler<LauncherState> {
|
||||
|
||||
public static final FloatProperty<DepthController> DEPTH =
|
||||
new FloatProperty<DepthController>("depth") {
|
||||
|
|
|
@ -36,9 +36,9 @@ import androidx.annotation.NonNull;
|
|||
|
||||
import com.android.launcher3.BaseQuickstepLauncher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager.StateHandler;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.graphics.OverviewScrim;
|
||||
import com.android.launcher3.statemanager.StateManager.StateHandler;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
||||
|
@ -49,7 +49,7 @@ import com.android.quickstep.views.RecentsView;
|
|||
* @param <T> the recents view
|
||||
*/
|
||||
public abstract class BaseRecentsViewStateController<T extends RecentsView>
|
||||
implements StateHandler {
|
||||
implements StateHandler<LauncherState> {
|
||||
protected final T mRecentsView;
|
||||
protected final BaseQuickstepLauncher mLauncher;
|
||||
|
||||
|
|
|
@ -18,14 +18,11 @@ package com.android.quickstep;
|
|||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Build;
|
||||
import android.util.Pair;
|
||||
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;
|
||||
|
||||
|
@ -33,7 +30,6 @@ import com.android.launcher3.BaseDraggingActivity;
|
|||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.statehandlers.DepthController;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.quickstep.util.ActivityInitListener;
|
||||
import com.android.quickstep.util.ShelfPeekAnim;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
|
@ -52,24 +48,13 @@ public interface BaseActivityInterface<T extends BaseDraggingActivity> {
|
|||
|
||||
int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect);
|
||||
|
||||
/**
|
||||
* @return The progress of the swipe where we start resisting the user, where 0 is fullscreen
|
||||
* and 1 is recents. These values should probably be greater than 1 to let the user swipe past
|
||||
* recents before we start resisting them.
|
||||
*/
|
||||
default Pair<Float, Float> getSwipeUpPullbackStartAndMaxProgress() {
|
||||
return new Pair<>(1.4f, 1.8f);
|
||||
}
|
||||
|
||||
void onSwipeUpToRecentsComplete();
|
||||
|
||||
default void onSwipeUpToHomeComplete() { }
|
||||
void onAssistantVisibilityChanged(float visibility);
|
||||
|
||||
@NonNull HomeAnimationFactory prepareHomeUI();
|
||||
|
||||
AnimationFactory prepareRecentsUI(boolean activityVisible, boolean animateActivity,
|
||||
Consumer<AnimatorPlaybackController> callback);
|
||||
AnimationFactory prepareRecentsUI(
|
||||
boolean activityVisible, Consumer<AnimatorPlaybackController> callback);
|
||||
|
||||
ActivityInitListener createActivityInitListener(Predicate<Boolean> onInitListener);
|
||||
|
||||
|
@ -152,35 +137,4 @@ public interface BaseActivityInterface<T extends BaseDraggingActivity> {
|
|||
*/
|
||||
default void setRecentsAttachedToAppWindow(boolean attached, boolean animate) { }
|
||||
}
|
||||
|
||||
interface HomeAnimationFactory {
|
||||
|
||||
/** Return the floating view that will animate in sync with the closing window. */
|
||||
default @Nullable View getFloatingView() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NonNull RectF getWindowTargetRect();
|
||||
|
||||
@NonNull AnimatorPlaybackController createActivityAnimationToHome();
|
||||
|
||||
default void playAtomicAnimation(float velocity) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
static RectF getDefaultWindowTargetRect(PagedOrientationHandler orientationHandler,
|
||||
DeviceProfile dp) {
|
||||
final int halfIconSize = dp.iconSizePx / 2;
|
||||
float primaryDimension = orientationHandler
|
||||
.getPrimaryValue(dp.availableWidthPx, dp.availableHeightPx);
|
||||
float secondaryDimension = orientationHandler
|
||||
.getSecondaryValue(dp.availableWidthPx, dp.availableHeightPx);
|
||||
final float targetX = primaryDimension / 2f;
|
||||
final float targetY = secondaryDimension - dp.hotseatBarSizePx;
|
||||
// Fallback to animate to center of screen.
|
||||
return new RectF(targetX - halfIconSize, targetY - halfIconSize,
|
||||
targetX + halfIconSize, targetY + halfIconSize);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,168 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
|
||||
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.util.ActivityTracker;
|
||||
import com.android.launcher3.util.SystemUiController;
|
||||
import com.android.launcher3.util.Themes;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* A base fallback recents activity that provides support for device profile changes, activity
|
||||
* lifecycle tracking, and basic input handling from recents.
|
||||
*
|
||||
* This class is only used as a fallback in case the default launcher does not have a recents
|
||||
* implementation.
|
||||
*/
|
||||
public abstract class BaseRecentsActivity extends BaseDraggingActivity {
|
||||
|
||||
public static final ActivityTracker<BaseRecentsActivity> ACTIVITY_TRACKER =
|
||||
new ActivityTracker<>();
|
||||
private Configuration mOldConfig;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mOldConfig = new Configuration(getResources().getConfiguration());
|
||||
initDeviceProfile();
|
||||
initViews();
|
||||
|
||||
getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW,
|
||||
Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText));
|
||||
ACTIVITY_TRACKER.handleCreate(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init drag layer and overview panel views.
|
||||
*/
|
||||
abstract protected void initViews();
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
int diff = newConfig.diff(mOldConfig);
|
||||
if ((diff & (CONFIG_ORIENTATION | CONFIG_SCREEN_SIZE)) != 0) {
|
||||
onHandleConfigChanged();
|
||||
}
|
||||
mOldConfig.setTo(newConfig);
|
||||
super.onConfigurationChanged(newConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logic for when device configuration changes (rotation, screen size change, multi-window,
|
||||
* etc.)
|
||||
*/
|
||||
protected void onHandleConfigChanged() {
|
||||
mUserEventDispatcher = null;
|
||||
initDeviceProfile();
|
||||
|
||||
AbstractFloatingView.closeOpenViews(this, true,
|
||||
AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
|
||||
dispatchDeviceProfileChanged();
|
||||
|
||||
reapplyUi();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize/update the device profile.
|
||||
*/
|
||||
private void initDeviceProfile() {
|
||||
mDeviceProfile = createDeviceProfile();
|
||||
onDeviceProfileInitiated();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the device profile to use in this activity.
|
||||
* @return device profile
|
||||
*/
|
||||
protected DeviceProfile createDeviceProfile() {
|
||||
DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(this).getDeviceProfile(this);
|
||||
|
||||
// In case we are reusing IDP, create a copy so that we don't conflict with Launcher
|
||||
// activity.
|
||||
return dp.copy(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
|
||||
// Workaround for b/78520668, explicitly trim memory once UI is hidden
|
||||
onTrimMemory(TRIM_MEMORY_UI_HIDDEN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnterAnimationComplete() {
|
||||
super.onEnterAnimationComplete();
|
||||
// After the transition to home, enable the high-res thumbnail loader if it wasn't enabled
|
||||
// as a part of quickstep, so that high-res thumbnails can load the next time we enter
|
||||
// overview
|
||||
RecentsModel.INSTANCE.get(this).getThumbnailCache()
|
||||
.getHighResLoadingState().setVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrimMemory(int level) {
|
||||
super.onTrimMemory(level);
|
||||
RecentsModel.INSTANCE.get(this).onTrimMemory(level);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
ACTIVITY_TRACKER.handleNewIntent(this, intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
ACTIVITY_TRACKER.onActivityDestroyed(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
// TODO: Launch the task we came from
|
||||
startHome();
|
||||
}
|
||||
|
||||
public void startHome() {
|
||||
startActivity(new Intent(Intent.ACTION_MAIN)
|
||||
.addCategory(Intent.CATEGORY_HOME)
|
||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
|
||||
super.dump(prefix, fd, writer, args);
|
||||
writer.println(prefix + "Misc:");
|
||||
dumpMisc(prefix + "\t", writer);
|
||||
}
|
||||
}
|
|
@ -110,10 +110,6 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
|||
public static final int STATE_RECENTS_SCROLLING_FINISHED =
|
||||
getFlagForIndex("STATE_RECENTS_SCROLLING_FINISHED");
|
||||
|
||||
// Called when the new task appeared from quick switching.
|
||||
public static final int STATE_TASK_APPEARED_DURING_SWITCH =
|
||||
getFlagForIndex("STATE_TASK_APPEARED_DURING_SWITCH");
|
||||
|
||||
// Needed to interact with the current activity
|
||||
private final Intent mHomeIntent;
|
||||
private final Intent mOverviewIntent;
|
||||
|
@ -123,9 +119,8 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
|||
|
||||
private ActivityManager.RunningTaskInfo mRunningTask;
|
||||
private GestureEndTarget mEndTarget;
|
||||
private RemoteAnimationTargetCompat mAnimationTarget;
|
||||
// TODO: This can be removed once we stop finishing the animation when starting a new task
|
||||
private int mFinishingRecentsAnimationTaskId = -1;
|
||||
private RemoteAnimationTargetCompat mLastAppearedTaskTarget;
|
||||
private int mLastStartedTaskId = -1;
|
||||
|
||||
public GestureState(OverviewComponentObserver componentObserver, int gestureId) {
|
||||
mHomeIntent = componentObserver.getHomeIntent();
|
||||
|
@ -143,7 +138,8 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
|||
mGestureId = other.mGestureId;
|
||||
mRunningTask = other.mRunningTask;
|
||||
mEndTarget = other.mEndTarget;
|
||||
mFinishingRecentsAnimationTaskId = other.mFinishingRecentsAnimationTaskId;
|
||||
mLastAppearedTaskTarget = other.mLastAppearedTaskTarget;
|
||||
mLastStartedTaskId = other.mLastStartedTaskId;
|
||||
}
|
||||
|
||||
public GestureState() {
|
||||
|
@ -225,6 +221,35 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
|||
mRunningTask = runningTask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the last task that appeared during this gesture.
|
||||
*/
|
||||
public void updateLastAppearedTaskTarget(RemoteAnimationTargetCompat lastAppearedTaskTarget) {
|
||||
mLastAppearedTaskTarget = lastAppearedTaskTarget;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The id of the task that appeared during this gesture.
|
||||
*/
|
||||
public int getLastAppearedTaskId() {
|
||||
return mLastAppearedTaskTarget != null ? mLastAppearedTaskTarget.taskId : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the last task that we started via startActivityFromRecents() during this gesture.
|
||||
*/
|
||||
public void updateLastStartedTaskId(int lastStartedTaskId) {
|
||||
mLastStartedTaskId = lastStartedTaskId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The id of the task that was most recently started during this gesture, or -1 if
|
||||
* no task has been started yet (i.e. we haven't settled on a new task).
|
||||
*/
|
||||
public int getLastStartedTaskId() {
|
||||
return mLastStartedTaskId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the end target for this gesture (if known).
|
||||
*/
|
||||
|
@ -232,14 +257,6 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
|||
return mEndTarget;
|
||||
}
|
||||
|
||||
public void setAnimationTarget(RemoteAnimationTargetCompat target) {
|
||||
mAnimationTarget = target;
|
||||
}
|
||||
|
||||
public RemoteAnimationTargetCompat getAnimationTarget() {
|
||||
return mAnimationTarget;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the end target of this gesture and immediately notifies the state changes.
|
||||
*/
|
||||
|
@ -259,30 +276,9 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the id for the task that was about to be launched following the finish of the recents
|
||||
* animation. Only defined between when the finish-recents call was made and the launch
|
||||
* activity call is made.
|
||||
*/
|
||||
public int getFinishingRecentsAnimationTaskId() {
|
||||
return mFinishingRecentsAnimationTaskId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the id for the task will be launched after the recents animation is finished. Once the
|
||||
* animation has finished then the id will be reset to -1.
|
||||
*/
|
||||
public void setFinishingRecentsAnimationTaskId(int taskId) {
|
||||
mFinishingRecentsAnimationTaskId = taskId;
|
||||
mStateCallback.runOnceAtState(STATE_RECENTS_ANIMATION_FINISHED, () -> {
|
||||
mFinishingRecentsAnimationTaskId = -1;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether the current gesture is still running a recents animation to a state in the
|
||||
* Launcher or Recents activity.
|
||||
* Updates the running task for the gesture to be the given {@param runningTask}.
|
||||
*/
|
||||
public boolean isRunningAnimationToLauncher() {
|
||||
return isRecentsAnimationRunning() && mEndTarget != null && mEndTarget.isLauncher;
|
||||
|
@ -314,18 +310,13 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
|||
mStateCallback.setState(STATE_RECENTS_ANIMATION_ENDED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskAppeared(RemoteAnimationTargetCompat app) {
|
||||
mAnimationTarget = app;
|
||||
mStateCallback.setState(STATE_TASK_APPEARED_DURING_SWITCH);
|
||||
}
|
||||
|
||||
public void dump(PrintWriter pw) {
|
||||
pw.println("GestureState:");
|
||||
pw.println(" gestureID=" + mGestureId);
|
||||
pw.println(" runningTask=" + mRunningTask);
|
||||
pw.println(" endTarget=" + mEndTarget);
|
||||
pw.println(" finishingRecentsAnimationTaskId=" + mFinishingRecentsAnimationTaskId);
|
||||
pw.println(" lastAppearedTaskTarget=" + mLastAppearedTaskTarget);
|
||||
pw.println(" lastStartedTaskId=" + mLastStartedTaskId);
|
||||
pw.println(" isRecentsAnimationRunning=" + isRecentsAnimationRunning());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,8 +154,7 @@ public class RecentTasksList extends TaskStackChangeListener {
|
|||
* Loads and creates a list of all the recent tasks.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
ArrayList<Task> loadTasksInBackground(int numTasks,
|
||||
boolean loadKeysOnly) {
|
||||
ArrayList<Task> loadTasksInBackground(int numTasks, boolean loadKeysOnly) {
|
||||
int currentUserId = Process.myUserHandle().getIdentifier();
|
||||
ArrayList<Task> allTasks = new ArrayList<>();
|
||||
List<ActivityManager.RecentTaskInfo> rawTasks =
|
||||
|
@ -174,9 +173,7 @@ public class RecentTasksList extends TaskStackChangeListener {
|
|||
}
|
||||
};
|
||||
|
||||
int taskCount = rawTasks.size();
|
||||
for (int i = 0; i < taskCount; i++) {
|
||||
ActivityManager.RecentTaskInfo rawTask = rawTasks.get(i);
|
||||
for (ActivityManager.RecentTaskInfo rawTask : rawTasks) {
|
||||
Task.TaskKey taskKey = new Task.TaskKey(rawTask);
|
||||
Task task;
|
||||
if (!loadKeysOnly) {
|
||||
|
|
|
@ -159,6 +159,6 @@ public class RecentsAnimationCallbacks implements
|
|||
/**
|
||||
* Callback made when a task started from the recents is ready for an app transition.
|
||||
*/
|
||||
default void onTaskAppeared(RemoteAnimationTargetCompat app) {}
|
||||
default void onTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package com.android.quickstep;
|
|||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_INITIALIZED;
|
||||
import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_STARTED;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
@ -28,6 +29,7 @@ import com.android.launcher3.Utilities;
|
|||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
|
||||
public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAnimationListener {
|
||||
|
||||
|
@ -36,6 +38,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
|||
private RecentsAnimationTargets mTargets;
|
||||
// Temporary until we can hook into gesture state events
|
||||
private GestureState mLastGestureState;
|
||||
private RemoteAnimationTargetCompat mLastAppearedTaskTarget;
|
||||
|
||||
/**
|
||||
* Preloads the recents animation.
|
||||
|
@ -79,6 +82,8 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
|||
}
|
||||
mController = controller;
|
||||
mTargets = targets;
|
||||
mLastAppearedTaskTarget = mTargets.findTask(mLastGestureState.getRunningTaskId());
|
||||
mLastGestureState.updateLastAppearedTaskTarget(mLastAppearedTaskTarget);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -96,6 +101,20 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
|||
public void onRecentsAnimationFinished(RecentsAnimationController controller) {
|
||||
cleanUpRecentsAnimation(null /* canceledThumbnail */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {
|
||||
if (mController != null) {
|
||||
if (mLastAppearedTaskTarget == null
|
||||
|| appearedTaskTarget.taskId != mLastAppearedTaskTarget.taskId) {
|
||||
if (mLastAppearedTaskTarget != null) {
|
||||
mController.removeTaskTarget(mLastAppearedTaskTarget);
|
||||
}
|
||||
mLastAppearedTaskTarget = appearedTaskTarget;
|
||||
mLastGestureState.updateLastAppearedTaskTarget(mLastAppearedTaskTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
mCallbacks.addListener(gestureState);
|
||||
mCallbacks.addListener(listener);
|
||||
|
@ -112,6 +131,9 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
|||
mCallbacks.removeListener(mLastGestureState);
|
||||
mLastGestureState = gestureState;
|
||||
mCallbacks.addListener(gestureState);
|
||||
gestureState.setState(STATE_RECENTS_ANIMATION_INITIALIZED
|
||||
| STATE_RECENTS_ANIMATION_STARTED);
|
||||
gestureState.updateLastAppearedTaskTarget(mLastAppearedTaskTarget);
|
||||
return mCallbacks;
|
||||
}
|
||||
|
||||
|
@ -171,6 +193,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
|||
mCallbacks = null;
|
||||
mTargets = null;
|
||||
mLastGestureState = null;
|
||||
mLastAppearedTaskTarget = null;
|
||||
}
|
||||
|
||||
public void dump() {
|
||||
|
|
|
@ -68,7 +68,7 @@ final class BackGestureTutorialController extends TutorialController {
|
|||
@Override
|
||||
Integer getActionButtonStringId() {
|
||||
if (mTutorialType == BACK_NAVIGATION_COMPLETE) {
|
||||
return R.string.gesture_tutorial_action_button_label;
|
||||
return R.string.gesture_tutorial_action_button_label_done;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ final class BackGestureTutorialController extends TutorialController {
|
|||
@Override
|
||||
Integer getActionTextButtonStringId() {
|
||||
if (mTutorialType == BACK_NAVIGATION_COMPLETE) {
|
||||
return R.string.gesture_tutorial_action_text_button_label;
|
||||
return R.string.gesture_tutorial_action_button_label_settings;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -89,7 +89,6 @@ final class BackGestureTutorialController extends TutorialController {
|
|||
@Override
|
||||
void onActionTextButtonClicked(View button) {
|
||||
mTutorialFragment.startSystemNavigationSetting();
|
||||
mTutorialFragment.closeTutorial();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -60,7 +60,7 @@ final class HomeGestureTutorialController extends TutorialController {
|
|||
@Override
|
||||
Integer getActionButtonStringId() {
|
||||
if (mTutorialType == HOME_NAVIGATION_COMPLETE) {
|
||||
return R.string.gesture_tutorial_action_button_label;
|
||||
return R.string.gesture_tutorial_action_button_label_done;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package com.android.quickstep.interaction;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Insets;
|
||||
import android.os.Bundle;
|
||||
|
@ -35,8 +34,6 @@ import androidx.fragment.app.FragmentActivity;
|
|||
import com.android.launcher3.R;
|
||||
import com.android.quickstep.interaction.TutorialController.TutorialType;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
abstract class TutorialFragment extends Fragment implements OnTouchListener {
|
||||
|
||||
private static final String LOG_TAG = "TutorialFragment";
|
||||
|
@ -182,14 +179,6 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
|
|||
}
|
||||
|
||||
void startSystemNavigationSetting() {
|
||||
try {
|
||||
startActivityForResult(
|
||||
Intent.parseUri(SYSTEM_NAVIGATION_SETTING_INTENT, /* flags= */ 0),
|
||||
/* requestCode= */ 0);
|
||||
} catch (URISyntaxException e) {
|
||||
Log.e(LOG_TAG, "The launch Intent Uri is wrong syntax: " + e);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Log.e(LOG_TAG, "The launch Activity not found: " + e);
|
||||
}
|
||||
startActivity(new Intent("com.android.settings.GESTURE_NAVIGATION_SETTINGS"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,17 +16,17 @@
|
|||
|
||||
package com.android.quickstep.logging;
|
||||
|
||||
import static android.stats.launcher.nano.Launcher.ALLAPPS;
|
||||
import static android.stats.launcher.nano.Launcher.BACKGROUND;
|
||||
import static android.stats.launcher.nano.Launcher.HOME;
|
||||
import static android.stats.launcher.nano.Launcher.OVERVIEW;
|
||||
import static com.android.launcher3.logger.LauncherAtom.ContainerInfo.ContainerCase.FOLDER;
|
||||
import static com.android.launcher3.logger.LauncherAtom.ItemInfo.ItemCase.WIDGET;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.logger.LauncherAtom;
|
||||
import com.android.launcher3.logging.InstanceId;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.logging.StatsLogUtils;
|
||||
import com.android.launcher3.model.AllAppsList;
|
||||
import com.android.launcher3.model.BaseModelUpdateTask;
|
||||
import com.android.launcher3.model.BgDataModel;
|
||||
|
@ -34,11 +34,13 @@ import com.android.launcher3.model.data.FolderInfo;
|
|||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.util.IntSparseArrayMap;
|
||||
import com.android.launcher3.util.LogConfig;
|
||||
import com.android.systemui.shared.system.SysUiStatsLog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* This method calls the StatsLog hidden method until they are made available public.
|
||||
* This class calls StatsLog compile time generated methods.
|
||||
*
|
||||
* To see if the logs are properly sent to statsd, execute following command.
|
||||
* $ adb root && adb shell statsd
|
||||
|
@ -47,29 +49,69 @@ import java.util.ArrayList;
|
|||
*/
|
||||
public class StatsLogCompatManager extends StatsLogManager {
|
||||
|
||||
private static final int SUPPORTED_TARGET_DEPTH = 2;
|
||||
private static final String TAG = "StatsLog";
|
||||
private static final boolean DEBUG = false;
|
||||
private static final boolean IS_VERBOSE = Utilities.isPropertyEnabled(LogConfig.STATSLOG);
|
||||
|
||||
private static Context sContext;
|
||||
|
||||
private static final int DEFAULT_WIDGET_SPAN_XY = 1;
|
||||
private static final int DEFAULT_WORKSPACE_GRID_XY = -1;
|
||||
private static final int DEFAULT_PAGE_INDEX = -2;
|
||||
private static final InstanceId DEFAULT_INSTANCE_ID = InstanceId.fakeInstanceId(0);
|
||||
|
||||
public StatsLogCompatManager(Context context) {
|
||||
sContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an event and accompanying {@link ItemInfo}
|
||||
*/
|
||||
public void log(LauncherEvent event, LauncherAtom.ItemInfo itemInfo) {
|
||||
log(event, DEFAULT_INSTANCE_ID, itemInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an event and accompanying {@link LauncherAtom.ItemInfo}
|
||||
*/
|
||||
@Override
|
||||
public void verify() {
|
||||
if (!(StatsLogUtils.LAUNCHER_STATE_ALLAPPS == ALLAPPS
|
||||
&& StatsLogUtils.LAUNCHER_STATE_BACKGROUND == BACKGROUND
|
||||
&& StatsLogUtils.LAUNCHER_STATE_OVERVIEW == OVERVIEW
|
||||
&& StatsLogUtils.LAUNCHER_STATE_HOME == HOME)) {
|
||||
throw new IllegalStateException(
|
||||
"StatsLogUtil constants doesn't match enums in launcher.proto");
|
||||
public void log(LauncherEvent event, InstanceId instanceId, LauncherAtom.ItemInfo itemInfo) {
|
||||
if (IS_VERBOSE) {
|
||||
Log.d(TAG, String.format("\n%s\n%s", event.name(), itemInfo));
|
||||
}
|
||||
if (!Utilities.ATLEAST_R) {
|
||||
return;
|
||||
}
|
||||
SysUiStatsLog.write(SysUiStatsLog.LAUNCHER_EVENT,
|
||||
SysUiStatsLog.LAUNCHER_UICHANGED__ACTION__DEFAULT_ACTION /* deprecated */,
|
||||
SysUiStatsLog.LAUNCHER_UICHANGED__DST_STATE__HOME /* TODO */,
|
||||
SysUiStatsLog.LAUNCHER_UICHANGED__DST_STATE__BACKGROUND /* TODO */,
|
||||
null /* launcher extensions, deprecated */,
|
||||
false /* quickstep_enabled, deprecated */,
|
||||
event.getId() /* event_id */,
|
||||
itemInfo.getItemCase().getNumber() /* target_id */,
|
||||
instanceId.getId() /* instance_id TODO */,
|
||||
0 /* uid TODO */,
|
||||
getPackageName(itemInfo) /* package_name */,
|
||||
getComponentName(itemInfo) /* component_name */,
|
||||
getGridX(itemInfo, false) /* grid_x */,
|
||||
getGridY(itemInfo, false) /* grid_y */,
|
||||
getPageId(itemInfo, false) /* page_id */,
|
||||
getGridX(itemInfo, true) /* grid_x_parent */,
|
||||
getGridY(itemInfo, true) /* grid_y_parent */,
|
||||
getPageId(itemInfo, true) /* page_id_parent */,
|
||||
getHierarchy(itemInfo) /* hierarchy */,
|
||||
itemInfo.getIsWork() /* is_work_profile */,
|
||||
itemInfo.getRank() /* rank */,
|
||||
0 /* fromState */,
|
||||
0 /* toState */,
|
||||
null /* edittext */,
|
||||
0 /* cardinality */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the workspace layout information on the model thread.
|
||||
*/
|
||||
@Override
|
||||
public void logSnapshot() {
|
||||
LauncherAppState.getInstance(sContext).getModel().enqueueModelUpdateTask(
|
||||
new SnapshotWorker());
|
||||
|
@ -84,18 +126,160 @@ public class StatsLogCompatManager extends StatsLogManager {
|
|||
|
||||
for (ItemInfo info : workspaceItems) {
|
||||
LauncherAtom.ItemInfo atomInfo = info.buildProto(null);
|
||||
// call StatsLog method
|
||||
writeSnapshot(atomInfo);
|
||||
}
|
||||
for (FolderInfo fInfo : folders) {
|
||||
for (ItemInfo info : fInfo.contents) {
|
||||
LauncherAtom.ItemInfo atomInfo = info.buildProto(fInfo);
|
||||
// call StatsLog method
|
||||
writeSnapshot(atomInfo);
|
||||
}
|
||||
}
|
||||
for (ItemInfo info : appWidgets) {
|
||||
LauncherAtom.ItemInfo atomInfo = info.buildProto(null);
|
||||
// call StatsLog method
|
||||
writeSnapshot(atomInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
private static void writeSnapshot(LauncherAtom.ItemInfo itemInfo) {
|
||||
if (IS_VERBOSE) {
|
||||
Log.d(TAG, "\nwriteSnapshot:" + itemInfo);
|
||||
}
|
||||
if (!Utilities.ATLEAST_R) {
|
||||
return;
|
||||
}
|
||||
SysUiStatsLog.write(SysUiStatsLog.LAUNCHER_SNAPSHOT,
|
||||
0 /* event_id */,
|
||||
itemInfo.getItemCase().getNumber() /* target_id */,
|
||||
0 /* instance_id */,
|
||||
0 /* uid */,
|
||||
getPackageName(itemInfo) /* package_name */,
|
||||
getComponentName(itemInfo) /* component_name */,
|
||||
getGridX(itemInfo, false) /* grid_x */,
|
||||
getGridY(itemInfo, false) /* grid_y */,
|
||||
getPageId(itemInfo, false) /* page_id */,
|
||||
getGridX(itemInfo, true) /* grid_x_parent */,
|
||||
getGridY(itemInfo, true) /* grid_y_parent */,
|
||||
getPageId(itemInfo, true) /* page_id_parent */,
|
||||
getHierarchy(itemInfo) /* hierarchy */,
|
||||
itemInfo.getIsWork() /* is_work_profile */,
|
||||
0 /* origin TODO */,
|
||||
0 /* cardinality */,
|
||||
getSpanX(itemInfo),
|
||||
getSpanY(itemInfo));
|
||||
}
|
||||
|
||||
private static int getSpanX(LauncherAtom.ItemInfo atomInfo) {
|
||||
if (atomInfo.getItemCase() != WIDGET) {
|
||||
return DEFAULT_WIDGET_SPAN_XY;
|
||||
}
|
||||
return atomInfo.getWidget().getSpanX();
|
||||
}
|
||||
|
||||
private static int getSpanY(LauncherAtom.ItemInfo atomInfo) {
|
||||
if (atomInfo.getItemCase() != WIDGET) {
|
||||
return DEFAULT_WIDGET_SPAN_XY;
|
||||
}
|
||||
return atomInfo.getWidget().getSpanY();
|
||||
}
|
||||
|
||||
private static String getPackageName(LauncherAtom.ItemInfo atomInfo) {
|
||||
switch (atomInfo.getItemCase()) {
|
||||
case APPLICATION:
|
||||
return atomInfo.getApplication().getPackageName();
|
||||
case SHORTCUT:
|
||||
return atomInfo.getShortcut().getShortcutName();
|
||||
case WIDGET:
|
||||
return atomInfo.getWidget().getPackageName();
|
||||
case TASK:
|
||||
return atomInfo.getTask().getPackageName();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String getComponentName(LauncherAtom.ItemInfo atomInfo) {
|
||||
switch (atomInfo.getItemCase()) {
|
||||
case APPLICATION:
|
||||
return atomInfo.getApplication().getComponentName();
|
||||
case SHORTCUT:
|
||||
return atomInfo.getShortcut().getShortcutName();
|
||||
case WIDGET:
|
||||
return atomInfo.getWidget().getComponentName();
|
||||
case TASK:
|
||||
return atomInfo.getTask().getComponentName();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static int getGridX(LauncherAtom.ItemInfo info, boolean parent) {
|
||||
switch (info.getContainerInfo().getContainerCase()) {
|
||||
case WORKSPACE:
|
||||
if (parent) {
|
||||
return DEFAULT_WORKSPACE_GRID_XY;
|
||||
} else {
|
||||
return info.getContainerInfo().getWorkspace().getGridX();
|
||||
}
|
||||
case FOLDER:
|
||||
if (parent) {
|
||||
switch (info.getContainerInfo().getFolder().getParentContainerCase()) {
|
||||
case WORKSPACE:
|
||||
return info.getContainerInfo().getFolder().getWorkspace().getGridX();
|
||||
default:
|
||||
return DEFAULT_WORKSPACE_GRID_XY;
|
||||
}
|
||||
} else {
|
||||
return info.getContainerInfo().getFolder().getGridX();
|
||||
}
|
||||
default:
|
||||
return DEFAULT_WORKSPACE_GRID_XY;
|
||||
}
|
||||
}
|
||||
|
||||
private static int getGridY(LauncherAtom.ItemInfo info, boolean parent) {
|
||||
switch (info.getContainerInfo().getContainerCase()) {
|
||||
case WORKSPACE:
|
||||
if (parent) {
|
||||
return DEFAULT_WORKSPACE_GRID_XY;
|
||||
} else {
|
||||
return info.getContainerInfo().getWorkspace().getGridY();
|
||||
}
|
||||
case FOLDER:
|
||||
if (parent) {
|
||||
switch (info.getContainerInfo().getFolder().getParentContainerCase()) {
|
||||
case WORKSPACE:
|
||||
return info.getContainerInfo().getFolder().getWorkspace().getGridY();
|
||||
default:
|
||||
return DEFAULT_WORKSPACE_GRID_XY;
|
||||
}
|
||||
} else {
|
||||
return info.getContainerInfo().getFolder().getGridY();
|
||||
}
|
||||
default:
|
||||
return DEFAULT_WORKSPACE_GRID_XY;
|
||||
}
|
||||
}
|
||||
|
||||
private static int getPageId(LauncherAtom.ItemInfo info, boolean parent) {
|
||||
switch (info.getContainerInfo().getContainerCase()) {
|
||||
case HOTSEAT:
|
||||
return info.getContainerInfo().getHotseat().getIndex();
|
||||
case WORKSPACE:
|
||||
return info.getContainerInfo().getWorkspace().getPageIndex();
|
||||
default:
|
||||
return DEFAULT_PAGE_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static int getHierarchy(LauncherAtom.ItemInfo info) {
|
||||
// TODO
|
||||
if (info.getContainerInfo().getContainerCase() == FOLDER) {
|
||||
return info.getContainerInfo().getFolder().getParentContainerCase().getNumber() + 100;
|
||||
} else {
|
||||
return info.getContainerInfo().getContainerCase().getNumber();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ import static com.android.quickstep.util.WindowSizeStrategy.LAUNCHER_ACTIVITY_SI
|
|||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
|
@ -66,4 +68,21 @@ public class LayoutUtils {
|
|||
return srcHeight / targetHeight;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively sets view and all children enabled/disabled.
|
||||
* @param viewGroup Top most parent view to change.
|
||||
* @param enabled True = enable, False = disable.
|
||||
*/
|
||||
public static void setViewEnabled(ViewGroup viewGroup, boolean enabled) {
|
||||
viewGroup.setEnabled(enabled);
|
||||
for (int i = 0; i < viewGroup.getChildCount(); i++) {
|
||||
View child = viewGroup.getChildAt(i);
|
||||
if (child instanceof ViewGroup) {
|
||||
setViewEnabled((ViewGroup) child, enabled);
|
||||
} else {
|
||||
child.setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,11 +19,13 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_LSQ_VELOCITY_PROV
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.launcher3.Alarm;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
|
||||
/**
|
||||
* Given positions along x- or y-axis, tracks velocity and acceleration and determines when there is
|
||||
|
@ -84,6 +86,9 @@ public class MotionPauseDetector {
|
|||
mSpeedSlow = res.getDimension(R.dimen.motion_pause_detector_speed_slow);
|
||||
mSpeedSomewhatFast = res.getDimension(R.dimen.motion_pause_detector_speed_somewhat_fast);
|
||||
mSpeedFast = res.getDimension(R.dimen.motion_pause_detector_speed_fast);
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "creating alarm");
|
||||
}
|
||||
mForcePauseTimeout = new Alarm();
|
||||
mForcePauseTimeout.setOnAlarmListener(alarm -> updatePaused(true /* isPaused */));
|
||||
mMakePauseHarderToTrigger = makePauseHarderToTrigger;
|
||||
|
@ -120,6 +125,9 @@ public class MotionPauseDetector {
|
|||
* @param pointerIndex Index for the pointer being tracked in the motion event
|
||||
*/
|
||||
public void addPosition(MotionEvent ev, int pointerIndex) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "setting alarm");
|
||||
}
|
||||
mForcePauseTimeout.setAlarm(mMakePauseHarderToTrigger
|
||||
? HARDER_TRIGGER_TIMEOUT
|
||||
: FORCE_PAUSE_TIMEOUT);
|
||||
|
@ -167,6 +175,9 @@ public class MotionPauseDetector {
|
|||
}
|
||||
|
||||
private void updatePaused(boolean isPaused) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "updatePaused: " + isPaused);
|
||||
}
|
||||
if (mDisallowPause) {
|
||||
isPaused = false;
|
||||
}
|
||||
|
@ -188,6 +199,9 @@ public class MotionPauseDetector {
|
|||
setOnMotionPauseListener(null);
|
||||
mIsPaused = mHasEverBeenPaused = false;
|
||||
mSlowStartTime = 0;
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "canceling alarm");
|
||||
}
|
||||
mForcePauseTimeout.cancelAlarm();
|
||||
}
|
||||
|
||||
|
|
|
@ -25,8 +25,8 @@ import android.content.SharedPreferences;
|
|||
|
||||
import com.android.launcher3.BaseQuickstepLauncher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager;
|
||||
import com.android.launcher3.LauncherStateManager.StateListener;
|
||||
import com.android.launcher3.statemanager.StateManager;
|
||||
import com.android.launcher3.statemanager.StateManager.StateListener;
|
||||
import com.android.launcher3.util.OnboardingPrefs;
|
||||
import com.android.quickstep.SysUINavigationMode;
|
||||
|
||||
|
@ -35,23 +35,23 @@ import com.android.quickstep.SysUINavigationMode;
|
|||
*/
|
||||
public class QuickstepOnboardingPrefs extends OnboardingPrefs<BaseQuickstepLauncher> {
|
||||
|
||||
public QuickstepOnboardingPrefs(BaseQuickstepLauncher launcher, SharedPreferences sharedPrefs,
|
||||
LauncherStateManager stateManager) {
|
||||
super(launcher, sharedPrefs, stateManager);
|
||||
public QuickstepOnboardingPrefs(BaseQuickstepLauncher launcher, SharedPreferences sharedPrefs) {
|
||||
super(launcher, sharedPrefs);
|
||||
|
||||
StateManager<LauncherState> stateManager = launcher.getStateManager();
|
||||
if (!getBoolean(HOME_BOUNCE_SEEN)) {
|
||||
mStateManager.addStateListener(new StateListener() {
|
||||
stateManager.addStateListener(new StateListener<LauncherState>() {
|
||||
@Override
|
||||
public void onStateTransitionComplete(LauncherState finalState) {
|
||||
boolean swipeUpEnabled = SysUINavigationMode.INSTANCE
|
||||
.get(mLauncher).getMode().hasGestures;
|
||||
LauncherState prevState = mStateManager.getLastState();
|
||||
LauncherState prevState = stateManager.getLastState();
|
||||
|
||||
if (((swipeUpEnabled && finalState == OVERVIEW) || (!swipeUpEnabled
|
||||
&& finalState == ALL_APPS && prevState == NORMAL) ||
|
||||
hasReachedMaxCount(HOME_BOUNCE_COUNT))) {
|
||||
mSharedPrefs.edit().putBoolean(HOME_BOUNCE_SEEN, true).apply();
|
||||
mStateManager.removeStateListener(this);
|
||||
stateManager.removeStateListener(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -65,27 +65,27 @@ public class QuickstepOnboardingPrefs extends OnboardingPrefs<BaseQuickstepLaunc
|
|||
mSharedPrefs.edit().putBoolean(SHELF_BOUNCE_SEEN, shelfBounceSeen).apply();
|
||||
}
|
||||
if (!shelfBounceSeen) {
|
||||
mStateManager.addStateListener(new StateListener() {
|
||||
stateManager.addStateListener(new StateListener<LauncherState>() {
|
||||
@Override
|
||||
public void onStateTransitionComplete(LauncherState finalState) {
|
||||
LauncherState prevState = mStateManager.getLastState();
|
||||
LauncherState prevState = stateManager.getLastState();
|
||||
|
||||
if ((finalState == ALL_APPS && prevState == OVERVIEW) ||
|
||||
hasReachedMaxCount(SHELF_BOUNCE_COUNT)) {
|
||||
mSharedPrefs.edit().putBoolean(SHELF_BOUNCE_SEEN, true).apply();
|
||||
mStateManager.removeStateListener(this);
|
||||
stateManager.removeStateListener(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!hasReachedMaxCount(ALL_APPS_COUNT)) {
|
||||
mStateManager.addStateListener(new StateListener() {
|
||||
stateManager.addStateListener(new StateListener<LauncherState>() {
|
||||
@Override
|
||||
public void onStateTransitionComplete(LauncherState finalState) {
|
||||
if (finalState == ALL_APPS) {
|
||||
if (incrementEventCount(ALL_APPS_COUNT)) {
|
||||
mStateManager.removeStateListener(this);
|
||||
stateManager.removeStateListener(this);
|
||||
mLauncher.getScrimView().updateDragHandleVisibility();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import static android.view.Surface.ROTATION_180;
|
|||
import static android.view.Surface.ROTATION_270;
|
||||
import static android.view.Surface.ROTATION_90;
|
||||
|
||||
import static com.android.launcher3.logging.LoggerUtils.extractObjectNameAndAddress;
|
||||
import static com.android.launcher3.states.RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY;
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
|
||||
|
@ -36,7 +37,6 @@ import android.database.ContentObserver;
|
|||
import android.graphics.Matrix;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Handler;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
|
@ -51,6 +51,7 @@ import com.android.launcher3.DeviceProfile;
|
|||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.launcher3.util.WindowBounds;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.util.function.IntConsumer;
|
||||
|
@ -84,7 +85,7 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
|||
|
||||
private @SurfaceRotation int mTouchRotation = ROTATION_0;
|
||||
private @SurfaceRotation int mDisplayRotation = ROTATION_0;
|
||||
private @SurfaceRotation int mLauncherRotation = Surface.ROTATION_0;
|
||||
private @SurfaceRotation int mLauncherRotation = ROTATION_0;
|
||||
|
||||
// Launcher activity supports multiple orientation, but fallback activity does not
|
||||
private static final int FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_ACTIVITY = 1 << 0;
|
||||
|
@ -102,6 +103,8 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
|||
private static final int FLAG_ROTATION_WATCHER_SUPPORTED = 1 << 6;
|
||||
// Whether to enable rotation watcher when multi-rotation is supported
|
||||
private static final int FLAG_ROTATION_WATCHER_ENABLED = 1 << 7;
|
||||
// Enable home rotation for UI tests, ignoring home rotation value from prefs
|
||||
private static final int FLAG_HOME_ROTATION_FORCE_ENABLED_FOR_TESTING = 1 << 8;
|
||||
|
||||
private static final int MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE =
|
||||
FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_ACTIVITY
|
||||
|
@ -121,7 +124,6 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
|||
private final WindowSizeStrategy mSizeStrategy;
|
||||
|
||||
private final Matrix mTmpMatrix = new Matrix();
|
||||
private final Matrix mTmpInverseMatrix = new Matrix();
|
||||
|
||||
private int mFlags;
|
||||
private int mPreviousRotation = ROTATION_0;
|
||||
|
@ -163,6 +165,10 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
|||
if (mOrientationListener.canDetectOrientation()) {
|
||||
mFlags |= FLAG_ROTATION_WATCHER_SUPPORTED;
|
||||
}
|
||||
|
||||
// initialize external flags
|
||||
updateAutoRotateSetting();
|
||||
updateHomeRotationSetting();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -181,13 +187,15 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
|||
* false otherwise
|
||||
*/
|
||||
public boolean update(
|
||||
@SurfaceRotation int touchRotation, @SurfaceRotation int displayRotation,
|
||||
@SurfaceRotation int launcherRotation) {
|
||||
@SurfaceRotation int touchRotation, @SurfaceRotation int displayRotation) {
|
||||
if (!isMultipleOrientationSupportedByDevice()) {
|
||||
return false;
|
||||
}
|
||||
if (mDisplayRotation == displayRotation && mTouchRotation == touchRotation
|
||||
&& launcherRotation == mLauncherRotation) {
|
||||
|
||||
int launcherRotation = inferLauncherRotation(displayRotation);
|
||||
if (mDisplayRotation == displayRotation
|
||||
&& mTouchRotation == touchRotation
|
||||
&& mLauncherRotation == launcherRotation) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -195,11 +203,10 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
|||
mDisplayRotation = displayRotation;
|
||||
mTouchRotation = touchRotation;
|
||||
|
||||
if (canLauncherRotate() || mLauncherRotation == mTouchRotation) {
|
||||
// TODO(b/153476489) Need to determine when launcher is rotated
|
||||
if (mLauncherRotation == mTouchRotation) {
|
||||
mOrientationHandler = PagedOrientationHandler.HOME_ROTATED;
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Set Orientation Handler: " + mOrientationHandler);
|
||||
Log.d(TAG, "current RecentsOrientedState: " + this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -212,11 +219,20 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
|||
mOrientationHandler = PagedOrientationHandler.PORTRAIT;
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Set Orientation Handler: " + mOrientationHandler);
|
||||
Log.d(TAG, "current RecentsOrientedState: " + this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@SurfaceRotation
|
||||
private int inferLauncherRotation(@SurfaceRotation int displayRotation) {
|
||||
if (!isMultipleOrientationSupportedByDevice() || isHomeRotationAllowed()) {
|
||||
return displayRotation;
|
||||
} else {
|
||||
return ROTATION_0;
|
||||
}
|
||||
}
|
||||
|
||||
private void setFlag(int mask, boolean enabled) {
|
||||
boolean wasRotationEnabled = !TestProtocol.sDisableSensorRotation
|
||||
&& mFlags == VALUE_ROTATION_WATCHER_ENABLED;
|
||||
|
@ -241,7 +257,9 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
|||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
|
||||
updateHomeRotationSetting();
|
||||
if (ALLOW_ROTATION_PREFERENCE_KEY.equals(s)) {
|
||||
updateHomeRotationSetting();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAutoRotateSetting() {
|
||||
|
@ -255,23 +273,24 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
|||
}
|
||||
|
||||
/**
|
||||
* Initializes aany system values and registers corresponding change listeners. It must be
|
||||
* paired with {@link #destroy()} call
|
||||
* Initializes any system values and registers corresponding change listeners. It must be
|
||||
* paired with {@link #destroyListeners()} call
|
||||
*/
|
||||
public void init() {
|
||||
public void initListeners() {
|
||||
if (isMultipleOrientationSupportedByDevice()) {
|
||||
mSharedPrefs.registerOnSharedPreferenceChangeListener(this);
|
||||
mContentResolver.registerContentObserver(
|
||||
Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION),
|
||||
false, mSystemAutoRotateObserver);
|
||||
}
|
||||
initWithoutListeners();
|
||||
updateAutoRotateSetting();
|
||||
updateHomeRotationSetting();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters any previously registered listeners.
|
||||
*/
|
||||
public void destroy() {
|
||||
public void destroyListeners() {
|
||||
if (isMultipleOrientationSupportedByDevice()) {
|
||||
mSharedPrefs.unregisterOnSharedPreferenceChangeListener(this);
|
||||
mContentResolver.unregisterContentObserver(mSystemAutoRotateObserver);
|
||||
|
@ -279,13 +298,8 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
|||
setRotationWatcherEnabled(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the OrientationState without attaching any listeners. This can be used when
|
||||
* the object is short lived.
|
||||
*/
|
||||
public void initWithoutListeners() {
|
||||
updateAutoRotateSetting();
|
||||
updateHomeRotationSetting();
|
||||
public void forceAllowRotationForTesting(boolean forceAllow) {
|
||||
setFlag(FLAG_HOME_ROTATION_FORCE_ENABLED_FOR_TESTING, forceAllow);
|
||||
}
|
||||
|
||||
@SurfaceRotation
|
||||
|
@ -310,7 +324,8 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
|||
|
||||
public boolean isHomeRotationAllowed() {
|
||||
return (mFlags & (FLAG_HOME_ROTATION_ALLOWED_IN_PREFS | FLAG_MULTIWINDOW_ROTATION_ALLOWED))
|
||||
!= 0;
|
||||
!= 0 ||
|
||||
(mFlags & FLAG_HOME_ROTATION_FORCE_ENABLED_FOR_TESTING) != 0;
|
||||
}
|
||||
|
||||
public boolean canLauncherRotate() {
|
||||
|
@ -347,7 +362,8 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
|||
float fullHeight = dp.heightPx - insets.top - insets.bottom;
|
||||
|
||||
if (dp.isMultiWindowMode) {
|
||||
mSizeStrategy.getMultiWindowSize(mContext, dp, outPivot);
|
||||
WindowBounds bounds = SplitScreenBounds.INSTANCE.getSecondaryWindowBounds(mContext);
|
||||
outPivot.set(bounds.availableSize.x, bounds.availableSize.y);
|
||||
} else {
|
||||
outPivot.set(fullWidth, fullHeight);
|
||||
}
|
||||
|
@ -403,23 +419,6 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
|||
*/
|
||||
}
|
||||
|
||||
public void mapRectFromNormalOrientation(RectF src, int screenWidth, int screenHeight) {
|
||||
mapRectFromRotation(mDisplayRotation, src, screenWidth, screenHeight);
|
||||
}
|
||||
|
||||
public void mapRectFromRotation(int rotation, RectF src, int screenWidth, int screenHeight) {
|
||||
mTmpMatrix.reset();
|
||||
postDisplayRotation(rotation, screenWidth, screenHeight, mTmpMatrix);
|
||||
mTmpMatrix.mapRect(src);
|
||||
}
|
||||
|
||||
public void mapInverseRectFromNormalOrientation(RectF src, int screenWidth, int screenHeight) {
|
||||
mTmpMatrix.reset();
|
||||
postDisplayRotation(mDisplayRotation, screenWidth, screenHeight, mTmpMatrix);
|
||||
mTmpMatrix.invert(mTmpInverseMatrix);
|
||||
mTmpInverseMatrix.mapRect(src);
|
||||
}
|
||||
|
||||
@SurfaceRotation
|
||||
public static int getRotationForUserDegreesRotated(float degrees, int currentRotation) {
|
||||
if (degrees == ORIENTATION_UNKNOWN) {
|
||||
|
@ -440,9 +439,13 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
|||
if (degrees < (90 - threshold)) {
|
||||
return ROTATION_0;
|
||||
}
|
||||
if (degrees > (90 + threshold)) {
|
||||
if (degrees > (90 + threshold) && degrees < 180) {
|
||||
return ROTATION_180;
|
||||
}
|
||||
// flip from seascape to landscape
|
||||
if (degrees > (180 + threshold) && degrees < 360) {
|
||||
return ROTATION_90;
|
||||
}
|
||||
break;
|
||||
case ROTATION_180:
|
||||
if (degrees < (180 - threshold)) {
|
||||
|
@ -453,12 +456,16 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
|||
}
|
||||
break;
|
||||
case ROTATION_90:
|
||||
if (degrees < (270 - threshold)) {
|
||||
if (degrees < (270 - threshold) && degrees > 90) {
|
||||
return ROTATION_180;
|
||||
}
|
||||
if (degrees > (270 + threshold)) {
|
||||
if (degrees > (270 + threshold) && degrees < 360) {
|
||||
return ROTATION_0;
|
||||
}
|
||||
// flip from landscape to seascape
|
||||
if (degrees > threshold && degrees < 180) {
|
||||
return ROTATION_270;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -506,13 +513,15 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
|||
public String toString() {
|
||||
boolean systemRotationOn = (mFlags & FLAG_SYSTEM_ROTATION_ALLOWED) != 0;
|
||||
return "["
|
||||
+ "mDisplayRotation=" + mDisplayRotation
|
||||
+ "this=" + extractObjectNameAndAddress(super.toString())
|
||||
+ " mOrientationHandler=" +
|
||||
extractObjectNameAndAddress(mOrientationHandler.toString())
|
||||
+ " mDisplayRotation=" + mDisplayRotation
|
||||
+ " mTouchRotation=" + mTouchRotation
|
||||
+ " mLauncherRotation=" + mLauncherRotation
|
||||
+ " mHomeRotation=" + isHomeRotationAllowed()
|
||||
+ " mSystemRotation=" + systemRotationOn
|
||||
+ " mFlags=" + mFlags
|
||||
+ " mOrientationHandler=" + mOrientationHandler
|
||||
+ "]";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.quickstep.util;
|
||||
|
||||
import static android.view.Surface.ROTATION_0;
|
||||
import static android.view.Surface.ROTATION_180;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.view.WindowInsets.Type;
|
||||
import android.view.WindowManager;
|
||||
import android.view.WindowMetrics;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.util.DefaultDisplay;
|
||||
import com.android.launcher3.util.WindowBounds;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Utility class to hold the information abound a window bounds for split screen
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.R)
|
||||
public class SplitScreenBounds {
|
||||
|
||||
public static final SplitScreenBounds INSTANCE = new SplitScreenBounds();
|
||||
private final ArrayList<OnChangeListener> mListeners = new ArrayList<>();
|
||||
|
||||
@Nullable
|
||||
private WindowBounds mBounds;
|
||||
|
||||
private SplitScreenBounds() { }
|
||||
|
||||
@UiThread
|
||||
public void setSecondaryWindowBounds(@NonNull WindowBounds bounds) {
|
||||
if (!bounds.equals(mBounds)) {
|
||||
mBounds = bounds;
|
||||
for (OnChangeListener listener : mListeners) {
|
||||
listener.onSecondaryWindowBoundsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public @NonNull WindowBounds getSecondaryWindowBounds(Context context) {
|
||||
if (mBounds == null) {
|
||||
mBounds = createDefaultWindowBounds(context);
|
||||
}
|
||||
return mBounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates window bounds as 50% of device size
|
||||
*/
|
||||
private static WindowBounds createDefaultWindowBounds(Context context) {
|
||||
WindowMetrics wm = context.getSystemService(WindowManager.class).getMaximumWindowMetrics();
|
||||
Insets insets = wm.getWindowInsets().getInsets(Type.systemBars());
|
||||
|
||||
WindowBounds bounds = new WindowBounds(wm.getBounds(),
|
||||
new Rect(insets.left, insets.top, insets.right, insets.bottom));
|
||||
int rotation = DefaultDisplay.INSTANCE.get(context).getInfo().rotation;
|
||||
int halfDividerSize = context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.multi_window_task_divider_size) / 2;
|
||||
|
||||
if (rotation == ROTATION_0 || rotation == ROTATION_180) {
|
||||
bounds.bounds.top = bounds.insets.top + bounds.availableSize.y / 2 + halfDividerSize;
|
||||
bounds.insets.top = 0;
|
||||
} else {
|
||||
bounds.bounds.left = bounds.insets.left + bounds.availableSize.x / 2 + halfDividerSize;
|
||||
bounds.insets.left = 0;
|
||||
}
|
||||
return new WindowBounds(bounds.bounds, bounds.insets);
|
||||
}
|
||||
|
||||
public void addOnChangeListener(OnChangeListener listener) {
|
||||
mListeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeOnChangeListener(OnChangeListener listener) {
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface to receive window bounds changes
|
||||
*/
|
||||
public interface OnChangeListener {
|
||||
|
||||
/**
|
||||
* Called when window bounds for secondary window changes
|
||||
*/
|
||||
void onSecondaryWindowBoundsChanged();
|
||||
}
|
||||
}
|
|
@ -16,36 +16,35 @@
|
|||
package com.android.quickstep.util;
|
||||
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
|
||||
import static com.android.quickstep.SysUINavigationMode.getMode;
|
||||
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
|
||||
import static com.android.quickstep.util.LayoutUtils.getDefaultSwipeHeight;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.util.WindowBounds;
|
||||
import com.android.quickstep.SysUINavigationMode.Mode;
|
||||
|
||||
/**
|
||||
* Utility class to wrap different layout behavior for Launcher and RecentsView
|
||||
* TODO: Merge is with {@link com.android.quickstep.BaseActivityInterface} once we remove the
|
||||
* state dependent members from {@link com.android.quickstep.LauncherActivityInterface}
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.R)
|
||||
public abstract class WindowSizeStrategy {
|
||||
|
||||
private final PointF mTempPoint = new PointF();
|
||||
public final boolean rotationSupportedByActivity;
|
||||
|
||||
private WindowSizeStrategy(boolean rotationSupportedByActivity) {
|
||||
this.rotationSupportedByActivity = rotationSupportedByActivity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the expected window size in multi-window mode
|
||||
*/
|
||||
public abstract void getMultiWindowSize(Context context, DeviceProfile dp, PointF out);
|
||||
|
||||
/**
|
||||
* Calculates the taskView size for the provided device configuration
|
||||
*/
|
||||
|
@ -57,35 +56,41 @@ public abstract class WindowSizeStrategy {
|
|||
|
||||
private void calculateTaskSize(
|
||||
Context context, DeviceProfile dp, float extraVerticalSpace, Rect outRect) {
|
||||
float taskWidth, taskHeight, paddingHorz;
|
||||
Resources res = context.getResources();
|
||||
Rect insets = dp.getInsets();
|
||||
final boolean showLargeTaskSize = showOverviewActions(context);
|
||||
|
||||
final int paddingResId;
|
||||
if (dp.isMultiWindowMode) {
|
||||
getMultiWindowSize(context, dp, mTempPoint);
|
||||
taskWidth = mTempPoint.x;
|
||||
taskHeight = mTempPoint.y;
|
||||
paddingHorz = res.getDimension(R.dimen.multi_window_task_card_horz_space);
|
||||
paddingResId = R.dimen.multi_window_task_card_horz_space;
|
||||
} else if (dp.isVerticalBarLayout()) {
|
||||
paddingResId = R.dimen.landscape_task_card_horz_space;
|
||||
} else if (showLargeTaskSize) {
|
||||
paddingResId = R.dimen.portrait_task_card_horz_space_big_overview;
|
||||
} else {
|
||||
paddingResId = R.dimen.portrait_task_card_horz_space;
|
||||
}
|
||||
float paddingHorz = res.getDimension(paddingResId);
|
||||
float paddingVert = showLargeTaskSize
|
||||
? 0 : res.getDimension(R.dimen.task_card_vert_space);
|
||||
|
||||
calculateTaskSizeInternal(context, dp, extraVerticalSpace, paddingHorz, paddingVert,
|
||||
res.getDimension(R.dimen.task_thumbnail_top_margin), outRect);
|
||||
}
|
||||
|
||||
private void calculateTaskSizeInternal(Context context, DeviceProfile dp,
|
||||
float extraVerticalSpace, float paddingHorz, float paddingVert, float topIconMargin,
|
||||
Rect outRect) {
|
||||
float taskWidth, taskHeight;
|
||||
Rect insets = dp.getInsets();
|
||||
if (dp.isMultiWindowMode) {
|
||||
WindowBounds bounds = SplitScreenBounds.INSTANCE.getSecondaryWindowBounds(context);
|
||||
taskWidth = bounds.availableSize.x;
|
||||
taskHeight = bounds.availableSize.y;
|
||||
} else {
|
||||
taskWidth = dp.availableWidthPx;
|
||||
taskHeight = dp.availableHeightPx;
|
||||
|
||||
final int paddingResId;
|
||||
if (dp.isVerticalBarLayout()) {
|
||||
paddingResId = R.dimen.landscape_task_card_horz_space;
|
||||
} else if (showLargeTaskSize) {
|
||||
paddingResId = R.dimen.portrait_task_card_horz_space_big_overview;
|
||||
} else {
|
||||
paddingResId = R.dimen.portrait_task_card_horz_space;
|
||||
}
|
||||
paddingHorz = res.getDimension(paddingResId);
|
||||
}
|
||||
|
||||
float topIconMargin = res.getDimension(R.dimen.task_thumbnail_top_margin);
|
||||
float paddingVert = showLargeTaskSize
|
||||
? 0 : res.getDimension(R.dimen.task_card_vert_space);
|
||||
|
||||
// Note this should be same as dp.availableWidthPx and dp.availableHeightPx unless
|
||||
// we override the insets ourselves.
|
||||
int launcherVisibleWidth = dp.widthPx - insets.left - insets.right;
|
||||
|
@ -107,26 +112,41 @@ public abstract class WindowSizeStrategy {
|
|||
Math.round(x) + Math.round(outWidth), Math.round(y) + Math.round(outHeight));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the modal taskView size for the provided device configuration
|
||||
*/
|
||||
public void calculateModalTaskSize(Context context, DeviceProfile dp, Rect outRect) {
|
||||
float paddingHorz = context.getResources().getDimension(dp.isMultiWindowMode
|
||||
? R.dimen.multi_window_task_card_horz_space
|
||||
: dp.isVerticalBarLayout()
|
||||
? R.dimen.landscape_task_card_horz_space
|
||||
: R.dimen.portrait_modal_task_card_horz_space);
|
||||
float extraVerticalSpace = getOverviewActionsHeight(context);
|
||||
float paddingVert = 0;
|
||||
float topIconMargin = 0;
|
||||
calculateTaskSizeInternal(context, dp, extraVerticalSpace, paddingHorz, paddingVert,
|
||||
topIconMargin, outRect);
|
||||
}
|
||||
|
||||
/** Gets the space that the overview actions will take, including margins. */
|
||||
public float getOverviewActionsHeight(Context context) {
|
||||
Resources res = context.getResources();
|
||||
float actionsBottomMargin = 0;
|
||||
if (getMode(context) == Mode.THREE_BUTTONS) {
|
||||
actionsBottomMargin = res.getDimensionPixelSize(
|
||||
R.dimen.overview_actions_bottom_margin_three_button);
|
||||
} else {
|
||||
actionsBottomMargin = res.getDimensionPixelSize(
|
||||
R.dimen.overview_actions_bottom_margin_gesture);
|
||||
}
|
||||
float overviewActionsHeight = actionsBottomMargin
|
||||
+ res.getDimensionPixelSize(R.dimen.overview_actions_height);
|
||||
return overviewActionsHeight;
|
||||
}
|
||||
|
||||
public static final WindowSizeStrategy LAUNCHER_ACTIVITY_SIZE_STRATEGY =
|
||||
new WindowSizeStrategy(true) {
|
||||
|
||||
@Override
|
||||
public void getMultiWindowSize(Context context, DeviceProfile dp, PointF out) {
|
||||
DeviceProfile fullDp = dp.getFullScreenProfile();
|
||||
// Use availableWidthPx and availableHeightPx instead of widthPx and heightPx to
|
||||
// account for system insets
|
||||
out.set(fullDp.availableWidthPx, fullDp.availableHeightPx);
|
||||
float halfDividerSize = context.getResources()
|
||||
.getDimension(R.dimen.multi_window_task_divider_size) / 2;
|
||||
|
||||
if (fullDp.isLandscape) {
|
||||
out.x = out.x / 2 - halfDividerSize;
|
||||
} else {
|
||||
out.y = out.y / 2 - halfDividerSize;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
float getExtraSpace(Context context, DeviceProfile dp) {
|
||||
if (dp.isVerticalBarLayout()) {
|
||||
|
@ -136,7 +156,7 @@ public abstract class WindowSizeStrategy {
|
|||
if (showOverviewActions(context)) {
|
||||
//TODO: this needs to account for the swipe gesture height and accessibility
|
||||
// UI when shown.
|
||||
return res.getDimensionPixelSize(R.dimen.overview_actions_height);
|
||||
return getOverviewActionsHeight(context);
|
||||
} else {
|
||||
return getDefaultSwipeHeight(context, dp) + dp.workspacePageIndicatorHeight
|
||||
+ res.getDimensionPixelSize(
|
||||
|
@ -150,10 +170,6 @@ public abstract class WindowSizeStrategy {
|
|||
|
||||
public static final WindowSizeStrategy FALLBACK_RECENTS_SIZE_STRATEGY =
|
||||
new WindowSizeStrategy(false) {
|
||||
@Override
|
||||
public void getMultiWindowSize(Context context, DeviceProfile dp, PointF out) {
|
||||
out.set(dp.widthPx, dp.heightPx);
|
||||
}
|
||||
|
||||
@Override
|
||||
float getExtraSpace(Context context, DeviceProfile dp) {
|
||||
|
|
|
@ -42,6 +42,7 @@ import com.android.launcher3.ui.TaplTestsLauncher3;
|
|||
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
@ -53,6 +54,18 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
|
|||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
TaplTestsLauncher3.initialize(this);
|
||||
executeOnLauncher(launcher -> {
|
||||
RecentsView recentsView = launcher.getOverviewPanel();
|
||||
recentsView.getPagedViewOrientedState().forceAllowRotationForTesting(true);
|
||||
});
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
executeOnLauncher(launcher -> {
|
||||
RecentsView recentsView = launcher.getOverviewPanel();
|
||||
recentsView.getPagedViewOrientedState().forceAllowRotationForTesting(false);
|
||||
});
|
||||
}
|
||||
|
||||
private void startTestApps() throws Exception {
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:alpha="1"
|
||||
android:color="?attr/workspaceTextColor"
|
||||
android:state_enabled="true" />
|
||||
<item
|
||||
android:alpha="?android:disabledAlpha"
|
||||
android:color="?attr/workspaceTextColor"
|
||||
android:state_enabled="false" />
|
||||
</selector>
|
|
@ -23,13 +23,13 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="32dp"
|
||||
android:background="@drawable/bottom_sheet_top_border"
|
||||
android:backgroundTint="?android:attr/colorAccent" />
|
||||
android:backgroundTint="?attr/eduHalfSheetBGColor" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/view_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/colorAccent"
|
||||
android:background="?attr/eduHalfSheetBGColor"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="@dimen/bottom_sheet_edu_padding"
|
||||
android:paddingRight="@dimen/bottom_sheet_edu_padding">
|
||||
|
|
|
@ -131,7 +131,7 @@
|
|||
<string name="accessibility_close" msgid="2277148124685870734">"بستن"</string>
|
||||
<string name="notification_dismissed" msgid="6002233469409822874">"اعلان رد شد"</string>
|
||||
<string name="all_apps_personal_tab" msgid="4190252696685155002">"شخصی"</string>
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"محل کار"</string>
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"کاری"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"نمایه کاری"</string>
|
||||
<string name="work_profile_edu_personal_apps" msgid="4155536355149317441">"دادههای شخصی از برنامههای کاری جدا است و از آن پنهان است"</string>
|
||||
<string name="work_profile_edu_work_apps" msgid="237051938268703058">"برنامههای کاری و دادهها برای سرپرست فناوری اطلاعات نمایان هستند"</string>
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<resources xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
|
||||
<string name="work_folder_name" msgid="3753320833950115786">"કાર્યાલય"</string>
|
||||
<string name="work_folder_name" msgid="3753320833950115786">"ઑફિસ"</string>
|
||||
<string name="activity_not_found" msgid="8071924732094499514">"ઍપ્લિકેશન ઇન્સ્ટોલ થઈ નથી."</string>
|
||||
<string name="activity_not_available" msgid="7456344436509528827">"ઍપ્લિકેશન ઉપલબ્ધ નથી"</string>
|
||||
<string name="safemode_shortcut_error" msgid="9160126848219158407">"સુરક્ષિત મોડમાં ડાઉનલોડ કરેલ ઍપ્લિકેશન અક્ષમ કરી"</string>
|
||||
|
@ -131,7 +131,7 @@
|
|||
<string name="accessibility_close" msgid="2277148124685870734">"બંધ કરો"</string>
|
||||
<string name="notification_dismissed" msgid="6002233469409822874">"સૂચના છોડી દીધી"</string>
|
||||
<string name="all_apps_personal_tab" msgid="4190252696685155002">"મનગમતી ઍપ"</string>
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"કાર્યાલયની ઍપ"</string>
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"ઑફિસની ઍપ"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"ઑફિસની પ્રોફાઇલ"</string>
|
||||
<string name="work_profile_edu_personal_apps" msgid="4155536355149317441">"વ્યક્તિગત ડેટા ઑફિસ માટેની ઍપથી અલગ અને છુપાવીને રાખેલો છે"</string>
|
||||
<string name="work_profile_edu_work_apps" msgid="237051938268703058">"ઑફિસ માટેની ઍપ અને ડેટા તમારા IT વ્યવસ્થાપકને દેખાય છે"</string>
|
||||
|
|
|
@ -53,11 +53,11 @@
|
|||
<string name="app_info_drop_target_label" msgid="692894985365717661">"अनुप्रयोगको जानकारी"</string>
|
||||
<string name="install_drop_target_label" msgid="2539096853673231757">"स्थापना गर्नुहोस्"</string>
|
||||
<string name="permlab_install_shortcut" msgid="5632423390354674437">"सर्टकट स्थापना गर्नेहोस्"</string>
|
||||
<string name="permdesc_install_shortcut" msgid="923466509822011139">"प्रयोगकर्ताको हस्तक्षेप बिना एउटा अनुप्रयोगलाई सर्टकटमा थप्नको लागि अनुमति दिनुहोस्।"</string>
|
||||
<string name="permdesc_install_shortcut" msgid="923466509822011139">"प्रयोगकर्ताको हस्तक्षेप बिना एउटा एपलाई सर्टकटमा थप्नको लागि अनुमति दिनुहोस्।"</string>
|
||||
<string name="permlab_read_settings" msgid="1941457408239617576">"गृह सेटिङहरू र सर्टकटहरू पढ्नुहोस्"</string>
|
||||
<string name="permdesc_read_settings" msgid="5833423719057558387">"गृहमा एउटा अनुप्रयोगलाई सेटिङहरू र सर्टकटहरू पढ्न अनुमति दिनुहोस्।"</string>
|
||||
<string name="permdesc_read_settings" msgid="5833423719057558387">"गृहमा एउटा एपलाई सेटिङहरू र सर्टकटहरू पढ्न अनुमति दिनुहोस्।"</string>
|
||||
<string name="permlab_write_settings" msgid="3574213698004620587">"गृह सेटिङहरू र सर्टकटहरू लेख्नुहोस्"</string>
|
||||
<string name="permdesc_write_settings" msgid="5440712911516509985">"गृहमा एउटा अनुप्रयोगलाई सेटिङ र सर्टकट बदल्न अनुमति दिनुहोस्।"</string>
|
||||
<string name="permdesc_write_settings" msgid="5440712911516509985">"गृहमा एउटा एपलाई सेटिङ र सर्टकट बदल्न अनुमति दिनुहोस्।"</string>
|
||||
<string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> ले फोन कलहरू गर्न अनुमति छैन"</string>
|
||||
<string name="gadget_error_text" msgid="6081085226050792095">"समस्या लोडिङ गर्ने विजेट"</string>
|
||||
<string name="gadget_setup_text" msgid="8274003207686040488">"सेटअप"</string>
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<resources xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="app_name" msgid="649227358658669779">"ଲଞ୍ଚର୍3"</string>
|
||||
<string name="work_folder_name" msgid="3753320833950115786">"କାମ"</string>
|
||||
<string name="work_folder_name" msgid="3753320833950115786">"ୱାର୍କ"</string>
|
||||
<string name="activity_not_found" msgid="8071924732094499514">"ଆପ୍ ଇନଷ୍ଟଲ୍ ହୋଇନାହିଁ"</string>
|
||||
<string name="activity_not_available" msgid="7456344436509528827">"ଆପ୍ ଉପଲବ୍ଧ ନାହିଁ"</string>
|
||||
<string name="safemode_shortcut_error" msgid="9160126848219158407">"ନିରାପଦ ମୋଡରେ ଡାଉନଲୋଡ୍ ହେଇଥିବା ଆପ୍ ଅକ୍ଷମ କରାଗଲା"</string>
|
||||
|
@ -131,7 +131,7 @@
|
|||
<string name="accessibility_close" msgid="2277148124685870734">"ବନ୍ଦ କରନ୍ତୁ"</string>
|
||||
<string name="notification_dismissed" msgid="6002233469409822874">"ବିଜ୍ଞପ୍ତି ଖାରଜ କରାଗଲା"</string>
|
||||
<string name="all_apps_personal_tab" msgid="4190252696685155002">"ବ୍ୟକ୍ତିଗତ"</string>
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"କାମ"</string>
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"ୱାର୍କ"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"ୱର୍କ ପ୍ରୋଫାଇଲ୍"</string>
|
||||
<string name="work_profile_edu_personal_apps" msgid="4155536355149317441">"ବ୍ୟକ୍ତିଗତ ଡାଟା କାର୍ଯ୍ୟସ୍ଥଳୀ ଆପଗୁଡ଼ିକ ଠାରୁ ପୃଥକ୍ ଓ ଲୁକ୍କାୟିତ ଅଟେ"</string>
|
||||
<string name="work_profile_edu_work_apps" msgid="237051938268703058">"କାର୍ଯ୍ୟସ୍ଥଳୀ ଆପଗୁଡ଼ିକ ଓ ଡାଟା ଆପଣଙ୍କ IT ଆଡମିନଙ୍କୁ ଦେଖାଯାଏ"</string>
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
<attr name="widgetsTheme" format="reference" />
|
||||
<attr name="loadingIconColor" format="color" />
|
||||
<attr name="iconOnlyShortcutColor" format="color"/>
|
||||
<attr name="eduHalfSheetBGColor" format="color"/>
|
||||
|
||||
<attr name="folderDotColor" format="color" />
|
||||
<attr name="folderFillColor" format="color" />
|
||||
|
|
|
@ -103,9 +103,9 @@
|
|||
<!-- Label for install drop target. [CHAR_LIMIT=20] -->
|
||||
<string name="install_drop_target_label">Install</string>
|
||||
<!-- Label for install dismiss prediction. -->
|
||||
<string translatable="false" name="dismiss_prediction_label">Don\'t suggest app</string>
|
||||
<string name="dismiss_prediction_label">Don\'t suggest app</string>
|
||||
<!-- Label for pinning predicted app. -->
|
||||
<string name="pin_prediction" translatable="false">Pin Prediction</string>
|
||||
<string name="pin_prediction">Pin Prediction</string>
|
||||
|
||||
|
||||
<!-- Permissions: -->
|
||||
|
@ -342,7 +342,7 @@
|
|||
<!--- heading shown when user opens work apps tab while work apps are paused -->
|
||||
<string name="work_apps_paused_title">Work profile is paused</string>
|
||||
<!--- body shown when user opens work apps tab while work apps are paused -->
|
||||
<string name="work_apps_paused_body">Work apps can\’t send you notifications, use your battery, or access your location</string>
|
||||
<string name="work_apps_paused_body">Work apps can\'t send you notifications, use your battery, or access your location</string>
|
||||
<!-- content description for paused work apps list -->
|
||||
<string name="work_apps_paused_content_description">Work profile is paused. Work apps can\’t send you notifications, use your battery, or access your location</string>
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
<item name="loadingIconColor">#CCFFFFFF</item>
|
||||
<item name="iconOnlyShortcutColor">?android:attr/textColorSecondary</item>
|
||||
<item name="workProfileOverlayTextColor">#FF212121</item>
|
||||
<item name="eduHalfSheetBGColor">?android:attr/colorAccent</item>
|
||||
|
||||
<item name="android:windowTranslucentStatus">false</item>
|
||||
<item name="android:windowTranslucentNavigation">false</item>
|
||||
|
@ -90,7 +91,7 @@
|
|||
<item name="android:textColorHint">#A0FFFFFF</item>
|
||||
<item name="android:colorControlHighlight">#A0FFFFFF</item>
|
||||
<item name="android:colorPrimary">#FF212121</item>
|
||||
<item name="allAppsScrimColor">#FF212121</item>
|
||||
<item name="allAppsScrimColor">#FF000000</item>
|
||||
<item name="allAppsInterimScrimAlpha">102</item>
|
||||
<item name="allAppsNavBarScrimColor">#80000000</item>
|
||||
<item name="popupColorPrimary">#3C4043</item> <!-- Gray 800 -->
|
||||
|
@ -106,6 +107,7 @@
|
|||
<item name="loadingIconColor">#99FFFFFF</item>
|
||||
<item name="iconOnlyShortcutColor">#B3FFFFFF</item>
|
||||
<item name="workProfileOverlayTextColor">@android:color/white</item>
|
||||
<item name="eduHalfSheetBGColor">#DD000000</item>
|
||||
</style>
|
||||
|
||||
<style name="LauncherTheme.Dark.DarkMainColor" parent="@style/LauncherTheme.Dark">
|
||||
|
@ -229,9 +231,7 @@
|
|||
|
||||
<style name="TextHeadline" parent="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle" />
|
||||
<style name="PrimaryMediumText" parent="@android:style/TextAppearance.DeviceDefault.Medium"/>
|
||||
<style name="PrimaryHeadline" parent="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle">
|
||||
<item name="android:textStyle">bold</item>
|
||||
</style>
|
||||
<style name="PrimaryHeadline" parent="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle"/>
|
||||
|
||||
<style name="TextTitle" parent="@android:style/TextAppearance.DeviceDefault" />
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.APP_LAUNCH_TAP;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
|
||||
import static com.android.launcher3.util.DefaultDisplay.CHANGE_ROTATION;
|
||||
|
||||
import android.app.ActivityOptions;
|
||||
|
@ -183,8 +183,7 @@ public abstract class BaseDraggingActivity extends BaseActivity
|
|||
sourceContainer);
|
||||
}
|
||||
getUserEventDispatcher().logAppLaunch(v, intent, user);
|
||||
|
||||
getStatsLogManager().log(APP_LAUNCH_TAP, item == null ? null
|
||||
getStatsLogManager().log(LAUNCHER_APP_LAUNCH_TAP, item == null ? null
|
||||
: item.buildProto(null));
|
||||
return true;
|
||||
} catch (NullPointerException|ActivityNotFoundException|SecurityException e) {
|
||||
|
|
|
@ -60,6 +60,7 @@ import com.android.launcher3.model.data.ItemInfoWithIcon;
|
|||
import com.android.launcher3.model.data.PackageItemInfo;
|
||||
import com.android.launcher3.model.data.PromiseAppInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.util.SafeCloseable;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.views.IconLabelDotView;
|
||||
|
||||
|
@ -722,17 +723,34 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
|||
}
|
||||
|
||||
@Override
|
||||
public void getVisualDragBounds(Rect bounds) {
|
||||
public void getWorkspaceVisualDragBounds(Rect bounds) {
|
||||
DeviceProfile grid = mActivity.getDeviceProfile();
|
||||
BubbleTextView.getIconBounds(this, bounds, grid.iconSizePx);
|
||||
}
|
||||
|
||||
private int getIconSizeForDisplay(int display) {
|
||||
DeviceProfile grid = mActivity.getDeviceProfile();
|
||||
switch (display) {
|
||||
case DISPLAY_ALL_APPS:
|
||||
return grid.allAppsIconSizePx;
|
||||
case DISPLAY_WORKSPACE:
|
||||
case DISPLAY_FOLDER:
|
||||
default:
|
||||
return grid.iconSizePx;
|
||||
}
|
||||
}
|
||||
|
||||
public void getSourceVisualDragBounds(Rect bounds) {
|
||||
BubbleTextView.getIconBounds(this, bounds, getIconSizeForDisplay(mDisplay));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareDrawDragView() {
|
||||
public SafeCloseable prepareDrawDragView() {
|
||||
if (getIcon() instanceof FastBitmapDrawable) {
|
||||
FastBitmapDrawable icon = (FastBitmapDrawable) getIcon();
|
||||
icon.setScale(1f);
|
||||
}
|
||||
setForceHideDot(true);
|
||||
return () -> { };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_CANCEL;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_REMOVE;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.UNDO;
|
||||
|
||||
|
@ -27,6 +29,7 @@ import android.view.View;
|
|||
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
|
||||
import com.android.launcher3.dragndrop.DragOptions;
|
||||
import com.android.launcher3.logging.LoggerUtils;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.model.ModelWriter;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
|
@ -38,6 +41,8 @@ import com.android.launcher3.views.Snackbar;
|
|||
|
||||
public class DeleteDropTarget extends ButtonDropTarget {
|
||||
|
||||
private final StatsLogManager mStatsLogManager;
|
||||
|
||||
private int mControlType = ControlType.DEFAULT_CONTROLTYPE;
|
||||
|
||||
public DeleteDropTarget(Context context, AttributeSet attrs) {
|
||||
|
@ -46,6 +51,7 @@ public class DeleteDropTarget extends ButtonDropTarget {
|
|||
|
||||
public DeleteDropTarget(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
this.mStatsLogManager = StatsLogManager.newInstance(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -120,6 +126,11 @@ public class DeleteDropTarget extends ButtonDropTarget {
|
|||
d.dragInfo.container = NO_ID;
|
||||
}
|
||||
super.onDrop(d, options);
|
||||
mStatsLogManager.log(
|
||||
mControlType == ControlType.REMOVE_TARGET
|
||||
? LAUNCHER_ITEM_DROPPED_ON_REMOVE
|
||||
: LAUNCHER_ITEM_DROPPED_ON_CANCEL,
|
||||
d.logInstanceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -78,7 +78,7 @@ public interface DropTarget {
|
|||
public DraggableView originalView = null;
|
||||
|
||||
/** Used for matching DROP event with its corresponding DRAG event on the server side. */
|
||||
final InstanceId mLogInstanceId =
|
||||
public final InstanceId logInstanceId =
|
||||
new InstanceIdSequence(1 << 20 /*InstanceId.INSTANCE_ID_MAX*/)
|
||||
.newInstanceId();
|
||||
|
||||
|
|
|
@ -67,7 +67,6 @@ import android.database.sqlite.SQLiteDatabase;
|
|||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.Handler;
|
||||
import android.os.Parcelable;
|
||||
import android.os.Process;
|
||||
import android.os.StrictMode;
|
||||
|
@ -87,12 +86,12 @@ import android.view.accessibility.AccessibilityEvent;
|
|||
import android.view.animation.OvershootInterpolator;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.launcher3.DropTarget.DragObject;
|
||||
import com.android.launcher3.LauncherStateManager.StateHandler;
|
||||
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
|
||||
import com.android.launcher3.allapps.AllAppsContainerView;
|
||||
import com.android.launcher3.allapps.AllAppsStore;
|
||||
|
@ -130,6 +129,10 @@ import com.android.launcher3.popup.PopupContainerWithArrow;
|
|||
import com.android.launcher3.popup.PopupDataProvider;
|
||||
import com.android.launcher3.popup.SystemShortcut;
|
||||
import com.android.launcher3.qsb.QsbContainerView;
|
||||
import com.android.launcher3.statemanager.StateManager;
|
||||
import com.android.launcher3.statemanager.StateManager.StateHandler;
|
||||
import com.android.launcher3.statemanager.StateManager.StateListener;
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
import com.android.launcher3.states.RotationHelper;
|
||||
import com.android.launcher3.testing.TestLogging;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
|
@ -193,7 +196,7 @@ import java.util.stream.Stream;
|
|||
/**
|
||||
* Default launcher application.
|
||||
*/
|
||||
public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
public class Launcher extends StatefulActivity<LauncherState> implements LauncherExterns,
|
||||
Callbacks, InvariantDeviceProfile.OnIDPChangeListener, PluginListener<OverlayPlugin> {
|
||||
public static final String TAG = "Launcher";
|
||||
|
||||
|
@ -240,7 +243,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
public static final String ON_RESUME_EVT = "Launcher.onResume";
|
||||
public static final String ON_NEW_INTENT_EVT = "Launcher.onNewIntent";
|
||||
|
||||
private LauncherStateManager mStateManager;
|
||||
private StateManager<LauncherState> mStateManager;
|
||||
|
||||
private static final int ON_ACTIVITY_RESULT_ANIMATION_DELAY = 500;
|
||||
|
||||
|
@ -324,10 +327,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
|
||||
private RotationHelper mRotationHelper;
|
||||
|
||||
final Handler mHandler = new Handler();
|
||||
private final Runnable mHandleDeferredResume = this::handleDeferredResume;
|
||||
private boolean mDeferredResumePending;
|
||||
|
||||
private float mCurrentAssistantVisibility = 0f;
|
||||
|
||||
protected LauncherOverlayManager mOverlayManager;
|
||||
|
@ -374,9 +373,9 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
|
||||
mDragController = new DragController(this);
|
||||
mAllAppsController = new AllAppsTransitionController(this);
|
||||
mStateManager = new LauncherStateManager(this);
|
||||
mStateManager = new StateManager<>(this, NORMAL);
|
||||
|
||||
mOnboardingPrefs = createOnboardingPrefs(mSharedPrefs, mStateManager);
|
||||
mOnboardingPrefs = createOnboardingPrefs(mSharedPrefs);
|
||||
|
||||
mAppWidgetManager = new WidgetManagerHelper(this);
|
||||
mAppWidgetHost = new LauncherAppWidgetHost(this,
|
||||
|
@ -439,7 +438,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
|
||||
mRotationHelper.initialize();
|
||||
|
||||
mStateManager.addStateListener(new LauncherStateManager.StateListener() {
|
||||
mStateManager.addStateListener(new StateListener<LauncherState>() {
|
||||
|
||||
@Override
|
||||
public void onStateTransitionComplete(LauncherState finalState) {
|
||||
|
@ -466,9 +465,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
return new LauncherOverlayManager() { };
|
||||
}
|
||||
|
||||
protected OnboardingPrefs createOnboardingPrefs(SharedPreferences sharedPrefs,
|
||||
LauncherStateManager stateManager) {
|
||||
return new OnboardingPrefs<>(this, sharedPrefs, stateManager);
|
||||
protected OnboardingPrefs createOnboardingPrefs(SharedPreferences sharedPrefs) {
|
||||
return new OnboardingPrefs<>(this, sharedPrefs);
|
||||
}
|
||||
|
||||
public OnboardingPrefs getOnboardingPrefs() {
|
||||
|
@ -522,13 +520,9 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
}
|
||||
|
||||
@Override
|
||||
public void reapplyUi() {
|
||||
reapplyUi(true /* cancelCurrentAnimation */);
|
||||
}
|
||||
|
||||
public void reapplyUi(boolean cancelCurrentAnimation) {
|
||||
getRootView().dispatchInsets();
|
||||
getStateManager().reapplyState(cancelCurrentAnimation);
|
||||
super.reapplyUi(cancelCurrentAnimation);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -582,7 +576,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
return mFocusHandler;
|
||||
}
|
||||
|
||||
public LauncherStateManager getStateManager() {
|
||||
@Override
|
||||
public StateManager<LauncherState> getStateManager() {
|
||||
return mStateManager;
|
||||
}
|
||||
|
||||
|
@ -889,11 +884,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
final boolean wasActive = isUserActive();
|
||||
final LauncherState origState = getStateManager().getState();
|
||||
final int origDragLayerChildCount = mDragLayer.getChildCount();
|
||||
super.onStop();
|
||||
|
||||
if (mDeferOverlayCallbacks) {
|
||||
checkIfOverlayStillDeferred();
|
||||
} else {
|
||||
|
@ -901,28 +892,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
}
|
||||
|
||||
logStopAndResume(Action.Command.STOP);
|
||||
|
||||
mAppWidgetHost.setListenIfResumed(false);
|
||||
|
||||
NotificationListener.removeNotificationsChangedListener();
|
||||
getStateManager().moveToRestState();
|
||||
|
||||
// Workaround for b/78520668, explicitly trim memory once UI is hidden
|
||||
onTrimMemory(TRIM_MEMORY_UI_HIDDEN);
|
||||
|
||||
if (wasActive) {
|
||||
// The expected condition is that this activity is stopped because the device goes to
|
||||
// sleep and the UI may have noticeable changes.
|
||||
mDragLayer.post(() -> {
|
||||
if ((!getStateManager().isInStableState(origState)
|
||||
// The drag layer may be animating (e.g. dismissing QSB).
|
||||
|| mDragLayer.getAlpha() < 1
|
||||
// Maybe an ArrowPopup is closed.
|
||||
|| mDragLayer.getChildCount() != origDragLayerChildCount)) {
|
||||
onUiChangedWhileSleeping();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -938,35 +909,27 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
TraceHelper.INSTANCE.endSection(traceToken);
|
||||
}
|
||||
|
||||
private void handleDeferredResume() {
|
||||
if (hasBeenResumed() && !mStateManager.getState().hasFlag(FLAG_NON_INTERACTIVE)) {
|
||||
logStopAndResume(Action.Command.RESUME);
|
||||
getUserEventDispatcher().startSession();
|
||||
@Override
|
||||
@CallSuper
|
||||
protected void onDeferredResumed() {
|
||||
logStopAndResume(Action.Command.RESUME);
|
||||
getUserEventDispatcher().startSession();
|
||||
|
||||
AppLaunchTracker.INSTANCE.get(this).onReturnedToHome();
|
||||
AppLaunchTracker.INSTANCE.get(this).onReturnedToHome();
|
||||
|
||||
// Process any items that were added while Launcher was away.
|
||||
InstallShortcutReceiver.disableAndFlushInstallQueue(
|
||||
InstallShortcutReceiver.FLAG_ACTIVITY_PAUSED, this);
|
||||
// Process any items that were added while Launcher was away.
|
||||
InstallShortcutReceiver.disableAndFlushInstallQueue(
|
||||
InstallShortcutReceiver.FLAG_ACTIVITY_PAUSED, this);
|
||||
|
||||
// Refresh shortcuts if the permission changed.
|
||||
mModel.refreshShortcutsIfRequired();
|
||||
// Refresh shortcuts if the permission changed.
|
||||
mModel.refreshShortcutsIfRequired();
|
||||
|
||||
// Set the notification listener and fetch updated notifications when we resume
|
||||
NotificationListener.setNotificationsChangedListener(mPopupDataProvider);
|
||||
// Set the notification listener and fetch updated notifications when we resume
|
||||
NotificationListener.setNotificationsChangedListener(mPopupDataProvider);
|
||||
|
||||
DiscoveryBounce.showForHomeIfNeeded(this);
|
||||
|
||||
onDeferredResumed();
|
||||
addActivityFlags(ACTIVITY_STATE_DEFERRED_RESUMED);
|
||||
|
||||
mDeferredResumePending = false;
|
||||
} else {
|
||||
mDeferredResumePending = true;
|
||||
}
|
||||
DiscoveryBounce.showForHomeIfNeeded(this);
|
||||
}
|
||||
|
||||
protected void onDeferredResumed() { }
|
||||
|
||||
private void logStopAndResume(int command) {
|
||||
int containerType = mStateManager.getState().containerType;
|
||||
|
@ -1015,10 +978,9 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
return mOverlayManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateSetStart(LauncherState state) {
|
||||
if (mDeferredResumePending) {
|
||||
handleDeferredResume();
|
||||
}
|
||||
super.onStateSetStart(state);
|
||||
if (mDeferOverlayCallbacks) {
|
||||
scheduleDeferredCheck();
|
||||
}
|
||||
|
@ -1041,7 +1003,9 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
mWorkspace.getPageIndicator().setShouldAutoHide(!state.hasFlag(FLAG_MULTI_PAGE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateSetEnd(LauncherState state) {
|
||||
super.onStateSetStart(state);
|
||||
getAppWidgetHost().setResumed(state == LauncherState.NORMAL);
|
||||
getWorkspace().setClipChildren(!state.hasFlag(FLAG_MULTI_PAGE));
|
||||
|
||||
|
@ -1067,9 +1031,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
TraceHelper.FLAG_UI_EVENT);
|
||||
super.onResume();
|
||||
|
||||
mHandler.removeCallbacks(mHandleDeferredResume);
|
||||
Utilities.postAsyncCallback(mHandler, mHandleDeferredResume);
|
||||
|
||||
if (!mOnResumeCallbacks.isEmpty()) {
|
||||
final ArrayList<OnResumeCallback> resumeCallbacks = new ArrayList<>(mOnResumeCallbacks);
|
||||
mOnResumeCallbacks.clear();
|
||||
|
@ -1112,10 +1073,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
}
|
||||
}
|
||||
|
||||
public boolean isInState(LauncherState state) {
|
||||
return mStateManager.getState() == state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the previous state, if it exists.
|
||||
*
|
||||
|
@ -1354,8 +1311,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
}
|
||||
};
|
||||
|
||||
protected void onUiChangedWhileSleeping() { }
|
||||
|
||||
private void updateNotificationDots(Predicate<PackageUserKey> updatedDots) {
|
||||
mWorkspace.updateNotificationDots(updatedDots);
|
||||
mAppsView.getAppsStore().updateNotificationDots(updatedDots);
|
||||
|
@ -2720,7 +2675,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
return super.onKeyUp(keyCode, event);
|
||||
}
|
||||
|
||||
protected StateHandler[] createStateHandlers() {
|
||||
protected StateHandler<LauncherState>[] createStateHandlers() {
|
||||
return new StateHandler[] { getAllAppsController(), getWorkspace() };
|
||||
}
|
||||
|
||||
|
|
|
@ -13,11 +13,8 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.launcher3;
|
||||
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
|
@ -57,17 +54,6 @@ public class LauncherAppTransitionManager implements ResourceBasedOverride {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of animations which run on state properties.
|
||||
*/
|
||||
public int getStateElementAnimationsCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Animator createStateElementAnimation(int index, float... values) {
|
||||
throw new RuntimeException("Unknown gesture animation " + index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers remote animations for certain system transitions.
|
||||
*/
|
||||
|
|
|
@ -20,7 +20,6 @@ import static com.android.launcher3.config.FeatureFlags.MULTI_DB_GRID_MIRATION_A
|
|||
import static com.android.launcher3.provider.LauncherDbUtils.copyTable;
|
||||
import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
|
||||
import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
|
||||
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.backup.BackupManager;
|
||||
|
@ -48,7 +47,6 @@ import android.net.Uri;
|
|||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
|
@ -85,6 +83,7 @@ import java.net.URISyntaxException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class LauncherProvider extends ContentProvider {
|
||||
|
@ -92,8 +91,7 @@ public class LauncherProvider extends ContentProvider {
|
|||
private static final boolean LOGD = false;
|
||||
|
||||
private static final String DOWNGRADE_SCHEMA_FILE = "downgrade_schema.json";
|
||||
private static final String TOKEN_RESTORE_BACKUP_TABLE = "restore_backup_table";
|
||||
private static final long RESTORE_BACKUP_TABLE_DELAY = 60000;
|
||||
private static final long RESTORE_BACKUP_TABLE_DELAY = TimeUnit.SECONDS.toMillis(30);
|
||||
|
||||
/**
|
||||
* Represents the schema of the database. Changes in scheme need not be backwards compatible.
|
||||
|
@ -107,6 +105,8 @@ public class LauncherProvider extends ContentProvider {
|
|||
|
||||
protected DatabaseHelper mOpenHelper;
|
||||
|
||||
private long mLastRestoreTimestamp = 0L;
|
||||
|
||||
/**
|
||||
* $ adb shell dumpsys activity provider com.android.launcher3
|
||||
*/
|
||||
|
@ -412,11 +412,12 @@ public class LauncherProvider extends ContentProvider {
|
|||
return null;
|
||||
}
|
||||
case LauncherSettings.Settings.METHOD_RESTORE_BACKUP_TABLE: {
|
||||
final Handler handler = MODEL_EXECUTOR.getHandler();
|
||||
handler.removeCallbacksAndMessages(TOKEN_RESTORE_BACKUP_TABLE);
|
||||
handler.postDelayed(() -> RestoreDbTask.restoreIfPossible(
|
||||
getContext(), mOpenHelper, new BackupManager(getContext())),
|
||||
TOKEN_RESTORE_BACKUP_TABLE, RESTORE_BACKUP_TABLE_DELAY);
|
||||
final long ts = System.currentTimeMillis();
|
||||
if (ts - mLastRestoreTimestamp > RESTORE_BACKUP_TABLE_DELAY) {
|
||||
mLastRestoreTimestamp = ts;
|
||||
RestoreDbTask.restoreIfPossible(
|
||||
getContext(), mOpenHelper, new BackupManager(getContext()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
case LauncherSettings.Settings.METHOD_UPDATE_CURRENT_OPEN_HELPER: {
|
||||
|
|
|
@ -15,19 +15,7 @@
|
|||
*/
|
||||
package com.android.launcher3;
|
||||
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
|
||||
import static com.android.launcher3.anim.Interpolators.clampToProgress;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
|
||||
import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL;
|
||||
import static com.android.launcher3.testing.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
|
||||
import static com.android.launcher3.testing.TestProtocol.HINT_STATE_ORDINAL;
|
||||
|
@ -39,24 +27,22 @@ import static com.android.launcher3.testing.TestProtocol.QUICK_SWITCH_STATE_ORDI
|
|||
import static com.android.launcher3.testing.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import com.android.launcher3.allapps.AllAppsContainerView;
|
||||
import com.android.launcher3.statemanager.BaseState;
|
||||
import com.android.launcher3.statemanager.StateManager;
|
||||
import com.android.launcher3.states.HintState;
|
||||
import com.android.launcher3.states.SpringLoadedState;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.uioverrides.states.AllAppsState;
|
||||
import com.android.launcher3.uioverrides.states.OverviewState;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
/**
|
||||
* Base state for various states used for the Launcher
|
||||
*/
|
||||
public abstract class LauncherState {
|
||||
public abstract class LauncherState implements BaseState<LauncherState> {
|
||||
|
||||
/**
|
||||
* Set of elements indicating various workspace elements which change visibility across states
|
||||
|
@ -76,25 +62,22 @@ public abstract class LauncherState {
|
|||
HOTSEAT_SEARCH_BOX | ALL_APPS_HEADER | ALL_APPS_HEADER_EXTRA | ALL_APPS_CONTENT;
|
||||
|
||||
// Flag indicating workspace has multiple pages visible.
|
||||
public static final int FLAG_MULTI_PAGE = 1 << 0;
|
||||
public static final int FLAG_MULTI_PAGE = BaseState.getFlag(0);
|
||||
// Flag indicating that workspace and its contents are not accessible
|
||||
public static final int FLAG_WORKSPACE_INACCESSIBLE = 1 << 1;
|
||||
public static final int FLAG_WORKSPACE_INACCESSIBLE = BaseState.getFlag(1);
|
||||
|
||||
public static final int FLAG_DISABLE_RESTORE = 1 << 2;
|
||||
// Flag indicating the state allows workspace icons to be dragged.
|
||||
public static final int FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED = 1 << 3;
|
||||
public static final int FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED = BaseState.getFlag(2);
|
||||
// Flag to indicate that workspace should draw page background
|
||||
public static final int FLAG_WORKSPACE_HAS_BACKGROUNDS = 1 << 4;
|
||||
// Flag to indicate that Launcher is non-interactive in this state
|
||||
public static final int FLAG_NON_INTERACTIVE = 1 << 5;
|
||||
public static final int FLAG_WORKSPACE_HAS_BACKGROUNDS = BaseState.getFlag(3);
|
||||
// True if the back button should be hidden when in this state (assuming no floating views are
|
||||
// open, launcher has window focus, etc).
|
||||
public static final int FLAG_HIDE_BACK_BUTTON = 1 << 6;
|
||||
public static final int FLAG_HIDE_BACK_BUTTON = BaseState.getFlag(4);
|
||||
// Flag to indicate if the state would have scrim over sysui region: statu sbar and nav bar
|
||||
public static final int FLAG_HAS_SYS_UI_SCRIM = 1 << 7;
|
||||
public static final int FLAG_HAS_SYS_UI_SCRIM = BaseState.getFlag(5);
|
||||
// Flag to inticate that all popups should be closed when this state is enabled.
|
||||
public static final int FLAG_CLOSE_POPUPS = 1 << 8;
|
||||
public static final int FLAG_OVERVIEW_UI = 1 << 9;
|
||||
public static final int FLAG_CLOSE_POPUPS = BaseState.getFlag(6);
|
||||
public static final int FLAG_OVERVIEW_UI = BaseState.getFlag(7);
|
||||
|
||||
|
||||
public static final float NO_OFFSET = 0;
|
||||
|
@ -167,26 +150,15 @@ public abstract class LauncherState {
|
|||
/**
|
||||
* Returns if the state has the provided flag
|
||||
*/
|
||||
@Override
|
||||
public final boolean hasFlag(int mask) {
|
||||
return (mFlags & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the state can be persisted across activity restarts.
|
||||
*/
|
||||
public final boolean shouldDisableRestore() {
|
||||
return hasFlag(FLAG_DISABLE_RESTORE);
|
||||
}
|
||||
|
||||
public static LauncherState[] values() {
|
||||
return Arrays.copyOf(sAllStates, sAllStates.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return How long the animation to this state should take (or from this state to NORMAL).
|
||||
*/
|
||||
public abstract int getTransitionDuration(Context context);
|
||||
|
||||
public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
|
||||
return new ScaleAndTranslation(NO_SCALE, NO_OFFSET, NO_OFFSET);
|
||||
}
|
||||
|
@ -280,65 +252,22 @@ public abstract class LauncherState {
|
|||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public LauncherState getHistoryForState(LauncherState previousState) {
|
||||
// No history is supported
|
||||
return NORMAL;
|
||||
}
|
||||
|
||||
public void onBackPressed(Launcher launcher) {
|
||||
if (this != NORMAL) {
|
||||
LauncherStateManager lsm = launcher.getStateManager();
|
||||
LauncherState lastState = lsm.getLastState();
|
||||
lsm.goToState(lastState);
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Ordinal-" + ordinal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares for a non-user controlled animation from fromState to this state. Preparations
|
||||
* include:
|
||||
* - Setting interpolators for various animations included in the state transition.
|
||||
* - Setting some start values (e.g. scale) for views that are hidden but about to be shown.
|
||||
*/
|
||||
public void prepareForAtomicAnimation(Launcher launcher, LauncherState fromState,
|
||||
StateAnimationConfig config) {
|
||||
if (this == NORMAL && fromState == OVERVIEW) {
|
||||
config.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL);
|
||||
config.setInterpolator(ANIM_WORKSPACE_FADE, ACCEL);
|
||||
config.setInterpolator(ANIM_OVERVIEW_SCALE, clampToProgress(ACCEL, 0, 0.9f));
|
||||
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL);
|
||||
config.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7);
|
||||
Workspace workspace = launcher.getWorkspace();
|
||||
|
||||
// Start from a higher workspace scale, but only if we're invisible so we don't jump.
|
||||
boolean isWorkspaceVisible = workspace.getVisibility() == VISIBLE;
|
||||
if (isWorkspaceVisible) {
|
||||
CellLayout currentChild = (CellLayout) workspace.getChildAt(
|
||||
workspace.getCurrentPage());
|
||||
isWorkspaceVisible = currentChild.getVisibility() == VISIBLE
|
||||
&& currentChild.getShortcutsAndWidgets().getAlpha() > 0;
|
||||
}
|
||||
if (!isWorkspaceVisible) {
|
||||
workspace.setScaleX(0.92f);
|
||||
workspace.setScaleY(0.92f);
|
||||
}
|
||||
Hotseat hotseat = launcher.getHotseat();
|
||||
boolean isHotseatVisible = hotseat.getVisibility() == VISIBLE && hotseat.getAlpha() > 0;
|
||||
if (!isHotseatVisible) {
|
||||
hotseat.setScaleX(0.92f);
|
||||
hotseat.setScaleY(0.92f);
|
||||
if (ENABLE_OVERVIEW_ACTIONS.get()) {
|
||||
AllAppsContainerView qsbContainer = launcher.getAppsView();
|
||||
View qsb = qsbContainer.getSearchView();
|
||||
boolean qsbVisible = qsb.getVisibility() == VISIBLE && qsb.getAlpha() > 0;
|
||||
if (!qsbVisible) {
|
||||
qsbContainer.setScaleX(0.92f);
|
||||
qsbContainer.setScaleY(0.92f);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (this == NORMAL && fromState == OVERVIEW_PEEK) {
|
||||
// Keep fully visible until the very end (when overview is offscreen) to make invisible.
|
||||
config.setInterpolator(ANIM_OVERVIEW_FADE, t -> t < 1 ? 0 : 1);
|
||||
public void onBackPressed(Launcher launcher) {
|
||||
if (this != NORMAL) {
|
||||
StateManager<LauncherState> lsm = launcher.getStateManager();
|
||||
LauncherState lastState = lsm.getLastState();
|
||||
lsm.goToState(lastState);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,10 @@ import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP
|
|||
import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.DISMISS_PREDICTION;
|
||||
import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.RECONFIGURE;
|
||||
import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.UNINSTALL;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_UNINSTALL;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_UNINSTALL_CANCELLED;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_UNINSTALL_COMPLETED;
|
||||
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_SYSTEM_MASK;
|
||||
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_SYSTEM_NO;
|
||||
|
||||
|
@ -34,6 +38,7 @@ import com.android.launcher3.config.FeatureFlags;
|
|||
import com.android.launcher3.dragndrop.DragOptions;
|
||||
import com.android.launcher3.logging.FileLog;
|
||||
import com.android.launcher3.logging.LoggerUtils;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.model.AppLaunchTracker;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
|
@ -58,7 +63,7 @@ public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmList
|
|||
|
||||
private static final long CACHE_EXPIRE_TIMEOUT = 5000;
|
||||
private final ArrayMap<UserHandle, Boolean> mUninstallDisabledCache = new ArrayMap<>(1);
|
||||
|
||||
private final StatsLogManager mStatsLogManager;
|
||||
private final Alarm mCacheExpireAlarm;
|
||||
private boolean mHadPendingAlarm;
|
||||
|
||||
|
@ -69,8 +74,8 @@ public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmList
|
|||
|
||||
public SecondaryDropTarget(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
mCacheExpireAlarm = new Alarm();
|
||||
mStatsLogManager = StatsLogManager.newInstance(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -214,6 +219,11 @@ public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmList
|
|||
// Defer onComplete
|
||||
d.dragSource = new DeferredOnComplete(d.dragSource, getContext());
|
||||
super.onDrop(d, options);
|
||||
if (mCurrentAccessibilityAction == UNINSTALL) {
|
||||
mStatsLogManager.log(LAUNCHER_ITEM_DROPPED_ON_UNINSTALL, d.logInstanceId);
|
||||
} else if (mCurrentAccessibilityAction == DISMISS_PREDICTION) {
|
||||
mStatsLogManager.log(LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST, d.logInstanceId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -338,8 +348,10 @@ public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmList
|
|||
mDragObject.dragInfo.user, PackageManager.MATCH_UNINSTALLED_PACKAGES) == null) {
|
||||
mDragObject.dragSource = mOriginal;
|
||||
mOriginal.onDropCompleted(SecondaryDropTarget.this, mDragObject, true);
|
||||
mStatsLogManager.log(LAUNCHER_ITEM_UNINSTALL_COMPLETED, mDragObject.logInstanceId);
|
||||
} else {
|
||||
sendFailure();
|
||||
mStatsLogManager.log(LAUNCHER_ITEM_UNINSTALL_CANCELLED, mDragObject.logInstanceId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -89,6 +89,7 @@ import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
|||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.pageindicators.WorkspacePageIndicator;
|
||||
import com.android.launcher3.popup.PopupContainerWithArrow;
|
||||
import com.android.launcher3.statemanager.StateManager.StateHandler;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.touch.WorkspaceTouchListener;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
||||
|
@ -119,7 +120,7 @@ import java.util.function.Predicate;
|
|||
*/
|
||||
public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
implements DropTarget, DragSource, View.OnTouchListener,
|
||||
DragController.DragListener, Insettable, LauncherStateManager.StateHandler,
|
||||
DragController.DragListener, Insettable, StateHandler<LauncherState>,
|
||||
WorkspaceLayoutManager {
|
||||
|
||||
/** The value that {@link #mTransitionProgress} must be greater than for
|
||||
|
@ -416,8 +417,12 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
|||
mLauncher.getStateManager().goToState(SPRING_LOADED);
|
||||
mStatsLogManager.log(
|
||||
LauncherEvent.LAUNCHER_ITEM_DRAG_STARTED,
|
||||
dragObject.mLogInstanceId,
|
||||
dragObject.originalDragInfo.buildProto(null));
|
||||
dragObject.logInstanceId,
|
||||
dragObject.originalDragInfo.buildProto(
|
||||
dragObject.dragSource instanceof Folder
|
||||
? ((Folder) dragObject.dragSource).mInfo
|
||||
: null)
|
||||
);
|
||||
}
|
||||
|
||||
public void deferRemoveExtraEmptyScreen() {
|
||||
|
@ -1437,6 +1442,10 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
|||
|
||||
mOutlineProvider = previewProvider;
|
||||
|
||||
if (draggableView == null && child instanceof DraggableView) {
|
||||
draggableView = (DraggableView) child;
|
||||
}
|
||||
|
||||
// The drag bitmap follows the touch point around on the screen
|
||||
final Bitmap b = previewProvider.createDragBitmap();
|
||||
int halfPadding = previewProvider.previewPadding / 2;
|
||||
|
@ -1447,12 +1456,8 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
|||
Point dragVisualizeOffset = null;
|
||||
Rect dragRect = new Rect();
|
||||
|
||||
if (draggableView == null && child instanceof DraggableView) {
|
||||
draggableView = (DraggableView) child;
|
||||
}
|
||||
|
||||
if (draggableView != null) {
|
||||
draggableView.getVisualDragBounds(dragRect);
|
||||
draggableView.getSourceVisualDragBounds(dragRect);
|
||||
dragLayerY += dragRect.top;
|
||||
dragVisualizeOffset = new Point(- halfPadding, halfPadding);
|
||||
}
|
||||
|
@ -1645,7 +1650,10 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
|||
Rect folderLocation = new Rect();
|
||||
float scale = mLauncher.getDragLayer().getDescendantRectRelativeToSelf(v, folderLocation);
|
||||
target.removeView(v);
|
||||
|
||||
mStatsLogManager.log(
|
||||
LauncherEvent.LAUNCHER_ITEM_DROP_FOLDER_CREATED,
|
||||
d.logInstanceId,
|
||||
destInfo.buildProto(null));
|
||||
FolderIcon fi = mLauncher.addFolder(target, container, screenId, targetCell[0],
|
||||
targetCell[1]);
|
||||
destInfo.cellX = -1;
|
||||
|
@ -1683,6 +1691,10 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
|||
if (dropOverView instanceof FolderIcon) {
|
||||
FolderIcon fi = (FolderIcon) dropOverView;
|
||||
if (fi.acceptDrop(d.dragInfo)) {
|
||||
mStatsLogManager.log(
|
||||
LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED,
|
||||
d.logInstanceId,
|
||||
fi.mInfo.buildProto(null));
|
||||
fi.onDrop(d, false /* itemReturnedOnFailedDrop */);
|
||||
|
||||
// if the drag started here, we need to remove it from the workspace
|
||||
|
@ -1885,15 +1897,15 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
|||
|
||||
mLauncher.getStateManager().goToState(
|
||||
NORMAL, SPRING_LOADED_EXIT_DELAY, onCompleteRunnable);
|
||||
mStatsLogManager.log(
|
||||
LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED,
|
||||
d.logInstanceId,
|
||||
d.dragInfo.buildProto(null));
|
||||
}
|
||||
|
||||
if (d.stateAnnouncer != null && !droppedOnOriginalCell) {
|
||||
d.stateAnnouncer.completeAction(R.string.item_moved);
|
||||
}
|
||||
mStatsLogManager.log(
|
||||
LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED,
|
||||
d.mLogInstanceId,
|
||||
d.dragInfo.buildProto(null));
|
||||
}
|
||||
|
||||
public void onNoCellFound(View dropTargetLayout) {
|
||||
|
@ -2515,6 +2527,10 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
|||
resetTransitionTransform();
|
||||
}
|
||||
}
|
||||
mStatsLogManager.log(
|
||||
LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED,
|
||||
d.logInstanceId,
|
||||
d.dragInfo.buildProto(null));
|
||||
}
|
||||
|
||||
public Bitmap createWidgetBitmap(ItemInfo widgetInfo, View layout) {
|
||||
|
|
|
@ -66,7 +66,7 @@ public class WorkspaceStateTransitionAnimation {
|
|||
}
|
||||
|
||||
/**
|
||||
* @see com.android.launcher3.LauncherStateManager.StateHandler#setStateWithAnimation
|
||||
* @see com.android.launcher3.statemanager.StateManager.StateHandler#setStateWithAnimation
|
||||
*/
|
||||
public void setStateWithAnimation(
|
||||
LauncherState toState, StateAnimationConfig config, PendingAnimation animation) {
|
||||
|
|
|
@ -28,11 +28,11 @@ import com.android.launcher3.DeviceProfile;
|
|||
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager.StateHandler;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.anim.PropertySetter;
|
||||
import com.android.launcher3.statemanager.StateManager.StateHandler;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
|
||||
import com.android.launcher3.util.Themes;
|
||||
|
@ -50,8 +50,8 @@ import com.android.systemui.plugins.PluginListener;
|
|||
* If release velocity < THRES1, snap according to either top or bottom depending on whether it's
|
||||
* closer to top or closer to the page indicator.
|
||||
*/
|
||||
public class AllAppsTransitionController implements StateHandler, OnDeviceProfileChangeListener,
|
||||
PluginListener<AllAppsSearchPlugin> {
|
||||
public class AllAppsTransitionController implements StateHandler<LauncherState>,
|
||||
OnDeviceProfileChangeListener, PluginListener<AllAppsSearchPlugin> {
|
||||
|
||||
public static final FloatProperty<AllAppsTransitionController> ALL_APPS_PROGRESS =
|
||||
new FloatProperty<AllAppsTransitionController>("allAppsProgress") {
|
||||
|
|
|
@ -31,9 +31,9 @@ import android.view.MotionEvent;
|
|||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager.StateListener;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.statemanager.StateManager.StateListener;
|
||||
import com.android.launcher3.util.OnboardingPrefs;
|
||||
|
||||
/**
|
||||
|
@ -46,7 +46,7 @@ public class DiscoveryBounce extends AbstractFloatingView {
|
|||
private final Launcher mLauncher;
|
||||
private final Animator mDiscoBounceAnimation;
|
||||
|
||||
private final StateListener mStateListener = new StateListener() {
|
||||
private final StateListener<LauncherState> mStateListener = new StateListener<LauncherState>() {
|
||||
@Override
|
||||
public void onStateTransitionStart(LauncherState toState) {
|
||||
handleClose(false);
|
||||
|
|
|
@ -22,7 +22,7 @@ import android.view.MotionEvent;
|
|||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager;
|
||||
import com.android.launcher3.statemanager.StateManager.StateListener;
|
||||
import com.android.launcher3.views.WorkEduView;
|
||||
|
||||
/**
|
||||
|
@ -32,7 +32,7 @@ public class LauncherAllAppsContainerView extends AllAppsContainerView {
|
|||
|
||||
private final Launcher mLauncher;
|
||||
|
||||
private LauncherStateManager.StateListener mWorkTabListener;
|
||||
private StateListener<LauncherState> mWorkTabListener;
|
||||
|
||||
public LauncherAllAppsContainerView(Context context) {
|
||||
this(context, null);
|
||||
|
|
|
@ -105,6 +105,13 @@ public class PendingAnimation implements PropertySetter {
|
|||
add(anim);
|
||||
}
|
||||
|
||||
public <T> void addFloat(T target, FloatProperty<T> property, float from, float to,
|
||||
TimeInterpolator interpolator) {
|
||||
Animator anim = ObjectAnimator.ofFloat(target, property, from, to);
|
||||
anim.setDuration(mDuration).setInterpolator(interpolator);
|
||||
add(anim);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void setInt(T target, IntProperty<T> property, int value,
|
||||
TimeInterpolator interpolator) {
|
||||
|
|
|
@ -186,8 +186,7 @@ public class DragController implements DragDriver.EventListener, TouchController
|
|||
|
||||
mDragObject.dragSource = source;
|
||||
mDragObject.dragInfo = dragInfo;
|
||||
mDragObject.originalDragInfo = new ItemInfo();
|
||||
mDragObject.originalDragInfo.copyFrom(dragInfo);
|
||||
mDragObject.originalDragInfo = mDragObject.dragInfo.makeShallowCopy();
|
||||
|
||||
if (dragOffset != null) {
|
||||
dragView.setDragVisualizeOffset(new Point(dragOffset));
|
||||
|
|
|
@ -274,19 +274,29 @@ public class DragLayer extends BaseDragLayer<Launcher> {
|
|||
scale *= childScale;
|
||||
int toX = Math.round(coord[0]);
|
||||
int toY = Math.round(coord[1]);
|
||||
|
||||
float toScale = scale;
|
||||
|
||||
if (child instanceof DraggableView) {
|
||||
// This code is fairly subtle. Please verify drag and drop is pixel-perfect in a number
|
||||
// of scenarios before modifying (from all apps, from workspace, different grid-sizes,
|
||||
// shortcuts from in and out of Launcher etc).
|
||||
DraggableView d = (DraggableView) child;
|
||||
d.getVisualDragBounds(dragViewBounds);
|
||||
Rect destRect = new Rect();
|
||||
d.getWorkspaceVisualDragBounds(destRect);
|
||||
|
||||
// In most cases this additional scale factor should be a no-op (1). It mainly accounts
|
||||
// for alternate grids where the source and destination icon sizes are different
|
||||
toScale *= ((1f * destRect.width())
|
||||
/ (dragView.getMeasuredWidth() - dragView.getBlurSizeOutline()));
|
||||
|
||||
// This accounts for the offset of the DragView created by scaling it about its
|
||||
// center as it animates into place.
|
||||
float scaleShiftX = dragView.getMeasuredWidth() * (1 - scale) / 2;
|
||||
float scaleShiftY = dragView.getMeasuredHeight() * (1 - scale) / 2;
|
||||
float scaleShiftX = dragView.getMeasuredWidth() * (1 - toScale) / 2;
|
||||
float scaleShiftY = dragView.getMeasuredHeight() * (1 - toScale) / 2;
|
||||
|
||||
toX += scale * (dragViewBounds.left - dragView.getBlurSizeOutline() / 2) - scaleShiftX;
|
||||
toY += scale * (dragViewBounds.top - dragView.getBlurSizeOutline() / 2) - scaleShiftY;
|
||||
toX += scale * destRect.left - toScale * dragView.getBlurSizeOutline() / 2 - scaleShiftX;
|
||||
toY += scale * destRect.top - toScale * dragView.getBlurSizeOutline() / 2 - scaleShiftY;
|
||||
}
|
||||
|
||||
child.setVisibility(INVISIBLE);
|
||||
|
|
|
@ -49,18 +49,18 @@ import com.android.launcher3.FirstFrameAnimatorHelper;
|
|||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.icons.LauncherIcons;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.statemanager.StateManager.StateListener;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class DragView extends View implements LauncherStateManager.StateListener {
|
||||
public class DragView extends View implements StateListener<LauncherState> {
|
||||
private static final ColorMatrix sTempMatrix1 = new ColorMatrix();
|
||||
private static final ColorMatrix sTempMatrix2 = new ColorMatrix();
|
||||
|
||||
|
|
|
@ -18,6 +18,10 @@ package com.android.launcher3.dragndrop;
|
|||
|
||||
import android.graphics.Rect;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.launcher3.util.SafeCloseable;
|
||||
|
||||
/**
|
||||
* Interface defining methods required for drawing and previewing DragViews, drag previews, and
|
||||
* related animations
|
||||
|
@ -42,9 +46,12 @@ public interface DraggableView {
|
|||
int getViewType();
|
||||
|
||||
/**
|
||||
* Before rendering as a DragView bitmap, some views need a preparation step.
|
||||
* Before rendering as a DragView bitmap, some views need a preparation step. Returns a
|
||||
* callback to clear any preparation work
|
||||
*/
|
||||
default void prepareDrawDragView() { }
|
||||
@NonNull default SafeCloseable prepareDrawDragView() {
|
||||
return () -> { };
|
||||
}
|
||||
|
||||
/**
|
||||
* If an actual View subclass, this method returns the rectangle (within the View's coordinates)
|
||||
|
@ -53,5 +60,14 @@ public interface DraggableView {
|
|||
*
|
||||
* @param bounds Visual bounds in the views coordinates will be written here.
|
||||
*/
|
||||
default void getVisualDragBounds(Rect bounds) { }
|
||||
default void getWorkspaceVisualDragBounds(Rect bounds) { }
|
||||
|
||||
/**
|
||||
* Same as above, but accounts for differing icon sizes between source and destination
|
||||
*
|
||||
* @param bounds Visual bounds in the views coordinates will be written here.
|
||||
*/
|
||||
default void getSourceVisualDragBounds(Rect bounds) {
|
||||
getWorkspaceVisualDragBounds(bounds);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,6 +87,7 @@ import com.android.launcher3.dragndrop.DragController;
|
|||
import com.android.launcher3.dragndrop.DragController.DragListener;
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
import com.android.launcher3.dragndrop.DragOptions;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.FolderInfo.FolderListener;
|
||||
|
@ -1346,6 +1347,10 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
|||
if (d.stateAnnouncer != null) {
|
||||
d.stateAnnouncer.completeAction(R.string.item_moved);
|
||||
}
|
||||
StatsLogManager.newInstance(getContext())
|
||||
.log(StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED,
|
||||
d.logInstanceId,
|
||||
d.dragInfo.buildProto(mInfo));
|
||||
}
|
||||
|
||||
// This is used so the item doesn't immediately appear in the folder when added. In one case
|
||||
|
|
|
@ -53,6 +53,7 @@ import com.android.launcher3.R;
|
|||
import com.android.launcher3.Reorderable;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.allapps.AllAppsContainerView;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.dot.FolderDotInfo;
|
||||
|
@ -85,7 +86,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
|
|||
|
||||
@Thunk ActivityContext mActivity;
|
||||
@Thunk Folder mFolder;
|
||||
private FolderInfo mInfo;
|
||||
public FolderInfo mInfo;
|
||||
|
||||
private CheckLongPressHelper mLongPressHelper;
|
||||
|
||||
|
@ -385,6 +386,14 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
|
|||
float finalAlpha = index < MAX_NUM_ITEMS_IN_PREVIEW ? 0.5f : 0f;
|
||||
|
||||
float finalScale = scale * scaleRelativeToDragLayer;
|
||||
|
||||
// Account for potentially different icon sizes with non-default grid settings
|
||||
if (d.dragSource instanceof AllAppsContainerView) {
|
||||
DeviceProfile grid = mActivity.getDeviceProfile();
|
||||
float containerScale = (1f * grid.iconSizePx / grid.allAppsIconSizePx);
|
||||
finalScale *= containerScale;
|
||||
}
|
||||
|
||||
dragLayer.animateView(animateView, from, to, finalAlpha,
|
||||
1, 1, finalScale, finalScale, DROP_IN_ANIMATION_DURATION,
|
||||
Interpolators.DEACCEL_2, Interpolators.ACCEL_2,
|
||||
|
@ -758,7 +767,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
|
|||
}
|
||||
|
||||
@Override
|
||||
public void getVisualDragBounds(Rect bounds) {
|
||||
public void getWorkspaceVisualDragBounds(Rect bounds) {
|
||||
getPreviewBounds(bounds);
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue