Merging ub-launcher3-qt-dev, build 5642962

Test: Manual

Bug:122345781 P1 Inflation happens and a binder call during swipe up gesture, that may cause jank
Bug:123900446 P1 App to home animation should zoom into the app icon
Bug:132209249 P1 Gesture bar interferes with Messenger chat heads.
Bug:132815672 P1 -1 to home swipe up gesture
Bug:132886768 P1 Swipe home animation sometimes drops frames
Bug:133009122 P2 Rare flake: dragged launchable to workspace, but the current state is not WORKSPACE; Can't find a launcher object; selector: BySelector [RES='\Qcom.google.android.apps.nexuslauncher:id/apps_view\E']
Bug:133226418 P1 [Gesture Nav] App launch animation has has incorrect origin when launched in Overview
Bug:133508173 P1 App switching is very janky on QT
Bug:133871965 P1 (V35 20190528.00_RC00):Unable to unlock/minimize phone app during ongoing call
Bug:134095068 P1 Shouldn't use seamless rotation in another case
Bug:134166337 P1 3P Launcher Breaks Overview (Standalone)
Bug:134172603 P1 Tracing for lab-only flakes
Bug:134517106 P1 Swipe up to home should fade out scrim
Bug:134532571 P1 Launcher flake: java.lang.AssertionError: http://go/tapl : want to switch from background to overview, but the current state is not BASE_OVERVIEW; Can't find a launcher object; selector: BySelector [RES='\Qcom.google.android.apps.nexuslauncher:id/overview_panel\E']
Bug:134674880 P1 App group name in expanded view is invisible with white wallpaper
Change-Id: I9bca7db0f03bd4c0581ce946646bf5209e8f6c79
This commit is contained in:
Winson Chung
2019-06-07 13:36:20 -07:00
50 changed files with 671 additions and 577 deletions
@@ -121,12 +121,16 @@ public final class LauncherAppTransitionManagerImpl extends QuickstepAppTransiti
alpha.setDuration(CONTENT_ALPHA_DURATION);
alpha.setInterpolator(LINEAR);
anim.play(alpha);
overview.setFreezeViewVisibility(true);
ObjectAnimator transY = ObjectAnimator.ofFloat(overview, View.TRANSLATION_Y, trans);
transY.setInterpolator(AGGRESSIVE_EASE);
transY.setDuration(CONTENT_TRANSLATION_DURATION);
anim.play(transY);
return mLauncher.getStateManager()::reapplyState;
return () -> {
overview.setFreezeViewVisibility(false);
mLauncher.getStateManager().reapplyState();
};
}
}
@@ -204,15 +204,6 @@ public abstract class RecentsUiFactory {
}
}
/**
* Clean-up logic that occurs when recents is no longer in use/visible.
*
* @param launcher the launcher activity
*/
public static void resetOverview(Launcher launcher) {
launcher.<RecentsView>getOverviewPanel().reset();
}
/**
* Recents logic that triggers when launcher state changes or launcher activity stops/resumes.
*
@@ -32,7 +32,6 @@ import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.PropertySetter;
import com.android.quickstep.hints.ProactiveHintsContainer;
import com.android.quickstep.views.ClearAllButton;
import com.android.quickstep.views.LauncherRecentsView;
import com.android.quickstep.views.RecentsView;
@@ -55,14 +54,6 @@ public final class RecentsViewStateController extends
if (state.overviewUi) {
mRecentsView.updateEmptyMessage();
mRecentsView.resetTaskVisuals();
mRecentsView.setHintVisibility(1f);
} else {
mRecentsView.setHintVisibility(0f);
ProactiveHintsContainer
proactiveHintsContainer = mRecentsView.getProactiveHintsContainer();
if (proactiveHintsContainer != null) {
proactiveHintsContainer.removeAllViews();
}
}
setAlphas(PropertySetter.NO_ANIM_PROPERTY_SETTER, state.getVisibleElements(mLauncher));
mRecentsView.setFullscreenProgress(state.getOverviewFullscreenProgress());
@@ -75,14 +66,6 @@ public final class RecentsViewStateController extends
if (!toState.overviewUi) {
builder.addOnFinishRunnable(mRecentsView::resetTaskVisuals);
mRecentsView.setHintVisibility(0f);
builder.addOnFinishRunnable(() -> {
ProactiveHintsContainer
proactiveHintsContainer = mRecentsView.getProactiveHintsContainer();
if (proactiveHintsContainer != null) {
proactiveHintsContainer.removeAllViews();
}
});
}
if (toState.overviewUi) {
@@ -94,7 +77,6 @@ public final class RecentsViewStateController extends
updateAnim.setDuration(config.duration);
builder.play(updateAnim);
mRecentsView.updateEmptyMessage();
builder.addOnFinishRunnable(() -> mRecentsView.setHintVisibility(1f));
}
PropertySetter propertySetter = config.getPropertySetter(builder);
@@ -21,7 +21,6 @@ import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
@@ -45,8 +44,6 @@ public class BackgroundAppState extends OverviewState {
@Override
public void onStateEnabled(Launcher launcher) {
RecentsView rv = launcher.getOverviewPanel();
rv.setOverviewStateEnabled(true);
AbstractFloatingView.closeAllOpenViews(launcher, false);
}
@@ -86,17 +86,9 @@ public class OverviewState extends LauncherState {
@Override
public void onStateEnabled(Launcher launcher) {
RecentsView rv = launcher.getOverviewPanel();
rv.setOverviewStateEnabled(true);
AbstractFloatingView.closeAllOpenViews(launcher);
}
@Override
public void onStateDisabled(Launcher launcher) {
RecentsView rv = launcher.getOverviewPanel();
rv.setOverviewStateEnabled(false);
}
@Override
public void onStateTransitionEnd(Launcher launcher) {
launcher.getRotationHelper().setCurrentStateRequest(REQUEST_ROTATE);
@@ -98,9 +98,6 @@ public class NavBarToHomeTouchController implements TouchController, SwipeDetect
if (mStartState == OVERVIEW || mStartState == ALL_APPS) {
return true;
}
if (!mLauncher.hasWindowFocus()) {
return true;
}
if (AbstractFloatingView.getTopOpenView(mLauncher) != null) {
return true;
}
@@ -17,6 +17,7 @@ package com.android.quickstep;
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.views.RecentsView.CONTENT_ALPHA;
import android.animation.Animator;
@@ -33,6 +34,7 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.views.RecentsView;
@@ -120,11 +122,14 @@ public final class FallbackActivityControllerHelper implements
return (transitionLength) -> { };
}
RecentsView rv = activity.getOverviewPanel();
FallbackRecentsView rv = activity.getOverviewPanel();
rv.setContentAlpha(0);
rv.getClearAllButton().setVisibilityAlpha(0);
rv.setDisallowScrollToClearAll(true);
boolean fromState = !animateActivity;
rv.setInOverviewState(fromState);
return new AnimationFactory() {
boolean isAnimatingToRecents = false;
@@ -141,15 +146,28 @@ public final class FallbackActivityControllerHelper implements
@Override
public void createActivityController(long transitionLength) {
if (!isAnimatingToRecents) {
return;
AnimatorSet animatorSet = new AnimatorSet();
if (isAnimatingToRecents) {
ObjectAnimator anim = ObjectAnimator.ofFloat(rv, CONTENT_ALPHA, 0, 1);
anim.setDuration(transitionLength).setInterpolator(LINEAR);
animatorSet.play(anim);
}
ObjectAnimator anim = ObjectAnimator.ofFloat(rv, CONTENT_ALPHA, 0, 1);
ObjectAnimator anim = ObjectAnimator.ofFloat(rv, ZOOM_PROGRESS, 1, 0);
anim.setDuration(transitionLength).setInterpolator(LINEAR);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(anim);
callback.accept(AnimatorPlaybackController.wrap(animatorSet, transitionLength));
AnimatorPlaybackController controller =
AnimatorPlaybackController.wrap(animatorSet, transitionLength);
// 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);
});
callback.accept(controller);
}
};
}
@@ -36,6 +36,7 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.os.UserHandle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Interpolator;
@@ -53,6 +54,7 @@ import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.SpringObjectAnimator;
import com.android.launcher3.compat.AccessibilityManagerCompat;
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;
@@ -174,6 +176,9 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
@Override
public AnimationFactory prepareRecentsUI(Launcher activity, boolean activityVisible,
boolean animateActivity, Consumer<AnimatorPlaybackController> callback) {
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "prepareRecentsUI");
}
final LauncherState startState = activity.getStateManager().getState();
LauncherState resetState = startState;
@@ -125,7 +125,14 @@ public final class RecentsActivity extends BaseRecentsActivity {
@Override
public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats,
AnimationResult result) {
result.setAnimation(composeRecentsLaunchAnimator(taskView, targetCompats));
AnimatorSet anim = composeRecentsLaunchAnimator(taskView, targetCompats);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mFallbackRecentsView.resetViewUI();
}
});
result.setAnimation(anim);
}
};
return ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat(
@@ -36,8 +36,6 @@ import java.util.List;
*/
public class TaskOverlayFactory implements ResourceBasedOverride {
public static final String AIAI_PACKAGE = "com.google.android.as";
/** Note that these will be shown in order from top to bottom, if available for the task. */
private static final TaskSystemShortcut[] MENU_OPTIONS = new TaskSystemShortcut[]{
new TaskSystemShortcut.AppInfo(),
@@ -51,29 +49,33 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
new MainThreadInitializedObject<>(c -> Overrides.getObject(TaskOverlayFactory.class,
c, R.string.task_overlay_factory_class));
public List<TaskSystemShortcut> getEnabledShortcuts(TaskView taskView) {
final ArrayList<TaskSystemShortcut> shortcuts = new ArrayList<>();
final BaseDraggingActivity activity = BaseActivity.fromContext(taskView.getContext());
for (TaskSystemShortcut menuOption : MENU_OPTIONS) {
View.OnClickListener onClickListener =
menuOption.getOnClickListener(activity, taskView);
if (onClickListener != null) {
shortcuts.add(menuOption);
}
}
return shortcuts;
}
public TaskOverlay createOverlay(View thumbnailView) {
return new TaskOverlay();
}
public static class TaskOverlay {
public void setTaskInfo(Task task, ThumbnailData thumbnail, Matrix matrix) {
}
/**
* Called when the current task is interactive for the user
*/
public void initOverlay(Task task, ThumbnailData thumbnail, Matrix matrix) { }
public void reset() {
}
public List<TaskSystemShortcut> getEnabledShortcuts(TaskView taskView) {
final ArrayList<TaskSystemShortcut> shortcuts = new ArrayList<>();
final BaseDraggingActivity activity = BaseActivity.fromContext(taskView.getContext());
for (TaskSystemShortcut menuOption : MENU_OPTIONS) {
View.OnClickListener onClickListener =
menuOption.getOnClickListener(activity, taskView);
if (onClickListener != null) {
shortcuts.add(menuOption);
}
}
return shortcuts;
}
/**
* Called when the overlay is no longer used.
*/
public void reset() { }
}
}
@@ -27,6 +27,8 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_N
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
import android.annotation.TargetApi;
import android.app.ActivityManager;
@@ -60,6 +62,7 @@ import android.view.WindowManager;
import androidx.annotation.BinderThread;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
import com.android.launcher3.ResourceUtils;
@@ -77,6 +80,7 @@ import com.android.quickstep.inputconsumers.DeviceLockedInputConsumer;
import com.android.quickstep.inputconsumers.InputConsumer;
import com.android.quickstep.inputconsumers.OtherActivityInputConsumer;
import com.android.quickstep.inputconsumers.OverviewInputConsumer;
import com.android.quickstep.inputconsumers.OverviewWithoutFocusInputConsumer;
import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
@@ -543,9 +547,11 @@ public class TouchInteractionService extends Service implements
if (!useSharedState) {
mSwipeSharedState.clearAllState();
}
if (mKM.isDeviceLocked()) {
if ((mSystemUiStateFlags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED) != 0
|| mKM.isDeviceLocked()) {
// This handles apps launched in direct boot mode (e.g. dialer) as well as apps launched
// while device is locked even after exiting direct boot mode (e.g. camera).
// while device is locked after exiting direct boot mode (e.g. camera), or if the
// app is showing over the lockscreen (even if not locked)
return createDeviceLockedInputConsumer(runningTaskInfo);
}
@@ -562,10 +568,9 @@ public class TouchInteractionService extends Service implements
info.id = mSwipeSharedState.nextRunningTaskId;
return createOtherActivityInputConsumer(event, info);
} else if (mSwipeSharedState.goingToLauncher || activityControl.isResumed()) {
return OverviewInputConsumer.newInstance(activityControl, mInputMonitorCompat, false);
} else if (ENABLE_QUICKSTEP_LIVE_TILE.get() &&
activityControl.isInLiveTileMode()) {
return OverviewInputConsumer.newInstance(activityControl, mInputMonitorCompat, false);
return createOverviewInputConsumer(event);
} else if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityControl.isInLiveTileMode()) {
return createOverviewInputConsumer(event);
} else if (mGestureBlockingActivity != null && runningTaskInfo != null
&& mGestureBlockingActivity.equals(runningTaskInfo.topActivity)) {
return InputConsumer.NO_OP;
@@ -574,20 +579,24 @@ public class TouchInteractionService extends Service implements
}
}
private boolean disableHorizontalSwipe(MotionEvent event) {
// mExclusionRegion can change on binder thread, use a local instance here.
Region exclusionRegion = mExclusionRegion;
return mMode == Mode.NO_BUTTON && exclusionRegion != null
&& exclusionRegion.contains((int) event.getX(), (int) event.getY());
}
private OtherActivityInputConsumer createOtherActivityInputConsumer(MotionEvent event,
RunningTaskInfo runningTaskInfo) {
final ActivityControlHelper activityControl =
mOverviewComponentObserver.getActivityControlHelper();
boolean shouldDefer = activityControl.deferStartingActivity(mActiveNavBarRegion, event);
// mExclusionRegion can change on binder thread, use a local instance here.
Region exclusionRegion = mExclusionRegion;
boolean disableHorizontalSwipe = mMode == Mode.NO_BUTTON && exclusionRegion != null
&& exclusionRegion.contains((int) event.getX(), (int) event.getY());
return new OtherActivityInputConsumer(this, runningTaskInfo, mRecentsModel,
mOverviewComponentObserver.getOverviewIntent(), activityControl,
shouldDefer, mOverviewCallbacks, mInputConsumer, this::onConsumerInactive,
mSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion, disableHorizontalSwipe);
mSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion,
disableHorizontalSwipe(event));
}
private InputConsumer createDeviceLockedInputConsumer(RunningTaskInfo taskInfo) {
@@ -599,6 +608,23 @@ public class TouchInteractionService extends Service implements
}
}
public InputConsumer createOverviewInputConsumer(MotionEvent event) {
final ActivityControlHelper activityControl =
mOverviewComponentObserver.getActivityControlHelper();
BaseDraggingActivity activity = activityControl.getCreatedActivity();
if (activity == null) {
return InputConsumer.NO_OP;
}
if (activity.getRootView().hasWindowFocus()) {
return new OverviewInputConsumer(activity, mInputMonitorCompat,
false /* startingInActivityBounds */);
} else {
return new OverviewWithoutFocusInputConsumer(this, mInputMonitorCompat,
disableHorizontalSwipe(event));
}
}
/**
* To be called by the consumer when it's no longer active.
*/
@@ -59,6 +59,7 @@ import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
@@ -83,6 +84,7 @@ import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.graphics.RotationMode;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -267,6 +269,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
private MultiStateCallback mStateCallback;
// Used to control launcher components throughout the swipe gesture.
private AnimatorPlaybackController mLauncherTransitionController;
private boolean mHasLauncherTransitionControllerStarted;
private T mActivity;
private RecentsView mRecentsView;
@@ -457,17 +460,32 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
}
private void onLauncherStart(final T activity) {
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart");
}
if (mActivity != activity) {
return;
}
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart 1");
}
if (mStateCallback.hasStates(STATE_HANDLER_INVALIDATED)) {
return;
}
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart 2");
}
// If we've already ended the gesture and are going home, don't prepare recents UI,
// as that will set the state as BACKGROUND_APP, overriding the animation to NORMAL.
if (mGestureEndTarget != HOME) {
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart 3");
}
Runnable initAnimFactory = () -> {
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart 4");
}
mAnimationFactory = mActivityControlHelper.prepareRecentsUI(mActivity,
mWasLauncherAlreadyVisible, true,
this::onAnimatorPlaybackControllerCreated);
@@ -477,8 +495,14 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
// Launcher is visible, but might be about to stop. Thus, if we prepare recents
// now, it might get overridden by moveToRestState() in onStop(). To avoid this,
// wait until the next gesture (and possibly launcher) starts.
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart 5");
}
mStateCallback.addCallback(STATE_GESTURE_STARTED, initAnimFactory);
} else {
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart 6");
}
initAnimFactory.run();
}
}
@@ -647,8 +671,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
}
private void buildAnimationController() {
if (mGestureEndTarget == HOME || (mLauncherTransitionController != null
&& mLauncherTransitionController.getAnimationPlayer().isStarted())) {
if (mGestureEndTarget == HOME || mHasLauncherTransitionControllerStarted) {
// We don't want a new mLauncherTransitionController if mGestureEndTarget == HOME (it
// has its own animation) or if we're already animating the current controller.
return;
@@ -858,7 +881,9 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
setTargetAlphaProvider(WindowTransformSwipeHandler::getHiddenTargetAlpha);
}
return OverviewInputConsumer.newInstance(mActivityControlHelper, null, true);
BaseDraggingActivity activity = mActivityControlHelper.getCreatedActivity();
return activity == null
? InputConsumer.NO_OP : new OverviewInputConsumer(activity, null, true);
}
private void endRunningWindowAnim() {
@@ -1122,6 +1147,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
}
mLauncherTransitionController.getAnimationPlayer().start();
}
mHasLauncherTransitionControllerStarted = true;
}
/**
@@ -15,19 +15,45 @@
*/
package com.android.quickstep.fallback;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.FloatProperty;
import android.view.View;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherState.ScaleAndTranslation;
import com.android.launcher3.Utilities;
import com.android.quickstep.RecentsActivity;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
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;
private float mZoomTranslationY = 0f;
public FallbackRecentsView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@@ -35,6 +61,7 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> {
public FallbackRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setOverviewStateEnabled(true);
setOverlayEnabled(true);
}
@Override
@@ -70,4 +97,46 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> {
// 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
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (getTaskViewCount() == 0) {
mZoomScale = 1f;
mZoomTranslationY = 0f;
} else {
TaskView dummyTask = getTaskViewAt(0);
ScaleAndTranslation sat = getTempClipAnimationHelper()
.updateForFullscreenOverview(dummyTask)
.getScaleAndTranslation();
mZoomScale = sat.scale;
mZoomTranslationY = sat.translationY;
}
setZoomProgress(mZoomInProgress);
}
public void setZoomProgress(float progress) {
mZoomInProgress = progress;
SCALE_PROPERTY.set(this, Utilities.mapRange(mZoomInProgress, 1, mZoomScale));
TRANSLATION_Y.set(this, Utilities.mapRange(mZoomInProgress, 0, mZoomTranslationY));
FULLSCREEN_PROGRESS.set(this, mZoomInProgress);
}
}
@@ -1,78 +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.hints;
import android.app.PendingIntent;
import android.graphics.drawable.Icon;
import android.os.Bundle;
public final class HintUtil {
public static final String ID_KEY = "id";
public static final String ICON_KEY = "icon";
public static final String TEXT_KEY = "text";
public static final String TAP_ACTION_KEY = "tap_action";
private HintUtil() {}
public static Bundle makeHint(String id, Icon icon, CharSequence text) {
Bundle hint = new Bundle();
hint.putString(ID_KEY, id);
hint.putParcelable(ICON_KEY, icon);
hint.putCharSequence(TEXT_KEY, text);
return hint;
}
public static Bundle makeHint(Icon icon, CharSequence text, PendingIntent tapAction) {
Bundle hint = new Bundle();
hint.putParcelable(ICON_KEY, icon);
hint.putCharSequence(TEXT_KEY, text);
hint.putParcelable(TAP_ACTION_KEY, tapAction);
return hint;
}
public static String getId(Bundle hint) {
String id = hint.getString(ID_KEY);
if (id == null) {
throw new IllegalArgumentException("Hint does not contain an ID");
}
return id;
}
public static Icon getIcon(Bundle hint) {
Icon icon = hint.getParcelable(ICON_KEY);
if (icon == null) {
throw new IllegalArgumentException("Hint does not contain an icon");
}
return icon;
}
public static CharSequence getText(Bundle hint) {
CharSequence text = hint.getCharSequence(TEXT_KEY);
if (text == null) {
throw new IllegalArgumentException("Hint does not contain text");
}
return text;
}
public static PendingIntent getTapAction(Bundle hint) {
PendingIntent tapAction = hint.getParcelable(TAP_ACTION_KEY);
if (tapAction == null) {
throw new IllegalArgumentException("Hint does not contain a tap action");
}
return tapAction;
}
}
@@ -1,71 +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.hints;
import static com.android.quickstep.hints.HintUtil.getIcon;
import static com.android.quickstep.hints.HintUtil.getText;
import android.content.Context;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.android.launcher3.R;
public class HintView extends LinearLayout {
private ImageView mIconView;
private TextView mLabelView;
public HintView(Context context) {
super(context);
}
public HintView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public HintView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public HintView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public void setHint(Bundle hint) {
mLabelView.setText(getText(hint));
Icon icon = getIcon(hint);
if (icon == null) {
mIconView.setVisibility(GONE);
} else {
mIconView.setImageIcon(icon);
mIconView.setVisibility(VISIBLE);
}
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mIconView = findViewById(R.id.icon);
mLabelView = findViewById(R.id.label);
}
}
@@ -1,55 +0,0 @@
package com.android.quickstep.hints;
import android.content.Context;
import android.util.AttributeSet;
import android.util.FloatProperty;
import android.view.View;
import android.widget.FrameLayout;
public class ProactiveHintsContainer extends FrameLayout {
public static final FloatProperty<ProactiveHintsContainer> HINT_VISIBILITY =
new FloatProperty<ProactiveHintsContainer>("hint_visibility") {
@Override
public void setValue(ProactiveHintsContainer proactiveHintsContainer, float v) {
proactiveHintsContainer.setHintVisibility(v);
}
@Override
public Float get(ProactiveHintsContainer proactiveHintsContainer) {
return proactiveHintsContainer.mHintVisibility;
}
};
private float mHintVisibility;
public ProactiveHintsContainer(Context context) {
super(context);
}
public ProactiveHintsContainer(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ProactiveHintsContainer(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public ProactiveHintsContainer(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public void setView(View v) {
removeAllViews();
addView(v);
}
public void setHintVisibility(float v) {
if (v == 1) {
setVisibility(VISIBLE);
} else {
setVisibility(GONE);
}
mHintVisibility = v;
}
}
@@ -1,28 +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.hints;
public final class UiHintListenerConstants {
private UiHintListenerConstants() {}
// Operations
public static final int ON_HINTS_RETURNED_CODE = 5;
// Keys
public static final String SESSION_ID_KEY = "session_id";
public static final String HINTS_KEY = "hints";
}
@@ -1,34 +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.hints;
public final class UiInterfaceConstants {
private UiInterfaceConstants() {}
// Operations
public static final int ON_HINT_TAP_CODE = 4;
public static final int REQUEST_HINTS_CODE = 7;
// Keys
public static final String SESSION_ID_KEY = "session_id";
public static final String HINT_ID_KEY = "hint_id";
public static final String WIDTH_PX_KEY = "width_px";
public static final String HEIGHT_PX_KEY = "height_px";
public static final String HINT_SPACE_WIDTH_PX_KEY = "hint_space_width_px";
public static final String HINT_SPACE_HEIGHT_PX_KEY = "hint_space_height_px";
}
@@ -31,6 +31,7 @@ public interface InputConsumer {
int TYPE_DEVICE_LOCKED = 1 << 4;
int TYPE_ACCESSIBILITY = 1 << 5;
int TYPE_SCREEN_PINNED = 1 << 6;
int TYPE_OVERVIEW_WITHOUT_FOCUS = 1 << 7;
InputConsumer NO_OP = () -> TYPE_NO_OP;
@@ -78,6 +79,8 @@ public interface InputConsumer {
return "ACCESSIBILITY";
case TYPE_SCREEN_PINNED:
return "SCREEN_PINNED";
case TYPE_OVERVIEW_WITHOUT_FOCUS:
return "TYPE_OVERVIEW_WITHOUT_FOCUS";
default:
return "NO_OP";
}
@@ -28,7 +28,6 @@ import static com.android.launcher3.uioverrides.RecentsUiFactory.ROTATION_LANDSC
import static com.android.launcher3.uioverrides.RecentsUiFactory.ROTATION_SEASCAPE;
import static com.android.launcher3.util.RaceConditionTracker.ENTER;
import static com.android.launcher3.util.RaceConditionTracker.EXIT;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
@@ -43,10 +42,8 @@ import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import androidx.annotation.UiThread;
@@ -65,6 +62,7 @@ import com.android.quickstep.WindowTransformSwipeHandler;
import com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget;
import com.android.quickstep.util.CachedEventDispatcher;
import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.util.NavBarPosition;
import com.android.quickstep.util.RecentsAnimationListenerSet;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.BackgroundExecutor;
@@ -95,7 +93,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
private final SysUINavigationMode.Mode mMode;
private final RectF mSwipeTouchRegion;
private final int mDisplayRotation;
private final NavBarPosition mNavBarPosition;
private final Consumer<OtherActivityInputConsumer> mOnCompleteCallback;
private final MotionPauseDetector mMotionPauseDetector;
@@ -157,7 +155,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
mInputConsumer = inputConsumer;
mSwipeSharedState = swipeSharedState;
mDisplayRotation = getSystemService(WindowManager.class).getDefaultDisplay().getRotation();
mNavBarPosition = new NavBarPosition(base);
mDragSlop = QuickStepContract.getQuickStepDragSlopPx();
float slop = QuickStepContract.getQuickStepTouchSlopPx();
mSquaredTouchSlop = slop * slop;
@@ -188,9 +186,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
if (mPassedDragSlop && mInteractionHandler != null
&& !mRecentsViewDispatcher.hasConsumer()) {
mRecentsViewDispatcher.setConsumer(mInteractionHandler.getRecentsViewDispatcher(
isNavBarOnLeft()
? ROTATION_SEASCAPE
: (isNavBarOnRight() ? ROTATION_LANDSCAPE : RotationMode.NORMAL)));
mNavBarPosition.getRotationMode()));
}
int edgeFlags = ev.getEdgeFlags();
ev.setEdgeFlags(edgeFlags | EDGE_NAV_BAR);
@@ -329,14 +325,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
mInteractionHandler.onGestureStarted();
}
private boolean isNavBarOnRight() {
return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_90;
}
private boolean isNavBarOnLeft() {
return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_270;
}
private void startTouchTrackingForWindowAnimation(long touchTimeMs) {
TOUCH_INTERACTION_LOG.addLog("startRecentsAnimation");
@@ -382,8 +370,8 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
ViewConfiguration.get(this).getScaledMaximumFlingVelocity());
float velocityX = mVelocityTracker.getXVelocity(mActivePointerId);
float velocityY = mVelocityTracker.getYVelocity(mActivePointerId);
float velocity = isNavBarOnRight() ? velocityX
: isNavBarOnLeft() ? -velocityX
float velocity = mNavBarPosition.isRightEdge() ? velocityX
: mNavBarPosition.isLeftEdge() ? -velocityX
: velocityY;
mInteractionHandler.updateDisplacement(getDisplacement(ev) - mStartDisplacement);
@@ -444,9 +432,9 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
}
private float getDisplacement(MotionEvent ev) {
if (isNavBarOnRight()) {
if (mNavBarPosition.isRightEdge()) {
return ev.getX() - mDownPos.x;
} else if (isNavBarOnLeft()) {
} else if (mNavBarPosition.isLeftEdge()) {
return mDownPos.x - ev.getX();
} else {
return ev.getY() - mDownPos.y;
@@ -51,7 +51,7 @@ public class OverviewInputConsumer<T extends BaseDraggingActivity>
private final boolean mStartingInActivityBounds;
private boolean mTargetHandledTouch;
OverviewInputConsumer(T activity, @Nullable InputMonitorCompat inputMonitor,
public OverviewInputConsumer(T activity, @Nullable InputMonitorCompat inputMonitor,
boolean startingInActivityBounds) {
mActivity = activity;
mInputMonitor = inputMonitor;
@@ -115,12 +115,12 @@ public class OverviewInputConsumer<T extends BaseDraggingActivity>
}
}
public static InputConsumer newInstance(ActivityControlHelper activityHelper,
@Nullable InputMonitorCompat inputMonitor, boolean startingInActivityBounds) {
public static InputConsumer newInstanceWithinActivityBounds(
ActivityControlHelper activityHelper) {
BaseDraggingActivity activity = activityHelper.getCreatedActivity();
if (activity == null) {
return InputConsumer.NO_OP;
}
return new OverviewInputConsumer(activity, inputMonitor, startingInActivityBounds);
return new OverviewInputConsumer(activity, null, true);
}
}
@@ -0,0 +1,151 @@
/*
* 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.inputconsumers;
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_UP;
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.content.Context;
import android.graphics.PointF;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
import com.android.launcher3.Utilities;
import com.android.quickstep.OverviewCallbacks;
import com.android.quickstep.util.NavBarPosition;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputMonitorCompat;
public class OverviewWithoutFocusInputConsumer implements InputConsumer {
private final InputMonitorCompat mInputMonitor;
private final boolean mDisableHorizontalSwipe;
private final PointF mDownPos = new PointF();
private final float mSquaredTouchSlop;
private final Context mContext;
private final NavBarPosition mNavBarPosition;
private boolean mInterceptedTouch;
private VelocityTracker mVelocityTracker;
public OverviewWithoutFocusInputConsumer(Context context, InputMonitorCompat inputMonitor,
boolean disableHorizontalSwipe) {
mInputMonitor = inputMonitor;
mDisableHorizontalSwipe = disableHorizontalSwipe;
mContext = context;
mSquaredTouchSlop = Utilities.squaredTouchSlop(context);
mNavBarPosition = new NavBarPosition(context);
mVelocityTracker = VelocityTracker.obtain();
}
@Override
public int getType() {
return TYPE_OVERVIEW_WITHOUT_FOCUS;
}
@Override
public boolean allowInterceptByParent() {
return !mInterceptedTouch;
}
private void endTouchTracking() {
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}
@Override
public void onMotionEvent(MotionEvent ev) {
if (mVelocityTracker == null) {
return;
}
mVelocityTracker.addMovement(ev);
switch (ev.getActionMasked()) {
case ACTION_DOWN: {
mDownPos.set(ev.getX(), ev.getY());
break;
}
case ACTION_MOVE: {
if (!mInterceptedTouch) {
float displacementX = ev.getX() - mDownPos.x;
float displacementY = ev.getY() - mDownPos.y;
if (squaredHypot(displacementX, displacementY) >= mSquaredTouchSlop) {
if (mDisableHorizontalSwipe
&& Math.abs(displacementX) > Math.abs(displacementY)) {
// Horizontal gesture is not allowed in this region
endTouchTracking();
break;
}
mInterceptedTouch = true;
if (mInputMonitor != null) {
mInputMonitor.pilferPointers();
}
}
}
break;
}
case ACTION_CANCEL:
endTouchTracking();
break;
case ACTION_UP: {
finishTouchTracking(ev);
endTouchTracking();
break;
}
}
}
private void finishTouchTracking(MotionEvent ev) {
mVelocityTracker.computeCurrentVelocity(100);
float velocityX = mVelocityTracker.getXVelocity();
float velocityY = mVelocityTracker.getYVelocity();
float velocity = mNavBarPosition.isRightEdge()
? -velocityX : (mNavBarPosition.isLeftEdge() ? velocityX : -velocityY);
final boolean triggerQuickstep;
if (Math.abs(velocity) >= ViewConfiguration.get(mContext).getScaledMinimumFlingVelocity()) {
triggerQuickstep = velocity > 0;
} else {
float displacementX = mDisableHorizontalSwipe ? 0 : (ev.getX() - mDownPos.x);
float displacementY = ev.getY() - mDownPos.y;
triggerQuickstep = squaredHypot(displacementX, displacementY) >= mSquaredTouchSlop;
}
if (triggerQuickstep) {
OverviewCallbacks.get(mContext).closeAllWindows();
ActivityManagerWrapper.getInstance()
.closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
TOUCH_INTERACTION_LOG.addLog("startQuickstep");
} else {
// ignore
}
}
}
@@ -0,0 +1,55 @@
/*
* 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.util;
import static com.android.launcher3.uioverrides.RecentsUiFactory.ROTATION_LANDSCAPE;
import static com.android.launcher3.uioverrides.RecentsUiFactory.ROTATION_SEASCAPE;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import android.content.Context;
import android.view.Surface;
import android.view.WindowManager;
import com.android.launcher3.graphics.RotationMode;
import com.android.quickstep.SysUINavigationMode;
/**
* Utility class to check nav bar position
*/
public class NavBarPosition {
private final SysUINavigationMode.Mode mMode;
private final int mDisplayRotation;
public NavBarPosition(Context context) {
mMode = SysUINavigationMode.getMode(context);
mDisplayRotation = context.getSystemService(WindowManager.class)
.getDefaultDisplay().getRotation();
}
public boolean isRightEdge() {
return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_90;
}
public boolean isLeftEdge() {
return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_270;
}
public RotationMode getRotationMode() {
return isLeftEdge() ? ROTATION_SEASCAPE
: (isRightEdge() ? ROTATION_LANDSCAPE : RotationMode.NORMAL);
}
}
@@ -28,13 +28,20 @@ import com.android.launcher3.CellLayout;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils.ViewProgressProperty;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager;
import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutAndWidgetContainer;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.anim.SpringObjectAnimator;
import java.util.ArrayList;
import java.util.List;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.anim.Interpolators.LINEAR;
/**
@@ -56,7 +63,7 @@ public class StaggeredWorkspaceAnim {
private final float mSpringTransY;
private final View mViewToIgnore;
private final List<ValueAnimator> mAnimators = new ArrayList<>();
private final List<Animator> mAnimators = new ArrayList<>();
/**
* @param floatingViewOriginalView The FloatingIconView's original view.
@@ -104,6 +111,9 @@ public class StaggeredWorkspaceAnim {
View qsb = launcher.findViewById(R.id.search_container_all_apps);
addStaggeredAnimationForView(qsb, grid.inv.numRows + 2, totalRows);
}
addWorkspaceScrimAnimationForState(launcher, BACKGROUND_APP, 0);
addWorkspaceScrimAnimationForState(launcher, NORMAL, ALPHA_DURATION_MS);
}
/**
@@ -150,4 +160,14 @@ public class StaggeredWorkspaceAnim {
alpha.setStartDelay(startDelay);
mAnimators.add(alpha);
}
private void addWorkspaceScrimAnimationForState(Launcher launcher, LauncherState state,
long duration) {
AnimatorSetBuilder scrimAnimBuilder = new AnimatorSetBuilder();
AnimationConfig scrimAnimConfig = new AnimationConfig();
scrimAnimConfig.duration = duration;
PropertySetter scrimPropertySetter = scrimAnimConfig.getPropertySetter(scrimAnimBuilder);
launcher.getWorkspace().getStateTransitionAnimation().setScrim(scrimPropertySetter, state);
mAnimators.add(scrimAnimBuilder.build());
}
}
@@ -20,6 +20,7 @@ import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.RECENTS_CLEAR_ALL_BUTTON;
import static com.android.launcher3.LauncherState.SPRING_LOADED;
import static com.android.launcher3.QuickstepAppTransitionManagerImpl.ALL_APPS_PROGRESS_OFF_SCREEN;
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
@@ -30,25 +31,20 @@ import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
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.anim.Interpolators;
import com.android.launcher3.appprediction.PredictionUiStateManager;
import com.android.launcher3.appprediction.PredictionUiStateManager.Client;
import com.android.launcher3.util.PendingAnimation;
import com.android.launcher3.views.BaseDragLayer;
import com.android.launcher3.views.ScrimView;
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.hints.ProactiveHintsContainer;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.ClipAnimationHelper.TransformParams;
import com.android.quickstep.util.LayoutUtils;
@@ -57,11 +53,9 @@ import com.android.quickstep.util.LayoutUtils;
* {@link RecentsView} used in Launcher activity
*/
@TargetApi(Build.VERSION_CODES.O)
public class LauncherRecentsView extends RecentsView<Launcher> {
public class LauncherRecentsView extends RecentsView<Launcher> implements StateListener {
private final TransformParams mTransformParams = new TransformParams();
private final int mChipOverhang;
@Nullable private ProactiveHintsContainer mProactiveHintsContainer;
public LauncherRecentsView(Context context) {
this(context, null);
@@ -74,16 +68,7 @@ public class LauncherRecentsView extends RecentsView<Launcher> {
public LauncherRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setContentAlpha(0);
mChipOverhang = (int) context.getResources().getDimension(R.dimen.chip_hint_overhang);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
View hintContainer = mActivity.findViewById(R.id.hints);
mProactiveHintsContainer =
hintContainer instanceof ProactiveHintsContainer
? (ProactiveHintsContainer) hintContainer : null;
mActivity.getStateManager().addStateListener(this);
}
@Override
@@ -102,11 +87,6 @@ public class LauncherRecentsView extends RecentsView<Launcher> {
}
}
@Nullable
public ProactiveHintsContainer getProactiveHintsContainer() {
return mProactiveHintsContainer;
}
@Override
public void draw(Canvas canvas) {
maybeDrawEmptyMessage(canvas);
@@ -160,23 +140,6 @@ public class LauncherRecentsView extends RecentsView<Launcher> {
@Override
protected void getTaskSize(DeviceProfile dp, Rect outRect) {
LayoutUtils.calculateLauncherTaskSize(getContext(), dp, outRect);
if (mProactiveHintsContainer != null) {
BaseDragLayer.LayoutParams params = (BaseDragLayer.LayoutParams) mProactiveHintsContainer.getLayoutParams();
params.bottomMargin = getHeight() - outRect.bottom - mChipOverhang;
params.width = outRect.width();
}
}
@Override
public PendingAnimation createTaskLauncherAnimation(TaskView tv, long duration) {
PendingAnimation anim = super.createTaskLauncherAnimation(tv, duration);
if (mProactiveHintsContainer != null) {
anim.anim.play(ObjectAnimator.ofFloat(
mProactiveHintsContainer, ProactiveHintsContainer.HINT_VISIBILITY, 0));
}
return anim;
}
@Override
@@ -194,31 +157,6 @@ public class LauncherRecentsView extends RecentsView<Launcher> {
}
}
@Override
public PendingAnimation createTaskDismissAnimation(TaskView taskView, boolean animateTaskView,
boolean shouldRemoveTask, long duration) {
PendingAnimation anim = super.createTaskDismissAnimation(taskView, animateTaskView,
shouldRemoveTask, duration);
if (mProactiveHintsContainer != null) {
anim.anim.play(ObjectAnimator.ofFloat(
mProactiveHintsContainer, ProactiveHintsContainer.HINT_VISIBILITY, 0));
anim.addEndListener(onEndListener -> {
if (!onEndListener.isSuccess) {
mProactiveHintsContainer.setHintVisibility(1);
}
});
}
return anim;
}
public void setHintVisibility(float v) {
if (mProactiveHintsContainer != null) {
mProactiveHintsContainer.setHintVisibility(v);
}
}
@Override
protected void onTaskLaunched(boolean success) {
if (success) {
@@ -286,6 +224,22 @@ public class LauncherRecentsView extends RecentsView<Launcher> {
PredictionUiStateManager.INSTANCE.get(getContext()).switchClient(Client.HOME);
}
@Override
public void onStateTransitionStart(LauncherState toState) {
setOverviewStateEnabled(toState.overviewUi);
setFreezeViewVisibility(true);
}
@Override
public void onStateTransitionComplete(LauncherState finalState) {
if (finalState == NORMAL || finalState == SPRING_LOADED) {
// Clean-up logic that occurs when recents is no longer in use/visible.
reset();
}
setOverlayEnabled(finalState == OVERVIEW);
setFreezeViewVisibility(false);
}
@Override
public void setOverviewStateEnabled(boolean enabled) {
super.setOverviewStateEnabled(enabled);
@@ -72,6 +72,9 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ListView;
import androidx.annotation.Nullable;
import androidx.dynamicanimation.animation.SpringForce;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
@@ -111,9 +114,6 @@ import com.android.systemui.shared.system.TaskStackChangeListener;
import java.util.ArrayList;
import java.util.function.Consumer;
import androidx.annotation.Nullable;
import androidx.dynamicanimation.animation.SpringForce;
/**
* A list of recent tasks.
*/
@@ -168,8 +168,6 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
// The threshold at which we update the SystemUI flags when animating from the task into the app
public static final float UPDATE_SYSUI_FLAGS_THRESHOLD = 0.85f;
private static final float[] sTempFloatArray = new float[3];
protected final T mActivity;
private final float mFastFlingVelocity;
private final RecentsModel mModel;
@@ -189,6 +187,8 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
private boolean mDwbToastShown;
private boolean mDisallowScrollToClearAll;
private boolean mOverlayEnabled;
private boolean mFreezeViewVisibility;
/**
* TODO: Call reloadIdNeeded in onTaskStackChanged.
@@ -428,11 +428,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
// Clear the task data for the removed child if it was visible
if (child != mClearAllButton) {
TaskView taskView = (TaskView) child;
Task task = taskView.getTask();
if (mHasVisibleTaskData.get(task.key.id)) {
mHasVisibleTaskData.delete(task.key.id);
taskView.onTaskListVisibilityChanged(false /* visible */);
}
mHasVisibleTaskData.delete(taskView.getTask().key.id);
mTaskViewPool.recycle(taskView);
}
}
@@ -455,7 +451,6 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
public void setOverviewStateEnabled(boolean enabled) {
mOverviewStateEnabled = enabled;
updateTaskStackListenerState();
if (!enabled) mDwbToastShown = false;
}
public void onDigitalWellbeingToastShown() {
@@ -582,6 +577,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
}
resetTaskVisuals();
onTaskStackUpdated();
updateEnabledOverlays();
}
public int getTaskViewCount() {
@@ -780,6 +776,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
unloadVisibleTaskData();
setCurrentPage(0);
mDwbToastShown = false;
}
public @Nullable TaskView getRunningTaskView() {
@@ -1306,7 +1303,25 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
mEmptyMessagePaint.setAlpha(alphaInt);
mEmptyIcon.setAlpha(alphaInt);
setVisibility(alpha > 0 ? VISIBLE : GONE);
if (alpha > 0) {
setVisibility(VISIBLE);
} else if (!mFreezeViewVisibility) {
setVisibility(GONE);
}
}
/**
* Freezes the view visibility change. When frozen, the view will not change its visibility
* to gone due to alpha changes.
*/
public void setFreezeViewVisibility(boolean freezeViewVisibility) {
if (mFreezeViewVisibility != freezeViewVisibility) {
mFreezeViewVisibility = freezeViewVisibility;
if (!mFreezeViewVisibility) {
setVisibility(mContentAlpha > 0 ? VISIBLE : GONE);
}
}
}
@Override
@@ -1545,6 +1560,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
protected void notifyPageSwitchListener(int prevPage) {
super.notifyPageSwitchListener(prevPage);
loadVisibleTaskData();
updateEnabledOverlays();
}
@Override
@@ -1685,4 +1701,19 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
public ClipAnimationHelper getTempClipAnimationHelper() {
return mTempClipAnimationHelper;
}
private void updateEnabledOverlays() {
int overlayEnabledPage = mOverlayEnabled ? getNextPage() : -1;
int taskCount = getTaskViewCount();
for (int i = 0; i < taskCount; i++) {
((TaskView) getChildAt(i)).setOverlayEnabled(i == overlayEnabledPage);
}
}
public void setOverlayEnabled(boolean overlayEnabled) {
if (mOverlayEnabled != overlayEnabled) {
mOverlayEnabled = overlayEnabled;
updateEnabledOverlays();
}
}
}
@@ -42,6 +42,7 @@ import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.TaskOverlayFactory;
import com.android.quickstep.TaskSystemShortcut;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.views.IconView.OnScaleUpdateListener;
@@ -196,7 +197,7 @@ public class TaskMenuView extends AbstractFloatingView {
final BaseDraggingActivity activity = BaseDraggingActivity.fromContext(getContext());
final List<TaskSystemShortcut> shortcuts =
taskView.getTaskOverlay().getEnabledShortcuts(taskView);
TaskOverlayFactory.INSTANCE.get(getContext()).getEnabledShortcuts(taskView);
final int count = shortcuts.size();
for (int i = 0; i < count; ++i) {
final TaskSystemShortcut menuOption = shortcuts.get(i);
@@ -98,6 +98,9 @@ public class TaskThumbnailView extends View {
private float mDimAlphaMultiplier = 1f;
private float mSaturation = 1f;
private boolean mOverlayEnabled;
private boolean mRotated;
public TaskThumbnailView(Context context) {
this(context, null);
}
@@ -192,10 +195,6 @@ public class TaskThumbnailView extends View {
return 0;
}
public TaskOverlay getTaskOverlay() {
return mOverlay;
}
@Override
protected void onDraw(Canvas canvas) {
RectF currentDrawnInsets = mFullscreenParams.mCurrentDrawnInsets;
@@ -257,6 +256,22 @@ public class TaskThumbnailView extends View {
return (TaskView) getParent();
}
public void setOverlayEnabled(boolean overlayEnabled) {
if (mOverlayEnabled != overlayEnabled) {
mOverlayEnabled = overlayEnabled;
updateOverlay();
}
}
private void updateOverlay() {
// The overlay doesn't really work when the screenshot is rotated, so don't add it.
if (mOverlayEnabled && !mRotated && mBitmapShader != null && mThumbnailData != null) {
mOverlay.initOverlay(mTask, mThumbnailData, mMatrix);
} else {
mOverlay.reset();
}
}
private void updateThumbnailPaintFilter() {
int mul = (int) ((1 - mDimAlpha * mDimAlphaMultiplier) * 255);
ColorFilter filter = getColorFilter(mul, mIsDarkTextTheme, mSaturation);
@@ -351,12 +366,8 @@ public class TaskThumbnailView extends View {
mPaint.setShader(mBitmapShader);
}
if (isRotated) {
// The overlay doesn't really work when the screenshot is rotated, so don't add it.
mOverlay.reset();
} else {
mOverlay.setTaskInfo(mTask, mThumbnailData, mMatrix);
}
mRotated = isRotated;
updateOverlay();
invalidate();
}
@@ -39,7 +39,6 @@ import android.os.Handler;
import android.util.AttributeSet;
import android.util.FloatProperty;
import android.util.Log;
import android.util.Property;
import android.view.View;
import android.view.ViewOutlineProvider;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -253,10 +252,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
return mIconView;
}
public TaskOverlayFactory.TaskOverlay getTaskOverlay() {
return mSnapshotView.getTaskOverlay();
}
public AnimatorPlaybackController createLaunchAnimationForRunningTask() {
final PendingAnimation pendingAnimation =
getRecentsView().createTaskLauncherAnimation(this, RECENTS_LAUNCH_DURATION);
@@ -488,6 +483,8 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
// Clear any references to the thumbnail (it will be re-read either from the cache or the
// system on next bind)
mSnapshotView.setThumbnail(mTask, null);
setOverlayEnabled(false);
onTaskListVisibilityChanged(false);
if (mTask != null) {
mTask.thumbnail = null;
}
@@ -608,7 +605,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
final Context context = getContext();
final List<TaskSystemShortcut> shortcuts =
mSnapshotView.getTaskOverlay().getEnabledShortcuts(this);
TaskOverlayFactory.INSTANCE.get(getContext()).getEnabledShortcuts(this);
final int count = shortcuts.size();
for (int i = 0; i < count; ++i) {
final TaskSystemShortcut menuOption = shortcuts.get(i);
@@ -647,7 +644,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
}
final List<TaskSystemShortcut> shortcuts =
mSnapshotView.getTaskOverlay().getEnabledShortcuts(this);
TaskOverlayFactory.INSTANCE.get(getContext()).getEnabledShortcuts(this);
final int count = shortcuts.size();
for (int i = 0; i < count; ++i) {
final TaskSystemShortcut menuOption = shortcuts.get(i);
@@ -733,6 +730,10 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
return mShowScreenshot;
}
public void setOverlayEnabled(boolean overlayEnabled) {
mSnapshotView.setOverlayEnabled(overlayEnabled);
}
/**
* We update and subsequently draw these in {@link #setFullscreenProgress(float)}.
*/
@@ -108,7 +108,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
// Use a shorter duration for x or y translation to create a curve effect
private static final long APP_LAUNCH_CURVED_DURATION = 250;
private static final long APP_LAUNCH_ALPHA_DURATION = 50;
private static final long APP_LAUNCH_ALPHA_START_DELAY = 50;
private static final long APP_LAUNCH_ALPHA_START_DELAY = 25;
// We scale the durations for the downward app launch animations (minus the scale animation).
private static final float APP_LAUNCH_DOWN_DUR_SCALE_FACTOR = 0.8f;
@@ -47,7 +47,6 @@ import com.android.launcher3.LauncherStateManager;
import com.android.launcher3.LauncherStateManager.StateHandler;
import com.android.launcher3.QuickstepAppTransitionManagerImpl;
import com.android.launcher3.Utilities;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.proxy.ProxyActivityStarter;
import com.android.launcher3.proxy.StartActivityParams;
import com.android.quickstep.OverviewInteractionState;
@@ -64,10 +63,14 @@ import java.util.zip.Deflater;
public class UiFactory extends RecentsUiFactory {
public static Runnable enableLiveTouchControllerChanges(DragLayer dl) {
NavigationModeChangeListener listener = m -> dl.recreateControllers();
SysUINavigationMode mode = SysUINavigationMode.INSTANCE.get(dl.getContext());
mode.addModeChangeListener(listener);
public static Runnable enableLiveUIChanges(Launcher launcher) {
NavigationModeChangeListener listener = m -> {
launcher.getDragLayer().recreateControllers();
launcher.getRotationHelper().setRotationHadDifferentUI(m != Mode.NO_BUTTON);
};
SysUINavigationMode mode = SysUINavigationMode.INSTANCE.get(launcher);
SysUINavigationMode.Mode m = mode.addModeChangeListener(listener);
launcher.getRotationHelper().setRotationHadDifferentUI(m != Mode.NO_BUTTON);
return () -> mode.removeModeChangeListener(listener);
}
@@ -18,14 +18,17 @@ package com.android.quickstep;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import org.junit.Rule;
import org.junit.rules.RuleChain;
import org.junit.rules.TestRule;
/**
* Base class for all instrumentation tests that deal with Quickstep.
*/
public abstract class AbstractQuickStepTest extends AbstractLauncherUiTest {
@Rule
public TestRule mQuickstepOnOffExecutor =
new NavigationModeSwitchRule(mLauncher);
@Override
protected TestRule getRulesInsideActivityMonitor() {
return RuleChain.
outerRule(new NavigationModeSwitchRule(mLauncher)).
around(super.getRulesInsideActivityMonitor());
}
}
-5
View File
@@ -48,11 +48,6 @@
layout="@layout/overview_panel"
android:visibility="gone" />
<include
android:id="@+id/hints"
layout="@layout/proactive_hints_container"
android:visibility="gone"/>
<!-- Keep these behind the workspace so that they are not visible when
we go into AllApps -->
<com.android.launcher3.pageindicators.WorkspacePageIndicator
-20
View File
@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2016 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.
-->
<Space
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="0dp" />
+2 -2
View File
@@ -56,9 +56,9 @@
android:paddingBottom="@dimen/folder_label_padding_bottom"
android:paddingTop="@dimen/folder_label_padding_top"
android:singleLine="true"
android:textColor="?android:attr/textColorTertiary"
android:textColor="?attr/folderTextColor"
android:textColorHighlight="?android:attr/colorControlHighlight"
android:textColorHint="?android:attr/textColorHint"
android:textColorHint="?attr/folderTextColor"
android:textSize="@dimen/folder_label_text_size" />
<com.android.launcher3.pageindicators.PageIndicatorDots
-5
View File
@@ -232,11 +232,6 @@
<dimen name="snackbar_min_text_size">12sp</dimen>
<dimen name="snackbar_max_text_size">14sp</dimen>
<!-- Hints -->
<dimen name="chip_hint_height">26dp</dimen>
<dimen name="chip_hint_bottom_margin">194dp</dimen>
<dimen name="chip_hint_overhang">15dp</dimen>
<!-- Theming related -->
<dimen name="default_dialog_corner_radius">8dp</dimen>
@@ -99,10 +99,6 @@ public class DeviceProfile {
public int folderChildTextSizePx;
public int folderChildDrawablePaddingPx;
// Hints
public int chipHintHeightPx;
public int chipHintBottomMarginPx;
// Hotseat
public int hotseatCellHeightPx;
// In portrait: size = height, in landscape: size = width
@@ -200,9 +196,6 @@ public class DeviceProfile {
workspaceCellPaddingXPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_padding_x);
chipHintHeightPx = res.getDimensionPixelSize(R.dimen.chip_hint_height);
chipHintBottomMarginPx = res.getDimensionPixelSize(R.dimen.chip_hint_bottom_margin);
hotseatBarTopPaddingPx =
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_top_padding);
hotseatBarBottomPaddingPx = (isTallDevice ? 0
+4 -1
View File
@@ -879,6 +879,9 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
@Override
protected void onStart() {
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "Launcher.onStart");
}
RaceConditionTracker.onEvent(ON_START_EVT, ENTER);
super.onStart();
if (mLauncherCallbacks != null) {
@@ -1063,7 +1066,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
// Setup the drag layer
mDragLayer.setup(mDragController, mWorkspace);
mCancelTouchController = UiFactory.enableLiveTouchControllerChanges(mDragLayer);
mCancelTouchController = UiFactory.enableLiveUIChanges(this);
mWorkspace.setup(mDragController);
// Until the workspace is bound, ensure that we keep the wallpaper offset locked to the
@@ -258,9 +258,6 @@ public class LauncherState {
* Called when the start transition ends and the user settles on this particular state.
*/
public void onStateTransitionEnd(Launcher launcher) {
if (this == NORMAL || this == SPRING_LOADED) {
UiFactory.resetOverview(launcher);
}
if (this == NORMAL) {
// Clear any rotation locks when going to normal state
launcher.getRotationHelper().setCurrentStateRequest(REQUEST_NONE);
+4
View File
@@ -1394,6 +1394,10 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
builder.play(stepAnimator);
}
public WorkspaceStateTransitionAnimation getStateTransitionAnimation() {
return mStateTransitionAnimation;
}
public void updateAccessibilityFlags() {
// TODO: Update the accessibility flags appropriately when dragging.
int accessibilityFlag = mLauncher.getStateManager().getState().workspaceAccessibilityFlag;
@@ -130,7 +130,10 @@ public class WorkspaceStateTransitionAnimation {
propertySetter.setFloat(mWorkspace.getPageIndicator(), View.TRANSLATION_Y,
hotseatScaleAndTranslation.translationY, translationInterpolator);
// Set scrim
setScrim(propertySetter, state);
}
public void setScrim(PropertySetter propertySetter, LauncherState state) {
WorkspaceAndHotseatScrim scrim = mLauncher.getDragLayer().getScrim();
propertySetter.setFloat(scrim, SCRIM_PROGRESS, state.getWorkspaceScrimAlpha(mLauncher),
LINEAR);
@@ -27,6 +27,7 @@ import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.IBinder;
import android.util.Log;
import android.view.DragEvent;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
@@ -491,6 +492,16 @@ public class DragController implements DragDriver.EventListener, TouchController
mLastTouch[0] = x;
mLastTouch[1] = y;
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.NO_DRAG_TAG,
"handleMoveEvent Conditions " +
mIsInPreDrag + ", " +
(mIsInPreDrag && mOptions.preDragCondition != null) + ", " +
(mIsInPreDrag && mOptions.preDragCondition != null
&& mOptions.preDragCondition.shouldStartDrag(
mDistanceSinceScroll)));
}
if (mIsInPreDrag && mOptions.preDragCondition != null
&& mOptions.preDragCondition.shouldStartDrag(mDistanceSinceScroll)) {
if (TestProtocol.sDebugTracing) {
@@ -73,7 +73,8 @@ public class RotationHelper implements OnSharedPreferenceChangeListener {
// This is used to defer setting rotation flags until the activity is being created
private boolean mInitialized;
public boolean mDestroyed;
private boolean mDestroyed;
private boolean mRotationHasDifferentUI;
private int mLastActivityFlags = -1;
@@ -92,8 +93,12 @@ public class RotationHelper implements OnSharedPreferenceChangeListener {
}
}
public void setRotationHadDifferentUI(boolean rotationHasDifferentUI) {
mRotationHasDifferentUI = rotationHasDifferentUI;
}
public boolean homeScreenCanRotate() {
return mIgnoreAutoRotateSettings || mAutoRotateEnabled
return mRotationHasDifferentUI || mIgnoreAutoRotateSettings || mAutoRotateEnabled
|| mStateHandlerRequest != REQUEST_NONE
|| mLauncher.getDeviceProfile().isMultiWindowMode;
}
@@ -72,4 +72,5 @@ public final class TestProtocol {
public static final String NO_DRAG_TAG = "b/133009122";
public static final String NO_START_TAG = "b/132900132";
public static final String NO_START_TASK_TAG = "b/133765434";
public static final String NO_OVERVIEW_EVENT_TAG = "b/134532571";
}
@@ -27,16 +27,17 @@ import android.util.MutableLong;
import com.android.launcher3.config.FeatureFlags;
/**
* A wrapper around {@link Trace} to allow easier proguarding for production builds.
* A wrapper around {@link Trace} with some utility information.
*
* To enable any tracing log, execute the following command:
* $ adb shell setprop log.tag.LAUNCHER_TRACE VERBOSE
* $ adb shell setprop log.tag.TAGNAME VERBOSE
*/
public class TraceHelper {
private static final boolean ENABLED = FeatureFlags.IS_DOGFOOD_BUILD;
private static final boolean ENABLED = isLoggable("LAUNCHER_TRACE", VERBOSE);
private static final boolean SYSTEM_TRACE = false;
private static final boolean SYSTEM_TRACE = ENABLED;
private static final ArrayMap<String, MutableLong> sUpTimes = ENABLED ? new ArrayMap<>() : null;
public static void beginSection(String sectionName) {
@@ -124,6 +124,7 @@ public class FloatingIconView extends View implements
private boolean mIsVerticalBarLayout = false;
private boolean mIsAdaptiveIcon = false;
private boolean mIsOpening;
private @Nullable Drawable mBadge;
private @Nullable Drawable mForeground;
@@ -178,8 +179,10 @@ public class FloatingIconView extends View implements
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
getViewTreeObserver().addOnGlobalLayoutListener(this);
mLauncher.getRotationHelper().setCurrentTransitionRequest(REQUEST_LOCK);
if (!mIsOpening) {
getViewTreeObserver().addOnGlobalLayoutListener(this);
mLauncher.getRotationHelper().setCurrentTransitionRequest(REQUEST_LOCK);
}
}
@Override
@@ -326,7 +329,7 @@ public class FloatingIconView extends View implements
* - For BubbleTextView, we return the icon bounds.
*/
private float getLocationBoundsForView(View v, RectF outRect) {
boolean ignoreTransform = true;
boolean ignoreTransform = !mIsOpening;
if (v instanceof DeepShortcutView) {
v = ((DeepShortcutView) v).getBubbleText();
ignoreTransform = false;
@@ -627,6 +630,7 @@ public class FloatingIconView extends View implements
view.recycle();
view.mIsVerticalBarLayout = launcher.getDeviceProfile().isVerticalBarLayout();
view.mIsOpening = isOpening;
view.mOriginalIcon = originalView;
view.mPositionOut = positionOut;
@@ -27,7 +27,6 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState.ScaleAndTranslation;
import com.android.launcher3.LauncherStateManager.StateHandler;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.graphics.RotationMode;
import com.android.launcher3.util.TouchController;
@@ -40,7 +39,7 @@ public class UiFactory {
launcher.getDragController(), new AllAppsSwipeController(launcher)};
}
public static Runnable enableLiveTouchControllerChanges(DragLayer dl) {
public static Runnable enableLiveUIChanges(Launcher l) {
return null;
}
@@ -58,19 +58,17 @@ import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.tapl.TestHelpers;
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.rule.FailureWatcher;
import com.android.launcher3.util.rule.LauncherActivityRule;
import com.android.launcher3.util.rule.ShellCommandRule;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.RuleChain;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -93,11 +91,11 @@ public abstract class AbstractLauncherUiTest {
public static final long SHORT_UI_TIMEOUT = 300;
public static final long DEFAULT_UI_TIMEOUT = 10000;
private static final String TAG = "AbstractLauncherUiTest";
private static int sScreenshotCount = 0;
protected MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor();
protected final UiDevice mDevice = UiDevice.getInstance(getInstrumentation());
protected final LauncherInstrumentation mLauncher;
protected final LauncherInstrumentation mLauncher =
new LauncherInstrumentation(getInstrumentation());
protected Context mTargetContext;
protected String mTargetPackage;
@@ -108,11 +106,9 @@ public abstract class AbstractLauncherUiTest {
throw new RuntimeException(e);
}
if (TestHelpers.isInLauncherProcess()) Utilities.enableRunningInTestHarnessForTests();
mLauncher = new LauncherInstrumentation(getInstrumentation());
}
@Rule
public LauncherActivityRule mActivityMonitor = new LauncherActivityRule();
protected final LauncherActivityRule mActivityMonitor = new LauncherActivityRule();
@Rule
public ShellCommandRule mDefaultLauncherRule =
@@ -166,43 +162,18 @@ public abstract class AbstractLauncherUiTest {
}
} : base;
protected TestRule getRulesInsideActivityMonitor() {
return new FailureWatcher(this);
}
@Rule
public TestWatcher mFailureWatcher = new TestWatcher() {
private void dumpViewHierarchy() {
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
mDevice.dumpWindowHierarchy(stream);
stream.flush();
stream.close();
for (String line : stream.toString().split("\\r?\\n")) {
Log.e(TAG, line.trim());
}
} catch (IOException e) {
Log.e(TAG, "error dumping XML to logcat", e);
}
}
public TestRule mOrderSensitiveRules = RuleChain.
outerRule(mActivityMonitor).
around(getRulesInsideActivityMonitor());
@Override
protected void failed(Throwable e, Description description) {
if (mDevice == null) return;
final String pathname = getInstrumentation().getTargetContext().
getFilesDir().getPath() + "/TaplTestScreenshot" + sScreenshotCount++ + ".png";
Log.e(TAG, "Failed test " + description.getMethodName() +
", screenshot will be saved to " + pathname +
", track trace is below, UI object dump is further below:\n" +
Log.getStackTraceString(e));
dumpViewHierarchy();
try {
final String dumpsysResult = mDevice.executeShellCommand(
"dumpsys activity service TouchInteractionService");
Log.d(TAG, "TouchInteractionService: " + dumpsysResult);
} catch (IOException ex) {
}
mDevice.takeScreenshot(new File(pathname));
}
};
public UiDevice getDevice() {
return mDevice;
}
@Before
public void setUp() throws Exception {
@@ -0,0 +1,59 @@
package com.android.launcher3.util.rule;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
import android.util.Log;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
public class FailureWatcher extends TestWatcher {
private static final String TAG = "FailureWatcher";
private static int sScreenshotCount = 0;
private AbstractLauncherUiTest mAbstractLauncherUiTest;
public FailureWatcher(AbstractLauncherUiTest abstractLauncherUiTest) {
mAbstractLauncherUiTest = abstractLauncherUiTest;
}
private void dumpViewHierarchy() {
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
mAbstractLauncherUiTest.getDevice().dumpWindowHierarchy(stream);
stream.flush();
stream.close();
for (String line : stream.toString().split("\\r?\\n")) {
Log.e(TAG, line.trim());
}
} catch (IOException e) {
Log.e(TAG, "error dumping XML to logcat", e);
}
}
@Override
protected void failed(Throwable e, Description description) {
if (mAbstractLauncherUiTest.getDevice() == null) return;
final String pathname = getInstrumentation().getTargetContext().
getFilesDir().getPath() + "/TaplTestScreenshot" + sScreenshotCount++ + ".png";
Log.e(TAG, "Failed test " + description.getMethodName() +
", screenshot will be saved to " + pathname +
", track trace is below, UI object dump is further below:\n" +
Log.getStackTraceString(e));
dumpViewHierarchy();
try {
final String dumpsysResult = mAbstractLauncherUiTest.getDevice().executeShellCommand(
"dumpsys activity service TouchInteractionService");
Log.d(TAG, "TouchInteractionService: " + dumpsysResult);
} catch (IOException ex) {
}
mAbstractLauncherUiTest.getDevice().takeScreenshot(new File(pathname));
}
}
@@ -59,6 +59,7 @@ public class Background extends LauncherInstrumentation.VisibleContainer {
}
protected void goToOverviewUnchecked(int expectedState) {
mLauncher.getTestInfo(TestProtocol.REQUEST_ENABLE_DEBUG_TRACING);
switch (mLauncher.getNavigationModel()) {
case ZERO_BUTTON: {
final int centerX = mLauncher.getDevice().getDisplayWidth() / 2;
@@ -103,6 +104,7 @@ public class Background extends LauncherInstrumentation.VisibleContainer {
mLauncher.waitForSystemUiObject("recent_apps").click();
break;
}
mLauncher.getTestInfo(TestProtocol.REQUEST_DISABLE_DEBUG_TRACING);
}
protected String getSwipeHeightRequestName() {